创建类似目录树

时间:2018-02-02 15:37:42

标签: c++ winapi wxwidgets windows-shell

目前,我正在使用wxWidgets的wxGenericDirCtrl,它为我提供了目录树的用户界面。它看起来像这样:

wxGenericDirCtrl

但是,我希望它看起来像这样:

Windows Explorer directory tree

与wxWidgets开发人员交谈时,他们建议继续进行的一个好方法是修改wxGenericDirCtrl类以使用本机Windows目录控件。我想自己将此功能贡献给wxWidgets,但我不知道从哪里开始,并且可以使用一些建议让我开始。

问题:

  1. 在C ++中创建这样一个控件的正确原生方法是什么。我是否使用MFC,.NET或其他东西?
  2. 是否有任何关键字可以帮助我找到这些信息?
  3. 是否有示例代码显示如何执行此操作?

3 个答案:

答案 0 :(得分:3)

自Windows Vista以来,创建类似目录树的窗口资源管理器(称为“shell命名空间树控件”)变得非常容易。可以通过名为INameSpaceTreeControl的COM类创建此控件。 Windows 7添加了此类的更新版本,名为INameSpaceTreeControl2

可以从父窗口的WM_CREATE处理程序调用以下示例代码。它创建一个名称空间树控件,其根目录设置为桌面文件夹。其他根文件夹也是可能的,甚至可以插入多个根。

#include <ShlObj.h>   //Shell COM API
#include <atlbase.h>  //CComPtr

static CComPtr<INameSpaceTreeControl> pTree;
if( SUCCEEDED( pTree.CoCreateInstance( CLSID_NamespaceTreeControl ) ) )
{
    RECT rc{ 0, 0, 444, 333 }; // Client coordinates of the tree control
    if( SUCCEEDED( pTree->Initialize( hWndParent, &rc, 
            NSTCS_HASEXPANDOS | NSTCS_AUTOHSCROLL | NSTCS_FADEINOUTEXPANDOS ) ) )
    {
        CComPtr<IShellItem> pItem;
        if( SUCCEEDED( SHCreateItemInKnownFolder( FOLDERID_Desktop, 0, nullptr, 
                                                  IID_PPV_ARGS( &pItem ) ) ) )
        {
            pTree->AppendRoot( pItem, SHCONTF_FOLDERS, NSTCRS_EXPANDED, nullptr );
        }
    }
}

当父窗口被销毁时,通常在父窗口的Release()处理程序中调用COM对象的WM_DESTROY方法来销毁命名空间树控件:

pTree.Release();  // Releases the COM object and sets the pointer to nullptr

在启动程序时不要忘记CoInitialize(nullptr),在关机前忘记CoUninitialize()

答案 1 :(得分:0)

wxWidgets不使用MFC,.NET或Windows上的任何其他高级库。只是基本的系统API(libs kernel32,winspool,comctl32等)。 OSX也是如此,使用操作系统提供的API。在Linux中没有这样的“基本API”,因此wxWidgets使用GTK +。

您已经拥有要搜索的关键字: explorer like control

wxGenericDirCtrlGetTreeCtrl()个成员。然后,只需将图像添加到节点,例如wxTreeCtrl::AssignButtonsImageList()。见wx docs

答案 2 :(得分:0)

<强> ExplorerApp.h

    #ifndef EXPLORERAPP_H
#define EXPLORERAPP_H

#include <wx/app.h>

class ExplorerApp : public wxApp
{
    public:
        virtual bool OnInit();
};

#endif // EXPLORERAPP_H

<强> ExplorerApp.cpp

#include "ExplorerApp.h"

//(*AppHeaders
#include "ExplorerMain.h"
#include <wx/image.h>
//*)

IMPLEMENT_APP(ExplorerApp);

bool ExplorerApp::OnInit()
{
    //(*AppInitialize
    bool wxsOK = true;
    wxInitAllImageHandlers();
    if ( wxsOK )
    {
        ExplorerFrame* Frame = new ExplorerFrame(0);
        Frame->Show();
        SetTopWindow(Frame);
    }
    //*)
    return wxsOK;

}

<强> ExplorerMain.h

#ifndef EXPLORERMAIN_H
#define EXPLORERMAIN_H

#include<wx/imaglist.h>
#include<wx/artprov.h>
#include<wx/dir.h>
////(*Headers(ExplorerFrame)
  #include <wx/treectrl.h>
  #include <wx/textctrl.h>
  #include <wx/button.h>
  #include <wx/dirdlg.h>
  #include <wx/frame.h>
  //*)

class ExplorerFrame: public wxFrame
{
    public:

        ExplorerFrame(wxWindow* parent,wxWindowID id = -1);
        virtual ~ExplorerFrame();

    private:

        ////(*Handlers(ExplorerFrame)
          void OnQuit(wxCommandEvent& event);
          void OnAbout(wxCommandEvent& event);
          void OnButton1Click(wxCommandEvent& event);
          void findir(wxTreeItemId,wxString);
          //*)

        ////(*Identifiers(ExplorerFrame)
          static const long ID_TEXTCTRL1;
          static const long ID_BUTTON1;
          static const long ID_CUSTOM1;
          //*)

        ////(*Declarations(ExplorerFrame)
          wxButton* Button1;
          wxDirDialog* DirDialog1;
          wxTextCtrl* TextCtrl1;
          wxTreeCtrl* Mytreectrl;
          //*)

        wxImageList* myimageliste;
        wxTreeItemId root;
        wxTreeItemId Child1;
        wxTreeItemId Child2;
        wxTreeItemId Child3;

        DECLARE_EVENT_TABLE()
};

#endif // EXPLORERMAIN_H

<强> ExplorerMain.cpp

#include "ExplorerMain.h"
#include <wx/msgdlg.h>

////(*InternalHeaders(ExplorerFrame)
#include <wx/intl.h>
#include <wx/string.h>
//*)

//helper functions
enum wxbuildinfoformat {
    short_f, long_f };

wxString wxbuildinfo(wxbuildinfoformat format)
{
    wxString wxbuild(wxVERSION_STRING);

    if (format == long_f )
    {
#if defined(__WXMSW__)
        wxbuild << _T("-Windows");
#elif defined(__UNIX__)
        wxbuild << _T("-Linux");
#endif

#if wxUSE_UNICODE
        wxbuild << _T("-Unicode build");
#else
        wxbuild << _T("-ANSI build");
#endif // wxUSE_UNICODE
    }

    return wxbuild;
}

//(*IdInit(ExplorerFrame)
const long ExplorerFrame::ID_TEXTCTRL1 = wxNewId();
const long ExplorerFrame::ID_BUTTON1 = wxNewId();
const long ExplorerFrame::ID_CUSTOM1 = wxNewId();
//*)

BEGIN_EVENT_TABLE(ExplorerFrame,wxFrame)
    //(*EventTable(ExplorerFrame)
    //*)
END_EVENT_TABLE()

ExplorerFrame::ExplorerFrame(wxWindow* parent,wxWindowID id)
{
    ////(*Initialize(ExplorerFrame)
      Create(parent, id, _("wxTreeCtrl"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
      SetClientSize(wxSize(400,298));
      TextCtrl1 = new wxTextCtrl(this, ID_TEXTCTRL1, _("C:/"), wxPoint(32,16), wxSize(240,22), 0, wxDefaultValidator, _T("ID_TEXTCTRL1"));
      Button1 = new wxButton(this, ID_BUTTON1, _("Browse"), wxPoint(320,16), wxDefaultSize, 0, wxDefaultValidator, _T("ID_BUTTON1"));
      Mytreectrl = new wxTreeCtrl(this,ID_CUSTOM1,wxPoint(24,56),wxSize(352,224),wxTR_HAS_BUTTONS,wxDefaultValidator,_T("ID_CUSTOM1"));
      DirDialog1 = new wxDirDialog(this, _("Select directory"), wxEmptyString, wxDD_DEFAULT_STYLE, wxDefaultPosition, wxDefaultSize, _T("wxDirDialog"));
      Center();

      Connect(ID_BUTTON1,wxEVT_COMMAND_BUTTON_CLICKED,(wxObjectEventFunction)&ExplorerFrame::OnButton1Click);
      //*)

    myimageliste = new wxImageList(16,16);
    myimageliste->Add(wxArtProvider::GetBitmap(wxART_FOLDER,wxART_OTHER,wxSize(16,16)));
    myimageliste->Add(wxArtProvider::GetBitmap(wxART_REPORT_VIEW,wxART_OTHER,wxSize(16,16)));

    Mytreectrl->AssignImageList(myimageliste);

    root = Mytreectrl->AddRoot(_T("Root"),0);
    /*Child1 = Mytreectrl->AppendItem(root,_T("Folder 1"),0);
    Mytreectrl->AppendItem(Child1,_T("My folder 11"),1);
    Mytreectrl->AppendItem(Child1,_T("My folder 12"),1);
    Mytreectrl->AppendItem(Child1,_T("My folder 13"),1);

    Child2 = Mytreectrl->AppendItem(root,_T("Folder 2"),0);
    Mytreectrl->AppendItem(Child2,_T("My folder 21"),1);
    Mytreectrl->AppendItem(Child2,_T("My folder 22"),1);
    Mytreectrl->AppendItem(Child2,_T("My folder 23"),1);

    Child3 = Mytreectrl->AppendItem(root,_T("Folder 3"),0);
    Mytreectrl->ExpandAll();*/
    //findir(root,"C:\\");
}

ExplorerFrame::~ExplorerFrame()
{
    //(*Destroy(ExplorerFrame)
    //*)
}

void ExplorerFrame::OnQuit(wxCommandEvent& event)
{
    Close();
}

void ExplorerFrame::OnAbout(wxCommandEvent& event)
{
    wxString msg = wxbuildinfo(long_f);
    wxMessageBox(msg, _("Welcome to..."));
}

void ExplorerFrame::findir(wxTreeItemId id,wxString path){
    wxDir mydir;
    //DirDialog1->SetPath(_T("C://"));
    bool isopen = false;
    //int dir = DirDialog1->ShowModal();
   // if(dir == wxID_OK){
    //TextCtrl1->SetValue(DirDialog1->GetPath());
    //Mytreectrl->DeleteChildren(root);
    //Mytreectrl->SetItemText(root,DirDialog1->GetPath());
    isopen = mydir.Open(path);
    //}

    wxString filename;
    bool cont = false;
    bool con = false;

    if(isopen){
        con = mydir.GetFirst(&filename,wxEmptyString,wxDIR_DIRS);
    }

    int handleforfiles = 0;
    while(con and isopen){
        wxTreeItemId ids = Mytreectrl->AppendItem(id,filename,0);
        //wxMessageBox(path+filename,path+'\\'+filename);
        if(handleforfiles >= 150){
            //wxMessageBox(_T("The Max File limit reached"),_T("The Max File limit reached"));
            break;
        }
        findir(ids,path+'\\'+filename);
        con = mydir.GetNext(&filename);
        ++handleforfiles;
    }

    if(isopen){
        cont = mydir.GetFirst(&filename,wxEmptyString,wxDIR_FILES);
    }

    handleforfiles = 0;

    while(cont and isopen){
        Mytreectrl->AppendItem(id,filename,1);
        if(handleforfiles >= 150){
            //wxMessageBox(_T("The Max File limit reached"),_T("The Max File limit reached"));
            break;
        }
        cont = mydir.GetNext(&filename);
        ++handleforfiles;
    }
}

void ExplorerFrame::OnButton1Click(wxCommandEvent& event)
{
    //wxDir mydir;
    DirDialog1->SetPath(_T("C://"));
    //bool isopen = false;
    int dir = DirDialog1->ShowModal();
    if(dir == wxID_OK){
        TextCtrl1->SetValue(DirDialog1->GetPath());
        Mytreectrl->DeleteChildren(root);
        Mytreectrl->SetItemText(root,DirDialog1->GetPath());
        //isopen = mydir.Open(DirDialog1->GetPath());
        findir(root,DirDialog1->GetPath());
    }
}