Creating a Windows explorer like directory tree

无人久伴 提交于 2019-12-01 10:59:38

Creating a Window Explorer like directory tree (known as "shell namespace tree control") has become quite easy since Windows Vista. This control can be created through a COM class called INameSpaceTreeControl. Windows 7 added a newer version of this class called INameSpaceTreeControl2.

The following sample code could be called from the WM_CREATE handler of the parent window. It creates a namespace tree control that has its root set to the desktop folder. Other root folders are possible, even multiple roots can be inserted.

#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 );
        }
    }
}

Destroy the namespace tree control by calling the Release() method of the COM object when the parent window gets destroyed, typically in the WM_DESTROY handler of the parent window:

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

Don't forget to CoInitialize(nullptr) once at startup of your program and CoUninitialize() before shutdown.

wxWidgets does NOT use MFC, .NET or whatever other high-level library on Windows. Just the basic system API (libs kernel32, winspool, comctl32, etc). Same goes for OSX, using the OS provided API. In Linux there's no such "basic API", and thus wxWidgets uses GTK+.

You already have the keywords to search for: explorer like control.

wxGenericDirCtrl has GetTreeCtrl()member. Then, just add images to nodes, for example by wxTreeCtrl::AssignButtonsImageList(). See wx docs

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());
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!