MyComputer を List View に表示する


Shell Folder で MyComputer と Desk Top を List View に表示します。
Shell Folder(LPSHELLFOLDER) は、エクスプローラのような Shell を作成するための専用の API です。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. 新規プロジェクトで(MyComp)を作成します。
    プロジェクトの作成は Directry を List View に表示する に順じます。
  2. フォルダーに Shell.c を格納して [プロジェクトへ追加][ファイル] からプロジェクトに取り込んで下さい。
    Shell.c のソースコードは、この後で説明します。
  3. DeskTop.cpp の説明です。
    commctrl.h をインクルードして、#pragma comment(lib,"comctl32.lib") を記述します。
    hList は List View のハンドルです。
    extern "c" 以降は、C言語で作成された関数を C++ で使用するときの関数の宣言です。
        #include    <commctrl.h>
        #include    "resource.h"
        #pragma     comment(lib,"comctl32.lib")
    
        HWND        hList;
    
        extern  "C" /* Assume C declarations for C++ */
        {       void    ViewMyComp(HWND hList);
                void    ShellEnd();
        }
        
  4. WinMain() では DialogBox を表示するだけです。
    Dialog Box CALLBACK 関数の WM_INITDIALOG: の記述です。
    ListView のハンドルをパラメータにして ViewMyComp() を呼びます。
        case WM_INITDIALOG:
            hList= GetDlgItem(hDlg,IDC_LIST1);
            ViewMyComp(hList);
            break;
        
  5. WM_CLOSE: で最後の後始末をする ShellEnd() を実行して下さい。
        case WM_CLOSE:
            ShellEnd();
            EndDialog(hDlg, TRUE);
            break;
        
  6. List View に Desk Top フォルダーを登録するソースコード Shell.c です。
    ソースコードは、C言語に対応しているので拡張子は「.C」にして下さい。
    ShellEnd() が最後の後始末をする関数です。
    /*********************************************/
    /*★ Shell Object   IShellFolder   前田 稔 ★*/
    /*********************************************/
    #include    <windows.h>
    #include    <shlobj.h>
    
    // Defines, constants, and global variables
    LPSHELLFOLDER   g_lpShell=  NULL;
    LPSHELLFOLDER   my_lpShell= NULL;
    HIMAGELIST      g_hSmall= NULL;
    
    // List View Test Data
    char    HEAD[][16]=
    {  "名前", "サイズ", "ファイルの種類", "更新日付"  };
    int     CX[]=  {  180, 80, 160, 120 };
    
    //★ Shell Object の終了
    void    ShellEnd()
    {    if (g_lpShell)     g_lpShell->lpVtbl->Release(g_lpShell);
         if (my_lpShell)    my_lpShell->lpVtbl->Release(my_lpShell);
         if (g_hSmall)      ImageList_Destroy(g_hSmall);
    }
    
    //★ LPCITEMIDLIST のサイズを調べる
    UINT GetSize(LPCITEMIDLIST pidl)
    {   UINT    cbTotal = 0;
        LPSTR   lpMem;
        if (pidl)
        {   cbTotal += sizeof(pidl->mkid.cb);       // Null terminator
            while (pidl->mkid.cb)
            {   cbTotal += pidl->mkid.cb;
                lpMem= (LPSTR)pidl;
                lpMem+= pidl->mkid.cb;
                pidl= (LPITEMIDLIST)lpMem;
            }
        }
        return cbTotal;
    }
    
    //★ LPCITEMIDLIST 同士を結合する
    LPITEMIDLIST ConcatPidls(LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2)
    {   LPITEMIDLIST    pidlNew= 0;
        UINT            cb1;
        UINT            cb2;
        LPMALLOC        lpMalloc;
        HRESULT         hr;
    
        if (pidl1)  cb1 = GetSize(pidl1)-sizeof(pidl1->mkid.cb);
        else        cb1 = 0;
        cb2 = GetSize(pidl2);
        hr= SHGetMalloc(&lpMalloc);
        if (FAILED(hr)) return  pidlNew;
        pidlNew= (LPITEMIDLIST)lpMalloc->lpVtbl->Alloc(lpMalloc, cb1+cb2);
        if (pidlNew)    memset(pidlNew,0,cb1+cb2);      //zero-init
        if (lpMalloc)   lpMalloc->lpVtbl->Release(lpMalloc);
        if (pidlNew)
        {  if (pidl1)   memcpy(pidlNew,pidl1,cb1);
           memcpy(((LPSTR)pidlNew)+cb1,pidl2,cb2);
        }
        return  pidlNew;
    }
        
  7. SetView() が List View に Desk Top フォルダーを登録する関数です。
    //★ ListView を表示する
    int SetView(HWND hList, LPSHELLFOLDER lpShell, LPITEMIDLIST lpFolderIDL)
    {   LV_ITEM         LVItem;
        int             iCtr;
        HWND            hWndParent;
        LPITEMIDLIST    lpItem=NULL;
        LPITEMIDLIST    lpItemAll=NULL;
        LPENUMIDLIST    lpEnum=NULL;
        ULONG           ulFetched;
        SHFILEINFO      sfi; 
        LPMALLOC        lpMalloc;
        HRESULT         hr;
        WIN32_FIND_DATA fd;
        FILETIME        ft;
        SYSTEMTIME      sTime;
        char            buf[64];
    
        hWndParent= GetParent(hList);     //親ウインドウのハンドル
        //lpEnum ← ファイル列挙するためのインターフェースを取得
        hr= lpShell->lpVtbl->EnumObjects(lpShell, hWndParent,
                SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN,&lpEnum);
        if (!SUCCEEDED(hr))     return  0;
        LVItem.mask= LVIF_TEXT | LVIF_IMAGE;
        iCtr = 0;
        //lpItem ← ファイルのアイテムIDリストを取得
        while(S_OK==lpEnum->lpVtbl->Next(lpEnum,1,&lpItem,&ulFetched))
        {   //リストビューへアイテムの挿入
            lpItemAll= ConcatPidls(lpFolderIDL, lpItem);
            SHGetFileInfo((LPCSTR)lpItemAll,0,&sfi,sizeof(SHFILEINFO),
                 SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON |
                 SHGFI_DISPLAYNAME | SHGFI_TYPENAME);
            hr= SHGetMalloc(&lpMalloc);
            lpMalloc->lpVtbl->Free(lpMalloc,lpItemAll);
            lpMalloc->lpVtbl->Release(lpMalloc);
            // ファイル名を表示
                   :
            // WIN32_FIND_DATA を取得
            hr=SHGetDataFromIDList(lpShell,lpItem,SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA));
            if (!FAILED(hr))
            {   // ファイルサイズを表示
                if (!(fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
                {      :
                }
                // 日付と作成時刻を表示
                if (!(fd.dwFileAttributes&FILE_ATTRIBUTE_SYSTEM))
                {      :
                }
            }
            // ファイルの種類を表示
            LVItem.pszText     = sfi.szTypeName;
            LVItem.iSubItem    = 2;
            ListView_SetItem(hList, &LVItem);
        }
        if (lpEnum)     lpEnum->lpVtbl->Release(lpEnum);
        return iCtr;
    }
        
  8. ViewMyComp() が DeskTop フォルダーを取得する関数です。
    Column を設定する方法は前回と同じです。
    現在のソースコードでは MyComputer が表示されます。
    DesktopFolder を表示するときは、行の先頭のコメント(//) を解除して下さい。
    //★ List View MyComp を表示する
    void  ViewMyComp(HWND hList)
    {   LV_COLUMN       LVcol;
        int             i;
        LPITEMIDLIST    lpItem=NULL;
        LPENUMIDLIST    lpEnum=NULL;
        SHFILEINFO      sfi; 
        HWND            hWndParent;
        HRESULT         hr;
        ULONG           ulFetched;
    
        // ImageList の設定
        g_hSmall= (HIMAGELIST)SHGetFileInfo((LPCSTR)"C:\\",0,&sfi,sizeof(SHFILEINFO),
                              SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
        if (g_hSmall)
            ListView_SetImageList(hList,g_hSmall,LVSIL_SMALL);
    
        // Column の項目設定
            :
            :
        //g_lpShell ← DesktopFolder の IShellFolder を取得
        SHGetDesktopFolder(&g_lpShell);
    //SetView(hList,g_lpShell,NULL);  return;   //☆DesktopFolder を表示するとき
        hWndParent= GetParent(hList);           //親ウインドウのハンドル
        //lpEnum ← ファイル列挙するためのインターフェースを取得
        hr= g_lpShell->lpVtbl->EnumObjects(g_lpShell, hWndParent,
                SHCONTF_FOLDERS|SHCONTF_NONFOLDERS|SHCONTF_INCLUDEHIDDEN,&lpEnum);
        if (!SUCCEEDED(hr))     return;
        //最初に見つかるのが MyComputer
        lpEnum->lpVtbl->Next(lpEnum,1,&lpItem,&ulFetched);
        //★サブフォルダーの IShellFolder を取得する
        g_lpShell->lpVtbl->BindToObject(g_lpShell,lpItem,0,&IID_IShellFolder,&my_lpShell);
        //IShellFolder が取得できたので、DeskTop の lpEnum を開放する
        if (lpEnum)  lpEnum->lpVtbl->Release(lpEnum);
        SetView(hList,my_lpShell,lpItem);
    }
        

初心者の方のために全ソースコードを掲載します。 (^_^;)
desktop.cpp のソースコード
shell.c のソースコード

超初心者のプログラム入門(Win32API C++)