Dlapi.c
上传用户:tj_dwf
上传日期:2020-11-17
资源大小:215k
文件大小:44k
源码类别:

RichEdit

开发平台:

Visual C++

  1. /******************************************************************************
  2. *
  3. *
  4. * Notepad2
  5. *
  6. * Dlapi.c
  7. *   Directory Listing APIs used in Notepad2
  8. *
  9. * See Readme.txt for more information about this source code.
  10. * Please send me your comments to this work.
  11. *
  12. * See License.txt for details about distribution and modification.
  13. *
  14. *                                              (c) Florian Balmer 1996-2010
  15. *                                                  florian.balmer@gmail.com
  16. *                                               http://www.flos-freeware.ch
  17. *
  18. *
  19. ******************************************************************************/
  20. #define _WIN32_WINNT 0x501
  21. #include <windows.h>
  22. #include <commctrl.h>
  23. #include <shlobj.h>
  24. #include <shlwapi.h>
  25. #include <string.h>
  26. #include "dlapi.h"
  27. //==== Global LPMALLOC instance ===============================================
  28. extern LPMALLOC g_lpMalloc;
  29. //==== DirList ================================================================
  30. //==== DLDATA Structure =======================================================
  31. typedef struct tagDLDATA // dl
  32. {
  33.   HWND hwnd;                 // HWND of ListView Control
  34.   UINT cbidl;                // Size of pidl
  35.   LPITEMIDLIST  pidl;        // Directory Id
  36.   LPSHELLFOLDER lpsf;        // IShellFolder Interface to pidl
  37.   WCHAR szPath[MAX_PATH];     // Pathname to Directory Id
  38.   int iDefIconFolder;        // Default Folder Icon
  39.   int iDefIconFile;          // Default File Icon
  40.   BOOL bNoFadeHidden;        // Flag passed from GetDispInfo()
  41.   HANDLE hExitThread;        // Flag is set when Icon Thread should terminate
  42.   HANDLE hTerminatedThread;  // Flag is set when Icon Thread has terminated
  43. } DLDATA, *LPDLDATA;
  44. //==== Property Name ==========================================================
  45. static const WCHAR *pDirListProp = L"DirListData";
  46. //=============================================================================
  47. //
  48. //  DirList_Init()
  49. //
  50. //  Initializes the DLDATA structure and sets up the listview control
  51. //
  52. BOOL DirList_Init(HWND hwnd,LPCWSTR pszHeader)
  53. {
  54.   HIMAGELIST hil;
  55.   SHFILEINFO shfi;
  56.   LV_COLUMN  lvc;
  57.   // Allocate DirListData Property
  58.   LPDLDATA lpdl = (LPVOID)GlobalAlloc(GPTR,sizeof(DLDATA));
  59.   SetProp(hwnd,pDirListProp,(HANDLE)lpdl);
  60.   // Setup dl
  61.   lpdl->hwnd = hwnd;
  62.   lpdl->cbidl = 0;
  63.   lpdl->pidl = NULL;
  64.   lpdl->lpsf = NULL;
  65.   lstrcpy(lpdl->szPath,L"");
  66.   // Add Imagelists
  67.   hil = (HIMAGELIST)SHGetFileInfo(L"C:\",0,&shfi,sizeof(SHFILEINFO),
  68.                     SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  69.   ListView_SetImageList(hwnd,hil,LVSIL_SMALL);
  70.   hil = (HIMAGELIST)SHGetFileInfo(L"C:\",0,&shfi,sizeof(SHFILEINFO),
  71.                     SHGFI_LARGEICON | SHGFI_SYSICONINDEX);
  72.   ListView_SetImageList(hwnd,hil,LVSIL_NORMAL);
  73.   // Initialize default icons - done in DirList_Fill()
  74.   //SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
  75.   //  SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  76.   //lpdl->iDefIconFolder = shfi.iIcon;
  77.   //SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
  78.   //  SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  79.   //lpdl->iDefIconFile = shfi.iIcon;
  80.   lpdl->iDefIconFolder = 0;
  81.   lpdl->iDefIconFile = 0;
  82.   // Icon thread control
  83.   lpdl->hExitThread = CreateEvent(NULL,TRUE,FALSE,NULL);
  84.   lpdl->hTerminatedThread = CreateEvent(NULL,TRUE,TRUE,NULL);
  85.   lvc;
  86.   pszHeader;
  87.   return TRUE;
  88. }
  89. //=============================================================================
  90. //
  91. //  DirList_Destroy()
  92. //
  93. //  Free memory used by dl structure
  94. //
  95. BOOL DirList_Destroy(HWND hwnd)
  96. {
  97.   //LPMALLOC lpMalloc;
  98.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  99.   // Release multithreading objects
  100.   DirList_TerminateIconThread(hwnd);
  101.   CloseHandle(lpdl->hExitThread);
  102.   CloseHandle(lpdl->hTerminatedThread);
  103.   //if (NOERROR == SHGetMalloc(&lpMalloc))
  104.   //{
  105.     if (lpdl->pidl)
  106.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);
  107.     //lpMalloc->lpVtbl->Release(lpMalloc);
  108.     if (lpdl->lpsf)
  109.       lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
  110.   //}
  111.   // Free DirListData Property
  112.   RemoveProp(hwnd,pDirListProp);
  113.   GlobalFree(lpdl);
  114.   return FALSE;
  115. }
  116. //=============================================================================
  117. //
  118. //  DirList_StartIconThread()
  119. //
  120. //  Start thread to extract file icons in the background
  121. //
  122. BOOL DirList_StartIconThread(HWND hwnd)
  123. {
  124.   DWORD dwtid;
  125.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  126.   DirList_TerminateIconThread(hwnd);
  127.   ResetEvent(lpdl->hExitThread);
  128.   //ResetEvent(lpdl->hTerminatedThread);
  129.   CreateThread(NULL,0,DirList_IconThread,(LPVOID)lpdl,0,&dwtid);
  130.   return TRUE;
  131. }
  132. //=============================================================================
  133. //
  134. //  DirList_TerminateIconThread()
  135. //
  136. //  Terminate Icon Thread and reset multithreading control structures
  137. //
  138. BOOL DirList_TerminateIconThread(HWND hwnd)
  139. {
  140.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  141.   SetEvent(lpdl->hExitThread);
  142.   //WaitForSingleObject(lpdl->hTerminatedThread,INFINITE);
  143.   while (WaitForSingleObject(lpdl->hTerminatedThread,0) != WAIT_OBJECT_0)
  144.   {
  145.     MSG msg;
  146.     if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
  147.       TranslateMessage(&msg);
  148.       DispatchMessage(&msg);
  149.     }
  150.   }
  151.   ResetEvent(lpdl->hExitThread);
  152.   SetEvent(lpdl->hTerminatedThread);
  153.   return TRUE;
  154. }
  155. //=============================================================================
  156. //
  157. //  DirList_Fill()
  158. //
  159. //  Snapshots a directory and displays the items in the listview control
  160. //
  161. int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec,
  162.                  BOOL bExcludeFilter,BOOL bNoFadeHidden,
  163.                  int iSortFlags,BOOL fSortRev)
  164. {
  165.   WCHAR wszDir[MAX_PATH];
  166.   //LPMALLOC lpMalloc = NULL;
  167.   LPSHELLFOLDER lpsfDesktop = NULL;
  168.   LPSHELLFOLDER lpsf = NULL;
  169.   LPITEMIDLIST  pidl = NULL;
  170.   LPITEMIDLIST  pidlEntry = NULL;
  171.   LPENUMIDLIST  lpe = NULL;
  172.   LV_ITEM       lvi;
  173.   LPLV_ITEMDATA lplvid;
  174.   ULONG chParsed = 0;
  175.   ULONG dwAttributes = 0;
  176.   DL_FILTER dlf;
  177.   SHFILEINFO shfi;
  178.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  179.   // Initialize default icons
  180.   SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
  181.     SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  182.   lpdl->iDefIconFolder = shfi.iIcon;
  183.   SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
  184.     SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  185.   lpdl->iDefIconFile = shfi.iIcon;
  186.   // First of all terminate running icon thread
  187.   DirList_TerminateIconThread(hwnd);
  188.   // A Directory is strongly required
  189.   if (!lpszDir || !*lpszDir)
  190.     return(-1);
  191.   lstrcpy(lpdl->szPath,lpszDir);
  192.   // Init ListView
  193.   SendMessage(hwnd,WM_SETREDRAW,0,0);
  194.   ListView_DeleteAllItems(hwnd);
  195.   // Init Filter
  196.   DirList_CreateFilter(&dlf,lpszFileSpec,bExcludeFilter);
  197.   // Init lvi
  198.   lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  199.   lvi.iItem = 0;
  200.   lvi.iSubItem = 0;
  201.   lvi.pszText = LPSTR_TEXTCALLBACK;
  202.   lvi.cchTextMax = MAX_PATH;
  203.   lvi.iImage = I_IMAGECALLBACK;
  204.   // Convert Directory to a UNICODE string
  205.   /*MultiByteToWideChar(CP_ACP,
  206.                       MB_PRECOMPOSED,
  207.                       lpszDir,
  208.                       -1,
  209.                       wszDir,
  210.                       MAX_PATH);*/
  211.   lstrcpy(wszDir,lpszDir);
  212.   // Get Shell's IMalloc Interface
  213.   //if (NOERROR == SHGetMalloc(&lpMalloc))
  214.   //{
  215.     // Get Desktop Folder
  216.     if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
  217.     {
  218.       // Convert wszDir into a pidl
  219.       if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName(
  220.                                             lpsfDesktop,
  221.                                             hwnd,
  222.                                             NULL,
  223.                                             wszDir,
  224.                                             &chParsed,
  225.                                             &pidl,
  226.                                             &dwAttributes))
  227.       {
  228.         // Bind pidl to IShellFolder
  229.         if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
  230.                                               lpsfDesktop,
  231.                                               pidl,
  232.                                               NULL,
  233.                                               &IID_IShellFolder,
  234.                                               &lpsf))
  235.         {
  236.           // Create an Enumeration object for lpsf
  237.           if (NOERROR == lpsf->lpVtbl->EnumObjects(
  238.                                          lpsf,
  239.                                          hwnd,
  240.                                          grfFlags,
  241.                                          &lpe))
  242.           {
  243.             // Enumerate the contents of lpsf
  244.             while (NOERROR == lpe->lpVtbl->Next(
  245.                                              lpe,
  246.                                              1,
  247.                                              &pidlEntry,
  248.                                              NULL))
  249.             {
  250.               // Add found item to the List
  251.               // Check if it's part of the Filesystem
  252.               dwAttributes = SFGAO_FILESYSTEM | SFGAO_FOLDER;
  253.               lpsf->lpVtbl->GetAttributesOf(
  254.                               lpsf,
  255.                               1,
  256.                               &pidlEntry,
  257.                               &dwAttributes);
  258.               if (dwAttributes & SFGAO_FILESYSTEM)
  259.               {
  260.                 // Check if item matches specified filter
  261.                 if (DirList_MatchFilter(lpsf,pidlEntry,&dlf))
  262.                 {
  263.                   lplvid = g_lpMalloc->lpVtbl->Alloc(
  264.                                                 g_lpMalloc,
  265.                                                 sizeof(LV_ITEMDATA));
  266.                   lplvid->pidl = pidlEntry;
  267.                   lplvid->lpsf = lpsf;
  268.                   lpsf->lpVtbl->AddRef(lpsf);
  269.                   lvi.lParam = (LPARAM)lplvid;
  270.                   // Setup default Icon - Folder or File
  271.                   lvi.iImage = (dwAttributes & SFGAO_FOLDER) ?
  272.                     lpdl->iDefIconFolder : lpdl->iDefIconFile;
  273.                   ListView_InsertItem(hwnd,&lvi);
  274.                   lvi.iItem++;
  275.                 }
  276.               }
  277.               //lpMalloc->lpVtbl->Free(lpMalloc,pidlEntry);
  278.             } // IEnumIDList::Next()
  279.             lpe->lpVtbl->Release(lpe);
  280.           } // IShellFolder::EnumObjects()
  281.         } // IShellFolder::BindToObject()
  282.       } // IShellFolder::ParseDisplayName()
  283.       lpsfDesktop->lpVtbl->Release(lpsfDesktop);
  284.     } // SHGetDesktopFolder()
  285.     if (lpdl->pidl)
  286.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdl->pidl);
  287.     if (lpdl->lpsf && lpdl->lpsf->lpVtbl)
  288.       lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
  289.     //lpMalloc->lpVtbl->Release(lpMalloc);
  290.   //} // SHGetMalloc()
  291.   // Set lpdl
  292.   lpdl->cbidl = IL_GetSize(pidl);
  293.   lpdl->pidl = pidl;
  294.   lpdl->lpsf = lpsf;
  295.   lpdl->bNoFadeHidden = bNoFadeHidden;
  296.   // Set column width to fit window
  297.   ListView_SetColumnWidth(hwnd,0,LVSCW_AUTOSIZE_USEHEADER);
  298.   // Sort before display is updated
  299.   DirList_Sort(hwnd,iSortFlags,fSortRev);
  300.   // Redraw Listview
  301.   SendMessage(hwnd,WM_SETREDRAW,1,0);
  302.   // Return number of items in the control
  303.   return (ListView_GetItemCount(hwnd));
  304. }
  305. //=============================================================================
  306. //
  307. //  DirList_IconThread()
  308. //
  309. //  Thread to extract file icons in the background
  310. //
  311. DWORD WINAPI DirList_IconThread(LPVOID lpParam)
  312. {
  313.   HWND hwnd;
  314.   LPDLDATA lpdl;
  315.   LV_ITEM lvi;
  316.   LPLV_ITEMDATA lplvid;
  317.   LPMALLOC lpMalloc;
  318.   IShellIcon* lpshi;
  319.   int iItem = 0;
  320.   int iMaxItem;
  321.   lpdl = (LPDLDATA)lpParam;
  322.   ResetEvent(lpdl->hTerminatedThread);
  323.   // Exit immediately if DirList_Fill() hasn't been called
  324.   if (!lpdl->lpsf) {
  325.     SetEvent(lpdl->hTerminatedThread);
  326.     ExitThread(0);
  327.     return(0);
  328.   }
  329.   hwnd = lpdl->hwnd;
  330.   iMaxItem = ListView_GetItemCount(hwnd);
  331.   CoInitialize(NULL);
  332.   SHGetMalloc(&lpMalloc);
  333.   // Get IShellIcon
  334.   lpdl->lpsf->lpVtbl->QueryInterface(lpdl->lpsf,&IID_IShellIcon,&lpshi);
  335.   while (iItem < iMaxItem && WaitForSingleObject(lpdl->hExitThread,0) != WAIT_OBJECT_0) {
  336.     lvi.iItem = iItem;
  337.     lvi.mask  = LVIF_PARAM;
  338.     if (ListView_GetItem(hwnd,&lvi)) {
  339.       SHFILEINFO shfi;
  340.       LPITEMIDLIST pidl;
  341.       DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;
  342.       lplvid = (LPLV_ITEMDATA)lvi.lParam;
  343.       lvi.mask = LVIF_IMAGE;
  344.       if (!lpshi || NOERROR != lpshi->lpVtbl->GetIconOf(lpshi,lplvid->pidl,GIL_FORSHELL,&lvi.iImage))
  345.       {
  346.         pidl = IL_Create(lpMalloc,lpdl->pidl,lpdl->cbidl,lplvid->pidl,0);
  347.         SHGetFileInfo((LPCWSTR)pidl,0,&shfi,sizeof(SHFILEINFO),SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  348.         lpMalloc->lpVtbl->Free(lpMalloc,pidl);
  349.         lvi.iImage = shfi.iIcon;
  350.       }
  351.       // It proved necessary to reset the state bits...
  352.       lvi.stateMask = 0;
  353.       lvi.state = 0;
  354.       // Link and Share Overlay
  355.       lplvid->lpsf->lpVtbl->GetAttributesOf(
  356.                               lplvid->lpsf,
  357.                               1,&lplvid->pidl,
  358.                               &dwAttributes);
  359.       if (dwAttributes & SFGAO_LINK)
  360.       {
  361.         lvi.mask |= LVIF_STATE;
  362.         lvi.stateMask |= LVIS_OVERLAYMASK;
  363.         lvi.state |= INDEXTOOVERLAYMASK(2);
  364.       }
  365.       if (dwAttributes & SFGAO_SHARE)
  366.       {
  367.         lvi.mask |= LVIF_STATE;
  368.         lvi.stateMask |= LVIS_OVERLAYMASK;
  369.         lvi.state |= INDEXTOOVERLAYMASK(1);
  370.       }
  371.       // Fade hidden/system files
  372.       if (!lpdl->bNoFadeHidden)
  373.       {
  374.         WIN32_FIND_DATA fd;
  375.         if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
  376.                         SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
  377.         {
  378.           if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
  379.               (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
  380.           {
  381.             lvi.mask |= LVIF_STATE;
  382.             lvi.stateMask |= LVIS_CUT;
  383.             lvi.state |= LVIS_CUT;
  384.           }
  385.         }
  386.       }
  387.       lvi.iSubItem = 0;
  388.       ListView_SetItem(hwnd,&lvi);
  389.     }
  390.     iItem++;
  391.   }
  392.   if (lpshi)
  393.     lpshi->lpVtbl->Release(lpshi);
  394.   lpMalloc->lpVtbl->Release(lpMalloc);
  395.   CoUninitialize();
  396.   SetEvent(lpdl->hTerminatedThread);
  397.   ExitThread(0);
  398.   return(0);
  399. }
  400. //=============================================================================
  401. //
  402. //  DirList_GetDispInfo()
  403. //
  404. //  Must be called in response to a WM_NOTIFY/LVN_GETDISPINFO message from
  405. //  the listview control
  406. //
  407. BOOL DirList_GetDispInfo(HWND hwnd,LPARAM lParam,BOOL bNoFadeHidden)
  408. {
  409.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  410.   LV_DISPINFO *lpdi = (LPVOID)lParam;
  411.   LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lpdi->item.lParam;
  412.   // SubItem 0 is handled only
  413.   if (lpdi->item.iSubItem != 0)
  414.     return FALSE;
  415.   // Text
  416.   if (lpdi->item.mask & LVIF_TEXT)
  417.     IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
  418.                       lpdi->item.pszText,lpdi->item.cchTextMax);
  419.   // Image
  420.   //if (lpdi->item.mask & LVIF_IMAGE)
  421.   //{
  422.   //  //LPMALLOC lpMalloc;
  423.   //  SHFILEINFO shfi;
  424.   //  LPITEMIDLIST pidl;
  425.   //  DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;
  426.   //  //if (NOERROR == SHGetMalloc(&lpMalloc))
  427.   //  //{
  428.   //    // Generate Full Qualified pidl
  429.   //    pidl = IL_Create(g_lpMalloc,lpdl->pidl,lpdl->cbidl,lplvid->pidl,0);
  430.   //    SHGetFileInfo((LPCWSTR)pidl,0,&shfi,sizeof(SHFILEINFO),SHGFI_PIDL | SHGFI_SYSICONINDEX);
  431.   //    lpdi->item.iImage = shfi.iIcon;
  432.   //    g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
  433.   //    //lpMalloc->lpVtbl->Release(lpMalloc);
  434.   //  //}
  435.   //  // It proved necessary to reset the state bits...
  436.   //  lpdi->item.stateMask = 0;
  437.   //  lpdi->item.state = 0;
  438.   //  // Link and Share Overlay
  439.   //  lplvid->lpsf->lpVtbl->GetAttributesOf(
  440.   //                          lplvid->lpsf,
  441.   //                          1,&lplvid->pidl,
  442.   //                          &dwAttributes);
  443.   //  if (dwAttributes & SFGAO_LINK)
  444.   //  {
  445.   //    lpdi->item.mask |= LVIF_STATE;
  446.   //    lpdi->item.stateMask |= LVIS_OVERLAYMASK;
  447.   //    lpdi->item.state |= INDEXTOOVERLAYMASK(2);
  448.   //  }
  449.   //  if (dwAttributes & SFGAO_SHARE)
  450.   //  {
  451.   //    lpdi->item.mask |= LVIF_STATE;
  452.   //    lpdi->item.stateMask |= LVIS_OVERLAYMASK;
  453.   //    lpdi->item.state |= INDEXTOOVERLAYMASK(1);
  454.   //  }
  455.   //  // Fade hidden/system files
  456.   //  if (!bNoFadeHidden)
  457.   //  {
  458.   //    WIN32_FIND_DATA fd;
  459.   //    if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
  460.   //                     SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
  461.   //    {
  462.   //      if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
  463.   //          (fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
  464.   //      {
  465.   //        lpdi->item.mask |= LVIF_STATE;
  466.   //        lpdi->item.stateMask |= LVIS_CUT;
  467.   //        lpdi->item.state |= LVIS_CUT;
  468.   //      }
  469.   //    }
  470.   //  }
  471.   //}
  472.   // Set values
  473.   lpdi->item.mask |= LVIF_DI_SETITEM;
  474.   return TRUE;
  475. }
  476. //=============================================================================
  477. //
  478. //  DirList_DeleteItem()
  479. //
  480. //  Must be called in response to a WM_NOTIFY/LVN_DELETEITEM message
  481. //  from the control
  482. //
  483. BOOL DirList_DeleteItem(HWND hwnd,LPARAM lParam)
  484. {
  485.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  486.   LV_ITEM lvi;
  487.   //LPMALLOC lpMalloc;
  488.   NM_LISTVIEW *lpnmlv = (LPVOID)lParam;
  489.   lvi.iItem = lpnmlv->iItem;
  490.   lvi.iSubItem = 0;
  491.   lvi.mask = LVIF_PARAM;
  492.   if (ListView_GetItem(hwnd,&lvi))
  493.   {
  494.     //if (NOERROR == SHGetMalloc(&lpMalloc))
  495.     //{
  496.       // Free mem
  497.       LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lvi.lParam;
  498.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lplvid->pidl);
  499.       lplvid->lpsf->lpVtbl->Release(lplvid->lpsf);
  500.       g_lpMalloc->lpVtbl->Free(g_lpMalloc,lplvid);
  501.       //lpMalloc->lpVtbl->Release(lpMalloc);
  502.       return TRUE;
  503.     //}
  504.   }
  505.   else
  506.     return FALSE;
  507. }
  508. //=============================================================================
  509. //
  510. //  DirList_CompareProc()
  511. //
  512. //  Compares two list items
  513. //
  514. int CALLBACK DirList_CompareProcFw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
  515. {
  516.   HRESULT hr;
  517.   int result;
  518.   LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
  519.   LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
  520.   hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
  521.                                  lplvid1->lpsf,
  522.                                  lFlags,
  523.                                  lplvid1->pidl,
  524.                                  lplvid2->pidl));
  525.   result = (short)(SCODE_CODE(GetScode(hr)));
  526.   if (result != 0 || lFlags == 0)
  527.     return(result);
  528.   hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
  529.                                  lplvid1->lpsf,
  530.                                  0,
  531.                                  lplvid1->pidl,
  532.                                  lplvid2->pidl));
  533.   result = (short)(SCODE_CODE(GetScode(hr)));
  534.   return(result);
  535. }
  536. int CALLBACK DirList_CompareProcRw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
  537. {
  538.   HRESULT hr;
  539.   int result;
  540.   LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
  541.   LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
  542.   hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
  543.                                  lplvid1->lpsf,
  544.                                  lFlags,
  545.                                  lplvid1->pidl,
  546.                                  lplvid2->pidl));
  547.   result = -(short)(SCODE_CODE(GetScode(hr)));
  548.   if (result != 0)
  549.     return(result);
  550.   hr = (lplvid1->lpsf->lpVtbl->CompareIDs(
  551.                                  lplvid1->lpsf,
  552.                                  0,
  553.                                  lplvid1->pidl,
  554.                                  lplvid2->pidl));
  555.   result = -(short)(SCODE_CODE(GetScode(hr)));
  556.   return(result);
  557. }
  558. //=============================================================================
  559. //
  560. //  DirList_Sort()
  561. //
  562. //  Sorts the listview control by the specified order
  563. //
  564. BOOL DirList_Sort(HWND hwnd,int lFlags,BOOL fRev)
  565. {
  566.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  567.   if (fRev)
  568.     return ListView_SortItems(hwnd,DirList_CompareProcRw,lFlags);
  569.   else
  570.     return ListView_SortItems(hwnd,DirList_CompareProcFw,lFlags);
  571. }
  572. //=============================================================================
  573. //
  574. //  DirList_GetItem()
  575. //
  576. //  Copies the data of the specified item in the listview control to a buffer
  577. //
  578. int DirList_GetItem(HWND hwnd,int iItem,LPDLITEM lpdli)
  579. {
  580.   LV_ITEM lvi;
  581.   LPLV_ITEMDATA lplvid;
  582.   ULONG dwAttributes = SFGAO_FILESYSTEM;
  583.   if (iItem == -1)
  584.   {
  585.     if (ListView_GetSelectedCount(hwnd))
  586.       iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
  587.     else
  588.       return(-1);
  589.   }
  590.   lvi.mask = LVIF_PARAM;
  591.   lvi.iItem = iItem;
  592.   lvi.iSubItem = 0;
  593.   if (!ListView_GetItem(hwnd,&lvi))
  594.   {
  595.     if (lpdli->mask & DLI_TYPE)
  596.       lpdli->ntype = DLE_NONE;
  597.     return(-1);
  598.   }
  599.   lplvid = (LPLV_ITEMDATA)lvi.lParam;
  600.   // Filename
  601.   if (lpdli->mask & DLI_FILENAME)
  602.     IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_FORPARSING,
  603.                       lpdli->szFileName,MAX_PATH);
  604.   // Displayname
  605.   if (lpdli->mask & DLI_DISPNAME)
  606.     IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
  607.                       lpdli->szDisplayName,MAX_PATH);
  608.   // Type (File / Directory)
  609.   if (lpdli->mask & DLI_TYPE)
  610.   {
  611.     WIN32_FIND_DATA fd;
  612.     if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
  613.                                        lplvid->pidl,
  614.                                        SHGDFIL_FINDDATA,
  615.                                        &fd,
  616.                                        sizeof(WIN32_FIND_DATA)))
  617.     lpdli->ntype = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
  618.                     DLE_DIR : DLE_FILE;
  619.     /*lplvid->lpsf->lpVtbl->GetAttributesOf(
  620.                             lplvid->lpsf,
  621.                             1,
  622.                             &lplvid->pidl,
  623.                             &dwAttributes);
  624.     lpdli->ntype = (dwAttributes & SFGAO_FOLDER) ? DLE_DIR : DLE_FILE;*/
  625.   }
  626.   return iItem;
  627. }
  628. //=============================================================================
  629. //
  630. //  DirList_GetItemEx()
  631. //
  632. //  Retrieves extended infomration on a dirlist item
  633. //
  634. int DirList_GetItemEx(HWND hwnd,int iItem,LPWIN32_FIND_DATA pfd)
  635. {
  636.   LV_ITEM lvi;
  637.   LPLV_ITEMDATA lplvid;
  638.   if (iItem == -1)
  639.   {
  640.     if (ListView_GetSelectedCount(hwnd))
  641.       iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
  642.     else
  643.       return(-1);
  644.   }
  645.   lvi.mask = LVIF_PARAM;
  646.   lvi.iItem = iItem;
  647.   lvi.iSubItem = 0;
  648.   if (!ListView_GetItem(hwnd,&lvi))
  649.     return(-1);
  650.   lplvid = (LPLV_ITEMDATA)lvi.lParam;
  651.   if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
  652.                                      lplvid->pidl,
  653.                                      SHGDFIL_FINDDATA,
  654.                                      pfd,
  655.                                      sizeof(WIN32_FIND_DATA)))
  656.     return iItem;
  657.   else
  658.     return(-1);
  659. }
  660. //=============================================================================
  661. //
  662. //  DirList_PropertyDlg()
  663. //
  664. //  Shows standard Win95 Property Dlg for selected Item
  665. //
  666. BOOL DirList_PropertyDlg(HWND hwnd,int iItem)
  667. {
  668.   LV_ITEM lvi;
  669.   LPLV_ITEMDATA lplvid;
  670.   LPCONTEXTMENU lpcm;
  671.   CMINVOKECOMMANDINFO cmi;
  672.   BOOL bSuccess = TRUE;
  673.   static const char *lpVerb = "properties";
  674.   if (iItem == -1)
  675.   {
  676.     if (ListView_GetSelectedCount(hwnd))
  677.       iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
  678.     else
  679.       return FALSE;
  680.   }
  681.   lvi.mask = LVIF_PARAM;
  682.   lvi.iItem = iItem;
  683.   lvi.iSubItem = 0;
  684.   if (!ListView_GetItem(hwnd,&lvi))
  685.     return FALSE;
  686.   lplvid = (LPLV_ITEMDATA)lvi.lParam;
  687.   if (NOERROR == lplvid->lpsf->lpVtbl->GetUIObjectOf(
  688.                                          lplvid->lpsf,
  689.                                          GetParent(hwnd),  // Owner
  690.                                          1,                // Number of objects
  691.                                          &lplvid->pidl,    // pidl
  692.                                          &IID_IContextMenu,
  693.                                          NULL,
  694.                                          &lpcm))
  695.   {
  696.     cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
  697.     cmi.fMask = 0;
  698.     cmi.hwnd = GetParent(hwnd);
  699.     cmi.lpVerb = lpVerb;
  700.     cmi.lpParameters = NULL;
  701.     cmi.lpDirectory = NULL;
  702.     cmi.nShow = SW_SHOWNORMAL;
  703.     cmi.dwHotKey = 0;
  704.     cmi.hIcon = NULL;
  705.     if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
  706.       bSuccess = FALSE;
  707.     lpcm->lpVtbl->Release(lpcm);
  708.   }
  709.   else
  710.     bSuccess = FALSE;
  711.   return(bSuccess);
  712. }
  713. //=============================================================================
  714. //
  715. //  DirList_DoDragDrop()
  716. //
  717. //  Execute an OLE Drag & Drop Operation in response to LVN_BEGIN(R)DRAG
  718. //
  719. //extern LPDROPSOURCE CreateDropSource();
  720. void DirList_DoDragDrop(HWND hwnd,LPARAM lParam)
  721. {
  722.   //LV_ITEM lvi;
  723.   //LPLV_ITEMDATA lplvid;
  724.   //LPDATAOBJECT lpdo;
  725.   //LPDROPSOURCE lpds;
  726.   //DWORD dwEffect;
  727.   //NM_LISTVIEW *pnmlv = (LPVOID)lParam;
  728.   //lvi.iItem = pnmlv->iItem;
  729.   //lvi.iSubItem = 0;
  730.   //lvi.mask = LVIF_PARAM;
  731.   //if (ListView_GetItem(hwnd,&lvi))
  732.   //{
  733.   //  lplvid = (LPLV_ITEMDATA)lvi.lParam;
  734.   //  if (SUCCEEDED(lplvid->lpsf->lpVtbl->GetUIObjectOf(
  735.   //                                        lplvid->lpsf,
  736.   //                                        GetParent(hwnd),
  737.   //                                        1,
  738.   //                                        &lplvid->pidl,
  739.   //                                        &IID_IDataObject,
  740.   //                                        NULL,
  741.   //                                        &lpdo)))
  742.   //  {
  743.   //    lpds = CreateDropSource();
  744.   //    DoDragDrop(lpdo,lpds,DROPEFFECT_COPY|DROPEFFECT_MOVE|DROPEFFECT_LINK,&dwEffect);
  745.   //    lpdo->lpVtbl->Release(lpdo);
  746.   //    lpds->lpVtbl->Release(lpds);
  747.   //  }
  748.   //}
  749. }
  750. //=============================================================================
  751. //
  752. //  DirList_GetLongPathName()
  753. //
  754. //  Get long pathname for currently displayed directory
  755. //
  756. BOOL DirList_GetLongPathName(HWND hwnd,LPWSTR lpszLongPath)
  757. {
  758.   WCHAR tch[MAX_PATH];
  759.   LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
  760.   if (SHGetPathFromIDList(lpdl->pidl,tch))
  761.   {
  762.     lstrcpy(lpszLongPath,tch);
  763.     return(TRUE);
  764.   }
  765.   else
  766.     return(FALSE);
  767. }
  768. //=============================================================================
  769. //
  770. //  DirList_SelectItem()
  771. //
  772. //  Select specified item in the list
  773. //
  774. BOOL DirList_SelectItem(HWND hwnd,LPCWSTR lpszDisplayName,LPCWSTR lpszFullPath)
  775. {
  776.   #define LVIS_FLAGS LVIS_SELECTED|LVIS_FOCUSED
  777.   WCHAR szShortPath[MAX_PATH];
  778.   SHFILEINFO  shfi;
  779.   LV_FINDINFO lvfi;
  780.   DLITEM dli;
  781.   int i = -1;
  782.   if (!lpszFullPath || !lstrlen(lpszFullPath))
  783.     return(FALSE);
  784.   else
  785.     GetShortPathName(lpszFullPath,szShortPath,MAX_PATH);
  786.   if (!lpszDisplayName || !lstrlen(lpszDisplayName))
  787.     SHGetFileInfo(lpszFullPath,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME);
  788.   else
  789.     lstrcpyn(shfi.szDisplayName,lpszDisplayName,MAX_PATH);
  790.   lvfi.flags = LVFI_STRING;
  791.   lvfi.psz   = shfi.szDisplayName;
  792.   dli.mask = DLI_ALL;
  793.   while ((i = ListView_FindItem(hwnd,i,&lvfi)) != -1)
  794.   {
  795.     DirList_GetItem(hwnd,i,&dli);
  796.     GetShortPathName(dli.szFileName,dli.szFileName,MAX_PATH);
  797.     if (!lstrcmpi(dli.szFileName,szShortPath))
  798.     {
  799.       ListView_SetItemState(hwnd,i,LVIS_FLAGS,LVIS_FLAGS);
  800.       ListView_EnsureVisible(hwnd,i,FALSE);
  801.       return(TRUE);
  802.     }
  803.   }
  804.   return(FALSE);
  805. }
  806. //=============================================================================
  807. //
  808. //  DirList_CreateFilter()
  809. //
  810. //  Create a valid DL_FILTER structure
  811. //
  812. void DirList_CreateFilter(PDL_FILTER pdlf,LPCWSTR lpszFileSpec,
  813.                           BOOL bExcludeFilter)
  814. {
  815.   WCHAR *p;
  816.   ZeroMemory(pdlf,sizeof(DL_FILTER));
  817.   lstrcpyn(pdlf->tFilterBuf,lpszFileSpec,(DL_FILTER_BUFSIZE-1));
  818.   pdlf->bExcludeFilter = bExcludeFilter;
  819.   if (!lstrcmp(lpszFileSpec,L"*.*") || !lstrlen(lpszFileSpec))
  820.     return;
  821.   pdlf->nCount = 1;
  822.   pdlf->pFilter[0] = &pdlf->tFilterBuf[0];    // Zeile zum Ausprobieren
  823.   while (p = StrChr(pdlf->pFilter[pdlf->nCount-1],L';'))
  824.   {
  825.     *p = L'';                              // Replace L';' by L''
  826.     pdlf->pFilter[pdlf->nCount] = (p + 1);  // Next position after L';'
  827.     pdlf->nCount++;                         // Increase number of filters
  828.   }
  829. }
  830. //=============================================================================
  831. //
  832. //  DirList_MatchFilter()
  833. //
  834. //  Check if a specified item matches a given filter
  835. //
  836. BOOL DirList_MatchFilter(LPSHELLFOLDER lpsf,LPCITEMIDLIST pidl,PDL_FILTER pdlf)
  837. {
  838.   int i;
  839.   WIN32_FIND_DATA fd;
  840.   BOOL bMatchSpec;
  841.   // Immediately return true if lpszFileSpec is *.* or NULL
  842.   if (pdlf->nCount == 0 && !pdlf->bExcludeFilter)
  843.     return TRUE;
  844.   SHGetDataFromIDList(lpsf,pidl,SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA));
  845.   // All the directories are added
  846.   if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  847.     return(TRUE);
  848.   // Check if exclude *.* after directories have been added
  849.   if (pdlf->nCount == 0 && pdlf->bExcludeFilter)
  850.     return FALSE;
  851.   for (i = 0; i < pdlf->nCount; i++)
  852.   {
  853.     if (*pdlf->pFilter[i]) // Filters like L"" are ignored
  854.     {
  855.       bMatchSpec = PathMatchSpec(fd.cFileName,pdlf->pFilter[i]);
  856.       if (bMatchSpec)
  857.       {
  858.         if (!pdlf->bExcludeFilter)
  859.           return(TRUE);
  860.         else
  861.           return(FALSE);
  862.       }
  863.     }
  864.   }
  865.   // No matching
  866.   return(pdlf->bExcludeFilter)?TRUE:FALSE;
  867. }
  868. //==== DriveBox ===============================================================
  869. //=============================================================================
  870. //
  871. //  Internal Itemdata Structure
  872. //
  873. typedef struct tagDC_ITEMDATA
  874. {
  875.   LPITEMIDLIST  pidl;
  876.   LPSHELLFOLDER lpsf;
  877. } DC_ITEMDATA, *LPDC_ITEMDATA;
  878. //=============================================================================
  879. //
  880. //  DriveBox_Init()
  881. //
  882. //  Initializes the drive box
  883. //
  884. BOOL DriveBox_Init(HWND hwnd)
  885. {
  886.   HIMAGELIST hil;
  887.   SHFILEINFO shfi;
  888.   hil = (HIMAGELIST)SHGetFileInfo(L"C:\",0,&shfi,sizeof(SHFILEINFO),
  889.                                   SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
  890.   SendMessage(hwnd,CBEM_SETIMAGELIST,0,(LPARAM)hil);
  891.   SendMessage(hwnd,CBEM_SETEXTENDEDSTYLE,CBES_EX_NOSIZELIMIT,CBES_EX_NOSIZELIMIT);
  892.   return TRUE;
  893. }
  894. //=============================================================================
  895. //
  896. //  DriveBox_Fill
  897. //
  898. int DriveBox_Fill(HWND hwnd)
  899. {
  900.   //LPMALLOC lpMalloc;
  901.   LPSHELLFOLDER lpsfDesktop;
  902.   LPSHELLFOLDER lpsf; // Workspace == CSIDL_DRIVES
  903.   LPITEMIDLIST  pidl;
  904.   LPITEMIDLIST  pidlEntry;
  905.   LPENUMIDLIST  lpe;
  906.   COMBOBOXEXITEM  cbei;
  907.   LPDC_ITEMDATA   lpdcid;
  908.   ULONG dwAttributes = 0;
  909.   DWORD grfFlags = SHCONTF_FOLDERS;
  910.   // Init ComboBox
  911.   SendMessage(hwnd,WM_SETREDRAW,0,0);
  912.   SendMessage(hwnd,CB_RESETCONTENT,0,0);
  913.   ZeroMemory(&cbei,sizeof(COMBOBOXEXITEM));
  914.   cbei.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_LPARAM;
  915.   cbei.pszText = LPSTR_TEXTCALLBACK;
  916.   cbei.cchTextMax = MAX_PATH;
  917.   cbei.iImage = I_IMAGECALLBACK;
  918.   cbei.iSelectedImage = I_IMAGECALLBACK;
  919.   // Get Shell's IMalloc Interface
  920.   //if (NOERROR == SHGetMalloc(&lpMalloc))
  921.   //{
  922.     // Get pidl to [My Computer]
  923.     if (NOERROR == SHGetSpecialFolderLocation(hwnd,
  924.                                               CSIDL_DRIVES,
  925.                                               &pidl))
  926.     {
  927.       // Get Desktop Folder
  928.       if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
  929.       {
  930.         // Bind pidl to IShellFolder
  931.         if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
  932.                                               lpsfDesktop,
  933.                                               pidl,
  934.                                               NULL,
  935.                                               &IID_IShellFolder,
  936.                                               &lpsf))
  937.         {
  938.           // Create an Enumeration object for lpsf
  939.           if (NOERROR == lpsf->lpVtbl->EnumObjects(
  940.                                          lpsf,
  941.                                          hwnd,
  942.                                          grfFlags,
  943.                                          &lpe))
  944.           {
  945.             // Enumerate the contents of [My Computer]
  946.             while (NOERROR == lpe->lpVtbl->Next(
  947.                                              lpe,
  948.                                              1,
  949.                                              &pidlEntry,
  950.                                              NULL))
  951.             {
  952.               // Add item to the List if it is part of the
  953.               // Filesystem
  954.               dwAttributes = SFGAO_FILESYSTEM;
  955.               lpsf->lpVtbl->GetAttributesOf(
  956.                               lpsf,
  957.                               1,
  958.                               &pidlEntry,
  959.                               &dwAttributes);
  960.               if (dwAttributes & SFGAO_FILESYSTEM)
  961.               {
  962.                 // Windows XP: check if pidlEntry is a drive
  963.                 SHDESCRIPTIONID di;
  964.                 HRESULT hr;
  965.                 hr = SHGetDataFromIDList(lpsf,pidlEntry,SHGDFIL_DESCRIPTIONID,
  966.                                          &di,sizeof(SHDESCRIPTIONID));
  967.                 if (hr != NOERROR || (di.dwDescriptionId >= SHDID_COMPUTER_DRIVE35 &&
  968.                                       di.dwDescriptionId <= SHDID_COMPUTER_OTHER))
  969.                 {
  970.                   lpdcid = g_lpMalloc->lpVtbl->Alloc(
  971.                                                 g_lpMalloc,
  972.                                                 sizeof(DC_ITEMDATA));
  973.                   //lpdcid->pidl = IL_Copy(lpMalloc,pidlEntry);
  974.                   lpdcid->pidl = pidlEntry;
  975.                   lpdcid->lpsf = lpsf;
  976.                   lpsf->lpVtbl->AddRef(lpsf);
  977.                   // Insert sorted ...
  978.                   {
  979.                     COMBOBOXEXITEM cbei2;
  980.                     LPDC_ITEMDATA lpdcid2;
  981.                     HRESULT hr;
  982.                     cbei2.mask = CBEIF_LPARAM;
  983.                     cbei2.iItem = 0;
  984.                     while ((SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei2)))
  985.                     {
  986.                       lpdcid2 = (LPDC_ITEMDATA)cbei2.lParam;
  987.                       hr = (lpdcid->lpsf->lpVtbl->CompareIDs(
  988.                                  lpdcid->lpsf,
  989.                                  0,
  990.                                  lpdcid->pidl,
  991.                                  lpdcid2->pidl));
  992.                       if ((short)(SCODE_CODE(GetScode(hr))) < 0)
  993.                         break;
  994.                       else
  995.                         cbei2.iItem++;
  996.                     }
  997.                     cbei.iItem = cbei2.iItem;
  998.                     cbei.lParam = (LPARAM)lpdcid;
  999.                     SendMessage(hwnd,CBEM_INSERTITEM,0,(LPARAM)&cbei);
  1000.                   }
  1001.                 }
  1002.               }
  1003.               //lpMalloc->lpVtbl->Free(lpMalloc,pidlEntry);
  1004.             } // IEnumIDList::Next()
  1005.             lpe->lpVtbl->Release(lpe);
  1006.           } // IShellFolder::EnumObjects()
  1007.           lpsf->lpVtbl->Release(lpsf);
  1008.         } // IShellFolder::BindToObject()
  1009.         g_lpMalloc->lpVtbl->Free(g_lpMalloc,pidl);
  1010.       } // SHGetSpecialFolderLocation()
  1011.       lpsfDesktop->lpVtbl->Release(lpsfDesktop);
  1012.     } // SHGetDesktopFolder()
  1013.     //lpMalloc->lpVtbl->Release(lpMalloc);
  1014.   //} // SHGetMalloc()
  1015.   SendMessage(hwnd,WM_SETREDRAW,1,0);
  1016.   // Return number of items added to combo box
  1017.   return (SendMessage(hwnd,CB_GETCOUNT,0,0));
  1018. }
  1019. //=============================================================================
  1020. //
  1021. //  DriveBox_GetSelDrive
  1022. //
  1023. BOOL DriveBox_GetSelDrive(HWND hwnd,LPWSTR lpszDrive,int nDrive,BOOL fNoSlash)
  1024. {
  1025.   COMBOBOXEXITEM cbei;
  1026.   LPDC_ITEMDATA lpdcid;
  1027.   int i = SendMessage(hwnd,CB_GETCURSEL,0,0);
  1028.   // CB_ERR means no Selection
  1029.   if (i == CB_ERR)
  1030.     return FALSE;
  1031.   // Get DC_ITEMDATA* of selected Item
  1032.   cbei.mask = CBEIF_LPARAM;
  1033.   cbei.iItem = i;
  1034.   SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1035.   lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1036.   // Get File System Path for Drive
  1037.   IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,lpszDrive,nDrive);
  1038.   // Remove Backslash if required (makes Drive relative!!!)
  1039.   if (fNoSlash)
  1040.     PathRemoveBackslash(lpszDrive);
  1041.   return TRUE;
  1042. }
  1043. //=============================================================================
  1044. //
  1045. //  DriveBox_SelectDrive
  1046. //
  1047. BOOL DriveBox_SelectDrive(HWND hwnd,LPCWSTR lpszPath)
  1048. {
  1049.   COMBOBOXEXITEM cbei;
  1050.   LPDC_ITEMDATA lpdcid;
  1051.   WCHAR szRoot[64];
  1052.   int i;
  1053.   int cbItems = SendMessage(hwnd,CB_GETCOUNT,0,0);
  1054.   // No Drives in Combo Box
  1055.   if (!cbItems)
  1056.     return FALSE;
  1057.   cbei.mask = CBEIF_LPARAM;
  1058.   for (i = 0; i < cbItems; i++)
  1059.   {
  1060.     // Get DC_ITEMDATA* of Item i
  1061.     cbei.iItem = i;
  1062.     SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1063.     lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1064.     // Get File System Path for Drive
  1065.     IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szRoot,64);
  1066.     // Compare Root Directory with Path
  1067.     if (PathIsSameRoot(lpszPath,szRoot))
  1068.     {
  1069.       // Select matching Drive
  1070.       SendMessage(hwnd,CB_SETCURSEL,i,0);
  1071.       return TRUE;
  1072.     }
  1073.   }
  1074.   // Don't select anything
  1075.   SendMessage(hwnd,CB_SETCURSEL,(WPARAM)-1,0);
  1076.   return FALSE;
  1077. }
  1078. //=============================================================================
  1079. //
  1080. //  DriveBox_PropertyDlg()
  1081. //
  1082. //  Shows standard Win95 Property Dlg for selected Drive
  1083. //
  1084. BOOL DriveBox_PropertyDlg(HWND hwnd)
  1085. {
  1086.   COMBOBOXEXITEM cbei;
  1087.   LPDC_ITEMDATA lpdcid;
  1088.   int iItem;
  1089.   LPCONTEXTMENU lpcm;
  1090.   CMINVOKECOMMANDINFO cmi;
  1091.   BOOL bSuccess = TRUE;
  1092.   static const char *lpVerb = "properties";
  1093.   iItem = SendMessage(hwnd,CB_GETCURSEL,0,0);
  1094.   if (iItem == CB_ERR)
  1095.     return FALSE;
  1096.   cbei.mask = CBEIF_LPARAM;
  1097.   cbei.iItem = iItem;
  1098.   SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1099.   lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1100.   if (NOERROR == lpdcid->lpsf->lpVtbl->GetUIObjectOf(
  1101.                                          lpdcid->lpsf,
  1102.                                          GetParent(hwnd),  // Owner
  1103.                                          1,                // Number of objects
  1104.                                          &lpdcid->pidl,    // pidl
  1105.                                          &IID_IContextMenu,
  1106.                                          NULL,
  1107.                                          &lpcm))
  1108.   {
  1109.     cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
  1110.     cmi.fMask = 0;
  1111.     cmi.hwnd = GetParent(hwnd);
  1112.     cmi.lpVerb = lpVerb;
  1113.     cmi.lpParameters = NULL;
  1114.     cmi.lpDirectory = NULL;
  1115.     cmi.nShow = SW_SHOWNORMAL;
  1116.     cmi.dwHotKey = 0;
  1117.     cmi.hIcon = NULL;
  1118.     if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
  1119.       bSuccess = FALSE;
  1120.     lpcm->lpVtbl->Release(lpcm);
  1121.   }
  1122.   else
  1123.     bSuccess = FALSE;
  1124.   return(bSuccess);
  1125. }
  1126. //=============================================================================
  1127. //
  1128. //  DriveBox_DeleteItem
  1129. //
  1130. LRESULT DriveBox_DeleteItem(HWND hwnd,LPARAM lParam)
  1131. {
  1132.   //LPMALLOC lpMalloc;
  1133.   NMCOMBOBOXEX *lpnmcbe;
  1134.   COMBOBOXEXITEM cbei;
  1135.   LPDC_ITEMDATA lpdcid;
  1136.   lpnmcbe = (LPVOID)lParam;
  1137.   cbei.iItem = lpnmcbe->ceItem.iItem;
  1138.   cbei.mask = CBEIF_LPARAM;
  1139.   SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
  1140.   lpdcid = (LPDC_ITEMDATA)cbei.lParam;
  1141.   //SHGetMalloc(&lpMalloc);
  1142.   // Free pidl
  1143.   g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdcid->pidl);
  1144.   // Release lpsf
  1145.   lpdcid->lpsf->lpVtbl->Release(lpdcid->lpsf);
  1146.   // Free lpdcid itself
  1147.   g_lpMalloc->lpVtbl->Free(g_lpMalloc,lpdcid);
  1148.   // Release lpMalloc
  1149.   //lpMalloc->lpVtbl->Release(lpMalloc);
  1150.   return TRUE;
  1151. }
  1152. //=============================================================================
  1153. //
  1154. //  DriveBox_GetDispInfo
  1155. //
  1156. LRESULT DriveBox_GetDispInfo(HWND hwnd,LPARAM lParam)
  1157. {
  1158.   NMCOMBOBOXEX *lpnmcbe;
  1159.   LPDC_ITEMDATA lpdcid;
  1160.   SHFILEINFO shfi;
  1161.   WCHAR szTemp[256];
  1162.   lpnmcbe = (LPVOID)lParam;
  1163.   lpdcid = (LPDC_ITEMDATA)lpnmcbe->ceItem.lParam;
  1164.   if (!lpdcid)
  1165.     return FALSE;
  1166.   // Get Display Name
  1167.   if (lpnmcbe->ceItem.mask & CBEIF_TEXT)
  1168.     IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_NORMAL,lpnmcbe->ceItem.pszText,lpnmcbe->ceItem.cchTextMax);
  1169.   // Get Icon Index
  1170.   if (lpnmcbe->ceItem.mask & (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE))
  1171.   {
  1172.     IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szTemp,256);
  1173.     SHGetFileInfo(szTemp,0,&shfi,sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
  1174.     lpnmcbe->ceItem.iImage = shfi.iIcon;
  1175.     lpnmcbe->ceItem.iSelectedImage = shfi.iIcon;
  1176.   }
  1177.   // Set values
  1178.   lpnmcbe->ceItem.mask |= CBEIF_DI_SETITEM;
  1179.   return TRUE;
  1180. }
  1181. //==== ItemID =================================================================
  1182. //=============================================================================
  1183. //
  1184. //  IL_Create()
  1185. //
  1186. // Creates an ITEMIDLIST by concatenating pidl1 and pidl2
  1187. // cb1 and cb2 indicate the sizes of the pidls, where cb1
  1188. // can be zero and pidl1 can be NULL
  1189. //
  1190. // If cb2 is zero, the size of pidl2 is retrieved using
  1191. // IL_GetSize(pidl2)
  1192. //
  1193. LPITEMIDLIST IL_Create(LPMALLOC lpMalloc,
  1194.                        LPCITEMIDLIST pidl1,UINT cb1,
  1195.                        LPCITEMIDLIST pidl2,UINT cb2)
  1196. {
  1197.   LPITEMIDLIST pidl;
  1198.   if (!pidl2)
  1199.     return NULL;
  1200.   if (!cb2)
  1201.     cb2 = IL_GetSize(pidl2) + 2; // Space for terminating Bytes
  1202.   if (!cb1)
  1203.     cb1 = IL_GetSize(pidl1);
  1204.   // Allocate Memory
  1205.   pidl = lpMalloc->lpVtbl->Alloc(lpMalloc,cb1 + cb2);
  1206.   // Init new ITEMIDLIST
  1207.   if (pidl1)
  1208.     CopyMemory(pidl,pidl1,cb1);
  1209.   // pidl2 can't be NULL here
  1210.   CopyMemory((LPBYTE)pidl + cb1,pidl2,cb2);
  1211.   return pidl;
  1212. }
  1213. //=============================================================================
  1214. //
  1215. // IL_GetSize()
  1216. //
  1217. // Retrieves the number of bytes in a pidl
  1218. // Does not add space for zero terminators !!
  1219. //
  1220. UINT IL_GetSize(LPCITEMIDLIST pidl)
  1221. {
  1222.   LPITEMIDLIST pidlTmp;
  1223.   UINT cb = 0;
  1224.   if (!pidl)
  1225.     return 0;
  1226.   for (pidlTmp = (LPITEMIDLIST)pidl;
  1227.        pidlTmp->mkid.cb;
  1228.        pidlTmp = _IL_Next(pidlTmp))
  1229.     cb += pidlTmp->mkid.cb;
  1230.   return cb;
  1231. }
  1232. //=============================================================================
  1233. //
  1234. // IL_GetDisplayName()
  1235. //
  1236. // Gets the Display Name of a pidl. lpsf is the parent IShellFolder Interface
  1237. // dwFlags specify a SHGDN_xx value
  1238. //
  1239. BOOL IL_GetDisplayName(LPSHELLFOLDER lpsf,
  1240.                        LPCITEMIDLIST pidl,
  1241.                        DWORD dwFlags,
  1242.                        LPWSTR lpszDisplayName,
  1243.                        int nDisplayName)
  1244. {
  1245.   STRRET str;
  1246.   if (NOERROR == lpsf->lpVtbl->GetDisplayNameOf(lpsf,
  1247.                                                 pidl,
  1248.                                                 dwFlags,
  1249.                                                 &str))
  1250.   {
  1251.     // Shlwapi.dll provides new function:
  1252.     return StrRetToBuf(&str,pidl,lpszDisplayName,nDisplayName);
  1253.     // ...but I suppose my version is faster ;-)
  1254.     /*switch (str.uType)
  1255.     {
  1256.       case STRRET_WSTR:
  1257.         WideCharToMultiByte(CP_ACP,
  1258.                             0,
  1259.                             str.pOleStr,
  1260.                             -1,
  1261.                             lpszDisplayName,
  1262.                             nDisplayName,
  1263.                             NULL,
  1264.                             NULL);
  1265.         g_lpMalloc->lpVtbl->Free(g_lpMalloc,str.pOleStr);
  1266.         break;
  1267.       case STRRET_OFFSET:
  1268.         lstrcpyn(lpszDisplayName,
  1269.                  ((WCHAR *)(pidl)) + str.uOffset,
  1270.                  nDisplayName);
  1271.         break;
  1272.       case STRRET_CSTR:
  1273.         lstrcpyn(lpszDisplayName,str.cStr,nDisplayName);
  1274.         break;
  1275.     }
  1276.     return TRUE;*/
  1277.   }
  1278.   return FALSE;
  1279. }
  1280. ///   End of Dlapi.c   \