mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-14 21:09:05 +08:00
1525 lines
38 KiB
C
1525 lines
38 KiB
C
/******************************************************************************
|
|
* *
|
|
* *
|
|
* Notepad3 *
|
|
* *
|
|
* Dlapi.c *
|
|
* Directory Listing APIs used in Notepad3 *
|
|
* Based on code from Notepad2, (c) Florian Balmer 1996-2011 *
|
|
* *
|
|
* (c) Rizonesoft 2008-2016 *
|
|
* https://rizonesoft.com *
|
|
* *
|
|
* *
|
|
*******************************************************************************/
|
|
#if !defined(WINVER)
|
|
#define WINVER 0x601 /*_WIN32_WINNT_WIN7*/
|
|
#endif
|
|
#if !defined(_WIN32_WINNT)
|
|
#define _WIN32_WINNT 0x601 /*_WIN32_WINNT_WIN7*/
|
|
#endif
|
|
#if !defined(NTDDI_VERSION)
|
|
#define NTDDI_VERSION 0x06010000 /*NTDDI_WIN7*/
|
|
#endif
|
|
#define VC_EXTRALEAN 1
|
|
|
|
#include <windows.h>
|
|
#include <commctrl.h>
|
|
#include <shlobj.h>
|
|
#include <shlwapi.h>
|
|
#include <string.h>
|
|
#include "helpers.h"
|
|
#include "dlapi.h"
|
|
|
|
|
|
|
|
//==== DirList ================================================================
|
|
|
|
//==== DLDATA Structure =======================================================
|
|
|
|
typedef struct tagDLDATA // dl
|
|
{
|
|
|
|
HWND hwnd; // HWND of ListView Control
|
|
UINT cbidl; // Size of pidl
|
|
LPITEMIDLIST pidl; // Directory Id
|
|
LPSHELLFOLDER lpsf; // IShellFolder Interface to pidl
|
|
WCHAR szPath[MAX_PATH]; // Pathname to Directory Id
|
|
int iDefIconFolder; // Default Folder Icon
|
|
int iDefIconFile; // Default File Icon
|
|
bool bNoFadeHidden; // Flag passed from GetDispInfo()
|
|
HANDLE hThread; // Thread Handle
|
|
HANDLE hExitThread; // Flag is set when Icon Thread should terminate
|
|
HANDLE hTerminatedThread; // Flag is set when Icon Thread has terminated
|
|
|
|
} DLDATA, *LPDLDATA;
|
|
|
|
|
|
//==== Property Name ==========================================================
|
|
static const WCHAR *pDirListProp = L"DirListData";
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_Init()
|
|
//
|
|
// Initializes the DLDATA structure and sets up the listview control
|
|
//
|
|
bool DirList_Init(HWND hwnd,LPCWSTR pszHeader)
|
|
{
|
|
HIMAGELIST hil;
|
|
SHFILEINFO shfi;
|
|
|
|
// Allocate DirListData Property
|
|
LPDLDATA lpdl = (LPVOID)GlobalAlloc(GPTR,sizeof(DLDATA));
|
|
SetProp(hwnd,pDirListProp,(HANDLE)lpdl);
|
|
|
|
// Setup dl
|
|
lpdl->hwnd = hwnd;
|
|
lpdl->cbidl = 0;
|
|
lpdl->pidl = NULL;
|
|
lpdl->lpsf = NULL;
|
|
StringCchCopy(lpdl->szPath,COUNTOF(lpdl->szPath),L"");
|
|
|
|
// Add Imagelists
|
|
hil = (HIMAGELIST)SHGetFileInfo(L"C:\\",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
|
|
|
|
ListView_SetImageList(hwnd,hil,LVSIL_SMALL);
|
|
|
|
hil = (HIMAGELIST)SHGetFileInfo(L"C:\\",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_LARGEICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
|
|
|
|
ListView_SetImageList(hwnd,hil,LVSIL_NORMAL);
|
|
|
|
// Initialize default icons - done in DirList_Fill()
|
|
//SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
|
|
// SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
|
|
//lpdl->iDefIconFolder = shfi.iIcon;
|
|
|
|
//SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
|
|
// SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
|
|
//lpdl->iDefIconFile = shfi.iIcon;
|
|
|
|
lpdl->iDefIconFolder = 0;
|
|
lpdl->iDefIconFile = 0;
|
|
|
|
// Icon thread control
|
|
lpdl->hExitThread = CreateEvent(NULL,true,false,NULL);
|
|
lpdl->hTerminatedThread = CreateEvent(NULL,true,true,NULL);
|
|
|
|
UNUSED(pszHeader);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_Destroy()
|
|
//
|
|
// Free memory used by dl structure
|
|
//
|
|
bool DirList_Destroy(HWND hwnd)
|
|
{
|
|
|
|
LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
|
|
|
|
// Release multithreading objects
|
|
DirList_TerminateIconThread(hwnd);
|
|
CloseHandle(lpdl->hExitThread);
|
|
CloseHandle(lpdl->hTerminatedThread);
|
|
|
|
if (lpdl->pidl)
|
|
CoTaskMemFree(lpdl->pidl);
|
|
|
|
if (lpdl->lpsf)
|
|
lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
|
|
|
|
// Free DirListData Property
|
|
RemoveProp(hwnd,pDirListProp);
|
|
GlobalFree(lpdl);
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_StartIconThread()
|
|
//
|
|
// Start thread to extract file icons in the background
|
|
//
|
|
bool DirList_StartIconThread(HWND hwnd)
|
|
{
|
|
DWORD dwtid;
|
|
LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
|
|
|
|
DirList_TerminateIconThread(hwnd);
|
|
|
|
ResetEvent(lpdl->hExitThread);
|
|
//ResetEvent(lpdl->hTerminatedThread);
|
|
|
|
lpdl->hThread = CreateThread(NULL, 0, DirList_IconThread, (LPVOID)lpdl, 0, &dwtid);
|
|
|
|
if (lpdl->hThread == NULL) {
|
|
ResetEvent(lpdl->hExitThread);
|
|
SetEvent(lpdl->hTerminatedThread);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_TerminateIconThread()
|
|
//
|
|
// Terminate Icon Thread and reset multithreading control structures
|
|
//
|
|
bool DirList_TerminateIconThread(HWND hwnd)
|
|
{
|
|
LPDLDATA lpdl = (LPDLDATA)GetProp(hwnd,pDirListProp);
|
|
|
|
if (!lpdl->hThread)
|
|
return false;
|
|
|
|
SetEvent(lpdl->hExitThread);
|
|
|
|
//WaitForSingleObject(lpdl->hTerminatedThread,INFINITE);
|
|
while (WaitForSingleObject(lpdl->hTerminatedThread,0) != WAIT_OBJECT_0)
|
|
{
|
|
MSG msg;
|
|
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
|
|
ResetEvent(lpdl->hExitThread);
|
|
SetEvent(lpdl->hTerminatedThread);
|
|
lpdl->hThread = NULL;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_Fill()
|
|
//
|
|
// Snapshots a directory and displays the items in the listview control
|
|
//
|
|
int DirList_Fill(HWND hwnd,LPCWSTR lpszDir,DWORD grfFlags,LPCWSTR lpszFileSpec,
|
|
bool bExcludeFilter,bool bNoFadeHidden,
|
|
int iSortFlags,bool fSortRev)
|
|
{
|
|
|
|
WCHAR wszDir[MAX_PATH] = { L'\0' };
|
|
|
|
LPSHELLFOLDER lpsfDesktop = NULL;
|
|
LPSHELLFOLDER lpsf = NULL;
|
|
|
|
LPITEMIDLIST pidl = NULL;
|
|
LPITEMIDLIST pidlEntry = NULL;
|
|
|
|
LPENUMIDLIST lpe = NULL;
|
|
|
|
ULONG chParsed = 0;
|
|
ULONG dwAttributes = 0;
|
|
|
|
// First of all terminate running icon thread
|
|
DirList_TerminateIconThread(hwnd);
|
|
|
|
LPDLDATA lpdl = (LPDLDATA)GetProp(hwnd,pDirListProp);
|
|
|
|
// Initialize default icons
|
|
SHFILEINFO shfi;
|
|
ZeroMemory(&shfi, sizeof(shfi));
|
|
SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
|
|
lpdl->iDefIconFolder = shfi.iIcon;
|
|
|
|
SHGetFileInfo(L"Icon",FILE_ATTRIBUTE_NORMAL,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_USEFILEATTRIBUTES | SHGFI_SMALLICON | SHGFI_SYSICONINDEX);
|
|
lpdl->iDefIconFile = shfi.iIcon;
|
|
|
|
// A Directory is strongly required
|
|
if (!lpszDir || !*lpszDir) {
|
|
return(-1);
|
|
}
|
|
StringCchCopyN(lpdl->szPath, COUNTOF(lpdl->szPath), lpszDir, MAX_PATH);
|
|
|
|
// Init ListView
|
|
SendMessage(hwnd,WM_SETREDRAW,0,0);
|
|
ListView_DeleteAllItems(hwnd);
|
|
|
|
// Init Filter
|
|
DL_FILTER dlf;
|
|
ZeroMemory(&dlf, sizeof(DL_FILTER));
|
|
DirList_CreateFilter(&dlf,lpszFileSpec,bExcludeFilter);
|
|
|
|
// Init lvi
|
|
LV_ITEM lvi;
|
|
ZeroMemory(&lvi, sizeof(LV_ITEM));
|
|
lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
|
|
lvi.iItem = 0;
|
|
lvi.iSubItem = 0;
|
|
lvi.pszText = LPSTR_TEXTCALLBACK;
|
|
lvi.cchTextMax = MAX_PATH;
|
|
lvi.iImage = I_IMAGECALLBACK;
|
|
|
|
// Convert Directory to a UNICODE string
|
|
/*MultiByteToWideChar(CP_ACP,
|
|
MB_PRECOMPOSED,
|
|
lpszDir,
|
|
-1,
|
|
wszDir,
|
|
MAX_PATH);*/
|
|
StringCchCopy(wszDir,COUNTOF(wszDir),lpszDir);
|
|
|
|
// Get Desktop Folder
|
|
if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
|
|
{
|
|
|
|
// Convert wszDir into a pidl
|
|
if (NOERROR == lpsfDesktop->lpVtbl->ParseDisplayName(
|
|
lpsfDesktop,
|
|
hwnd,
|
|
NULL,
|
|
wszDir,
|
|
&chParsed,
|
|
&pidl,
|
|
&dwAttributes))
|
|
|
|
{
|
|
|
|
// Bind pidl to IShellFolder
|
|
if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
|
|
lpsfDesktop,
|
|
pidl,
|
|
NULL,
|
|
&IID_IShellFolder,
|
|
&lpsf))
|
|
|
|
{
|
|
|
|
// Create an Enumeration object for lpsf
|
|
if (NOERROR == lpsf->lpVtbl->EnumObjects(
|
|
lpsf,
|
|
hwnd,
|
|
grfFlags,
|
|
&lpe))
|
|
|
|
{
|
|
|
|
// Enumerate the contents of lpsf
|
|
while (NOERROR == lpe->lpVtbl->Next(
|
|
lpe,
|
|
1,
|
|
&pidlEntry,
|
|
NULL))
|
|
|
|
{
|
|
|
|
// Add found item to the List
|
|
// Check if it's part of the Filesystem
|
|
dwAttributes = SFGAO_FILESYSTEM | SFGAO_FOLDER;
|
|
|
|
lpsf->lpVtbl->GetAttributesOf(
|
|
lpsf,
|
|
1,
|
|
&pidlEntry,
|
|
&dwAttributes);
|
|
|
|
if (dwAttributes & SFGAO_FILESYSTEM)
|
|
{
|
|
|
|
// Check if item matches specified filter
|
|
if (DirList_MatchFilter(lpsf,pidlEntry,&dlf))
|
|
{
|
|
|
|
LPLV_ITEMDATA lplvid = CoTaskMemAlloc(sizeof(LV_ITEMDATA));
|
|
|
|
lplvid->pidl = pidlEntry;
|
|
lplvid->lpsf = lpsf;
|
|
|
|
lpsf->lpVtbl->AddRef(lpsf);
|
|
|
|
lvi.lParam = (LPARAM)lplvid;
|
|
|
|
// Setup default Icon - Folder or File
|
|
lvi.iImage = (dwAttributes & SFGAO_FOLDER) ?
|
|
lpdl->iDefIconFolder : lpdl->iDefIconFile;
|
|
|
|
ListView_InsertItem(hwnd,&lvi);
|
|
|
|
lvi.iItem++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // IEnumIDList::Next()
|
|
|
|
lpe->lpVtbl->Release(lpe);
|
|
|
|
} // IShellFolder::EnumObjects()
|
|
|
|
} // IShellFolder::BindToObject()
|
|
|
|
} // IShellFolder::ParseDisplayName()
|
|
|
|
lpsfDesktop->lpVtbl->Release(lpsfDesktop);
|
|
|
|
} // SHGetDesktopFolder()
|
|
|
|
if (lpdl->pidl)
|
|
CoTaskMemFree(lpdl->pidl);
|
|
|
|
if (lpdl->lpsf && lpdl->lpsf->lpVtbl)
|
|
lpdl->lpsf->lpVtbl->Release(lpdl->lpsf);
|
|
|
|
// Set lpdl
|
|
lpdl->cbidl = IL_GetSize(pidl);
|
|
lpdl->pidl = pidl;
|
|
lpdl->lpsf = lpsf;
|
|
lpdl->bNoFadeHidden = bNoFadeHidden;
|
|
|
|
// Set column width to fit window
|
|
ListView_SetColumnWidth(hwnd,0,LVSCW_AUTOSIZE_USEHEADER);
|
|
|
|
// Sort before display is updated
|
|
DirList_Sort(hwnd,iSortFlags,fSortRev);
|
|
|
|
// Redraw Listview
|
|
SendMessage(hwnd,WM_SETREDRAW,1,0);
|
|
|
|
// Return number of items in the control
|
|
return (ListView_GetItemCount(hwnd));
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_IconThread()
|
|
//
|
|
// Thread to extract file icons in the background
|
|
//
|
|
DWORD WINAPI DirList_IconThread(LPVOID lpParam)
|
|
{
|
|
if (!lpParam)
|
|
return(0);
|
|
|
|
LPDLDATA lpdl = (LPDLDATA)lpParam;
|
|
ResetEvent(lpdl->hTerminatedThread);
|
|
|
|
// Exit immediately if DirList_Fill() hasn't been called
|
|
if (!(lpdl->lpsf)) {
|
|
SetEvent(lpdl->hTerminatedThread);
|
|
ExitThread(0);
|
|
//return(0);
|
|
}
|
|
|
|
HWND hwnd = lpdl->hwnd;
|
|
int iMaxItem = ListView_GetItemCount(hwnd);
|
|
|
|
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY);
|
|
|
|
// Get IShellIcon
|
|
IShellIcon* lpshi = NULL;
|
|
lpdl->lpsf->lpVtbl->QueryInterface(lpdl->lpsf,&IID_IShellIcon,&lpshi);
|
|
|
|
int iItem = 0;
|
|
while (iItem < iMaxItem && WaitForSingleObject(lpdl->hExitThread,0) != WAIT_OBJECT_0) {
|
|
|
|
LV_ITEM lvi = { 0 };
|
|
|
|
lvi.iItem = iItem;
|
|
lvi.mask = LVIF_PARAM;
|
|
if (ListView_GetItem(hwnd,&lvi)) {
|
|
|
|
SHFILEINFO shfi;
|
|
LPITEMIDLIST pidl;
|
|
DWORD dwAttributes = SFGAO_LINK | SFGAO_SHARE;
|
|
|
|
LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lvi.lParam;
|
|
|
|
lvi.mask = LVIF_IMAGE;
|
|
|
|
if (!lpshi || NOERROR != lpshi->lpVtbl->GetIconOf(lpshi,lplvid->pidl,GIL_FORSHELL,&lvi.iImage))
|
|
{
|
|
// get attributes of the shell object using its pidl.
|
|
lplvid->lpsf->lpVtbl->GetAttributesOf(lplvid->lpsf, 1, &lplvid->pidl, &dwAttributes);
|
|
|
|
DWORD attr = 0;
|
|
if ((dwAttributes & SFGAO_FOLDER) == SFGAO_FOLDER)
|
|
attr = FILE_ATTRIBUTE_DIRECTORY;
|
|
else
|
|
attr = FILE_ATTRIBUTE_NORMAL;
|
|
|
|
pidl = IL_Create(lpdl->pidl, lpdl->cbidl, lplvid->pidl, 0);
|
|
|
|
SHGetFileInfo((LPCWSTR)pidl,attr,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
|
|
CoTaskMemFree(pidl);
|
|
lvi.iImage = shfi.iIcon;
|
|
}
|
|
|
|
// It proved necessary to reset the state bits...
|
|
lvi.stateMask = 0;
|
|
lvi.state = 0;
|
|
|
|
// Link and Share Overlay
|
|
lplvid->lpsf->lpVtbl->GetAttributesOf(lplvid->lpsf,1,&lplvid->pidl,&dwAttributes);
|
|
|
|
if (dwAttributes & SFGAO_LINK)
|
|
{
|
|
lvi.mask |= LVIF_STATE;
|
|
lvi.stateMask |= LVIS_OVERLAYMASK;
|
|
lvi.state |= INDEXTOOVERLAYMASK(2);
|
|
}
|
|
|
|
if (dwAttributes & SFGAO_SHARE)
|
|
{
|
|
lvi.mask |= LVIF_STATE;
|
|
lvi.stateMask |= LVIS_OVERLAYMASK;
|
|
lvi.state |= INDEXTOOVERLAYMASK(1);
|
|
}
|
|
|
|
// Fade hidden/system files
|
|
if (!lpdl->bNoFadeHidden)
|
|
{
|
|
WIN32_FIND_DATA fd;
|
|
if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,lplvid->pidl,
|
|
SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA)))
|
|
{
|
|
if ((fd.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ||
|
|
(fd.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM))
|
|
{
|
|
lvi.mask |= LVIF_STATE;
|
|
lvi.stateMask |= LVIS_CUT;
|
|
lvi.state |= LVIS_CUT;
|
|
}
|
|
}
|
|
}
|
|
lvi.iSubItem = 0;
|
|
ListView_SetItem(hwnd,&lvi);
|
|
}
|
|
iItem++;
|
|
}
|
|
|
|
if (lpshi)
|
|
lpshi->lpVtbl->Release(lpshi);
|
|
|
|
CoUninitialize();
|
|
|
|
SetEvent(lpdl->hTerminatedThread);
|
|
ExitThread(0);
|
|
//return(0);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_GetDispInfo()
|
|
//
|
|
// Must be called in response to a WM_NOTIFY/LVN_GETDISPINFO message from
|
|
// the listview control
|
|
//
|
|
bool DirList_GetDispInfo(HWND hwnd,LPARAM lParam,bool bNoFadeHidden)
|
|
{
|
|
|
|
LV_DISPINFO *lpdi = (LPVOID)lParam;
|
|
|
|
LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lpdi->item.lParam;
|
|
|
|
// SubItem 0 is handled only
|
|
if (lpdi->item.iSubItem != 0)
|
|
return false;
|
|
|
|
// Text
|
|
if (lpdi->item.mask & LVIF_TEXT)
|
|
IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
|
|
lpdi->item.pszText,lpdi->item.cchTextMax);
|
|
|
|
// Set values
|
|
lpdi->item.mask |= LVIF_DI_SETITEM;
|
|
|
|
UNUSED(hwnd);
|
|
UNUSED(bNoFadeHidden);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_DeleteItem()
|
|
//
|
|
// Must be called in response to a WM_NOTIFY/LVN_DELETEITEM message
|
|
// from the control
|
|
//
|
|
bool DirList_DeleteItem(HWND hwnd,LPARAM lParam)
|
|
{
|
|
if (!lParam)
|
|
return false;
|
|
|
|
LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW)lParam;
|
|
|
|
LV_ITEM lvi;
|
|
ZeroMemory(&lvi, sizeof(LV_ITEM));
|
|
lvi.iItem = lpnmlv->iItem;
|
|
lvi.iSubItem = 0;
|
|
lvi.mask = LVIF_PARAM;
|
|
|
|
if (ListView_GetItem(hwnd,&lvi))
|
|
{
|
|
// Free mem
|
|
LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lvi.lParam;
|
|
CoTaskMemFree(lplvid->pidl);
|
|
lplvid->lpsf->lpVtbl->Release(lplvid->lpsf);
|
|
|
|
CoTaskMemFree(lplvid);
|
|
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_CompareProc()
|
|
//
|
|
// Compares two list items
|
|
//
|
|
int CALLBACK DirList_CompareProcFw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
|
|
{
|
|
LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
|
|
LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
|
|
|
|
HRESULT hr = (lplvid1->lpsf->lpVtbl->CompareIDs(lplvid1->lpsf,lFlags,lplvid1->pidl,lplvid2->pidl));
|
|
|
|
int result = (short)(SCODE_CODE(GetScode(hr)));
|
|
|
|
if (result != 0 || lFlags == 0)
|
|
return result;
|
|
|
|
hr = (lplvid1->lpsf->lpVtbl->CompareIDs(lplvid1->lpsf,0,lplvid1->pidl,lplvid2->pidl));
|
|
|
|
result = (short)(SCODE_CODE(GetScode(hr)));
|
|
|
|
return result;
|
|
}
|
|
|
|
int CALLBACK DirList_CompareProcRw(LPARAM lp1,LPARAM lp2,LPARAM lFlags)
|
|
{
|
|
LPLV_ITEMDATA lplvid1 = (LPLV_ITEMDATA)lp1;
|
|
LPLV_ITEMDATA lplvid2 = (LPLV_ITEMDATA)lp2;
|
|
|
|
HRESULT hr = (lplvid1->lpsf->lpVtbl->CompareIDs(lplvid1->lpsf,lFlags,lplvid1->pidl,lplvid2->pidl));
|
|
|
|
int result = -(short)(SCODE_CODE(GetScode(hr)));
|
|
|
|
if (result != 0)
|
|
return result;
|
|
|
|
hr = (lplvid1->lpsf->lpVtbl->CompareIDs(lplvid1->lpsf,0,lplvid1->pidl,lplvid2->pidl));
|
|
|
|
result = -(short)(SCODE_CODE(GetScode(hr)));
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_Sort()
|
|
//
|
|
// Sorts the listview control by the specified order
|
|
//
|
|
bool DirList_Sort(HWND hwnd,int lFlags,bool fRev)
|
|
{
|
|
if (fRev)
|
|
return ListView_SortItems(hwnd,DirList_CompareProcRw,lFlags);
|
|
else
|
|
return ListView_SortItems(hwnd,DirList_CompareProcFw,lFlags);
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_GetItem()
|
|
//
|
|
// Copies the data of the specified item in the listview control to a buffer
|
|
//
|
|
int DirList_GetItem(HWND hwnd,int iItem,LPDLITEM lpdli)
|
|
{
|
|
if (iItem == -1)
|
|
{
|
|
if (ListView_GetSelectedCount(hwnd))
|
|
iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
|
|
else
|
|
return(-1);
|
|
}
|
|
|
|
LV_ITEM lvi;
|
|
ZeroMemory(&lvi, sizeof(LV_ITEM));
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iItem;
|
|
lvi.iSubItem = 0;
|
|
|
|
if (!ListView_GetItem(hwnd,&lvi))
|
|
{
|
|
if (lpdli->mask & DLI_TYPE)
|
|
lpdli->ntype = DLE_NONE;
|
|
|
|
return(-1);
|
|
}
|
|
|
|
LPLV_ITEMDATA lplvid = (LPLV_ITEMDATA)lvi.lParam;
|
|
|
|
// Filename
|
|
if (lpdli->mask & DLI_FILENAME)
|
|
|
|
IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_FORPARSING,
|
|
lpdli->szFileName,MAX_PATH);
|
|
|
|
// Displayname
|
|
if (lpdli->mask & DLI_DISPNAME)
|
|
|
|
IL_GetDisplayName(lplvid->lpsf,lplvid->pidl,SHGDN_INFOLDER,
|
|
lpdli->szDisplayName,MAX_PATH);
|
|
|
|
// Type (File / Directory)
|
|
if (lpdli->mask & DLI_TYPE)
|
|
{
|
|
|
|
WIN32_FIND_DATA fd;
|
|
|
|
if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
|
|
lplvid->pidl,
|
|
SHGDFIL_FINDDATA,
|
|
&fd,
|
|
sizeof(WIN32_FIND_DATA)))
|
|
|
|
lpdli->ntype = (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
|
DLE_DIR : DLE_FILE;
|
|
|
|
//ULONG dwAttributes = SFGAO_FILESYSTEM;
|
|
/*lplvid->lpsf->lpVtbl->GetAttributesOf(
|
|
lplvid->lpsf,
|
|
1,
|
|
&lplvid->pidl,
|
|
&dwAttributes);
|
|
|
|
lpdli->ntype = (dwAttributes & SFGAO_FOLDER) ? DLE_DIR : DLE_FILE;*/
|
|
|
|
}
|
|
|
|
return iItem;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_GetItemEx()
|
|
//
|
|
// Retrieves extended infomration on a dirlist item
|
|
//
|
|
int DirList_GetItemEx(HWND hwnd,int iItem,LPWIN32_FIND_DATA pfd)
|
|
{
|
|
|
|
LV_ITEM lvi;
|
|
LPLV_ITEMDATA lplvid;
|
|
|
|
|
|
if (iItem == -1)
|
|
{
|
|
|
|
if (ListView_GetSelectedCount(hwnd))
|
|
|
|
iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
|
|
|
|
else
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iItem;
|
|
lvi.iSubItem = 0;
|
|
|
|
if (!ListView_GetItem(hwnd,&lvi))
|
|
return(-1);
|
|
|
|
lplvid = (LPLV_ITEMDATA)lvi.lParam;
|
|
|
|
if (NOERROR == SHGetDataFromIDList(lplvid->lpsf,
|
|
lplvid->pidl,
|
|
SHGDFIL_FINDDATA,
|
|
pfd,
|
|
sizeof(WIN32_FIND_DATA)))
|
|
return iItem;
|
|
|
|
else
|
|
return(-1);
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_PropertyDlg()
|
|
//
|
|
// Shows standard Win95 Property Dlg for selected Item
|
|
//
|
|
bool DirList_PropertyDlg(HWND hwnd,int iItem)
|
|
{
|
|
|
|
LV_ITEM lvi;
|
|
LPLV_ITEMDATA lplvid;
|
|
LPCONTEXTMENU lpcm;
|
|
CMINVOKECOMMANDINFO cmi;
|
|
bool bSuccess = true;
|
|
|
|
static const char *lpVerb = "properties";
|
|
|
|
if (iItem == -1)
|
|
{
|
|
if (ListView_GetSelectedCount(hwnd))
|
|
iItem = ListView_GetNextItem(hwnd,-1,LVNI_ALL | LVNI_SELECTED);
|
|
|
|
else
|
|
return false;
|
|
}
|
|
|
|
lvi.mask = LVIF_PARAM;
|
|
lvi.iItem = iItem;
|
|
lvi.iSubItem = 0;
|
|
|
|
if (!ListView_GetItem(hwnd,&lvi))
|
|
return false;
|
|
|
|
lplvid = (LPLV_ITEMDATA)lvi.lParam;
|
|
|
|
if (NOERROR == lplvid->lpsf->lpVtbl->GetUIObjectOf(
|
|
lplvid->lpsf,
|
|
GetParent(hwnd), // Owner
|
|
1, // Number of objects
|
|
&lplvid->pidl, // pidl
|
|
&IID_IContextMenu,
|
|
NULL,
|
|
&lpcm))
|
|
{
|
|
|
|
cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
|
|
cmi.fMask = 0;
|
|
cmi.hwnd = GetParent(hwnd);
|
|
cmi.lpVerb = lpVerb;
|
|
cmi.lpParameters = NULL;
|
|
cmi.lpDirectory = NULL;
|
|
cmi.nShow = SW_SHOWNORMAL;
|
|
cmi.dwHotKey = 0;
|
|
cmi.hIcon = NULL;
|
|
|
|
if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
|
|
bSuccess = false;
|
|
|
|
lpcm->lpVtbl->Release(lpcm);
|
|
|
|
}
|
|
|
|
else
|
|
bSuccess = false;
|
|
|
|
return(bSuccess);
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_GetLongPathName()
|
|
//
|
|
// Get long pathname for currently displayed directory
|
|
//
|
|
bool DirList_GetLongPathName(HWND hwnd,LPWSTR lpszLongPath,int length)
|
|
{
|
|
WCHAR tch[MAX_PATH] = { L'\0' };
|
|
LPDLDATA lpdl = (LPVOID)GetProp(hwnd,pDirListProp);
|
|
if (SHGetPathFromIDList(lpdl->pidl,tch))
|
|
{
|
|
StringCchCopy(lpszLongPath,length,tch);
|
|
return(true);
|
|
}
|
|
else
|
|
return(false);
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_SelectItem()
|
|
//
|
|
// Select specified item in the list
|
|
//
|
|
bool DirList_SelectItem(HWND hwnd,LPCWSTR lpszDisplayName,LPCWSTR lpszFullPath)
|
|
{
|
|
|
|
#define LVIS_FLAGS LVIS_SELECTED|LVIS_FOCUSED
|
|
|
|
WCHAR szShortPath[MAX_PATH] = { L'\0' };
|
|
SHFILEINFO shfi;
|
|
|
|
LV_FINDINFO lvfi;
|
|
DLITEM dli;
|
|
|
|
int i = -1;
|
|
|
|
if (!lpszFullPath || !StringCchLen(lpszFullPath,MAX_PATH))
|
|
return(false);
|
|
else
|
|
GetShortPathName(lpszFullPath,szShortPath,MAX_PATH);
|
|
|
|
if (!lpszDisplayName || !StringCchLen(lpszDisplayName,MAX_PATH))
|
|
SHGetFileInfo(lpszFullPath,0,&shfi,sizeof(SHFILEINFO),SHGFI_DISPLAYNAME);
|
|
else
|
|
StringCchCopyN(shfi.szDisplayName,COUNTOF(shfi.szDisplayName),lpszDisplayName,MAX_PATH);
|
|
|
|
lvfi.flags = LVFI_STRING;
|
|
lvfi.psz = shfi.szDisplayName;
|
|
|
|
dli.mask = DLI_ALL;
|
|
|
|
while ((i = ListView_FindItem(hwnd,i,&lvfi)) != -1)
|
|
{
|
|
|
|
DirList_GetItem(hwnd,i,&dli);
|
|
GetShortPathName(dli.szFileName,dli.szFileName,MAX_PATH);
|
|
|
|
if (!StringCchCompareIN(dli.szFileName,COUNTOF(dli.szFileName),szShortPath,COUNTOF(szShortPath)))
|
|
{
|
|
ListView_SetItemState(hwnd,i,LVIS_FLAGS,LVIS_FLAGS);
|
|
ListView_EnsureVisible(hwnd,i,false);
|
|
|
|
return(true);
|
|
}
|
|
|
|
}
|
|
|
|
return(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_CreateFilter()
|
|
//
|
|
// Create a valid DL_FILTER structure
|
|
//
|
|
void DirList_CreateFilter(PDL_FILTER pdlf,LPCWSTR lpszFileSpec,
|
|
bool bExcludeFilter)
|
|
{
|
|
if (!lpszFileSpec)
|
|
return;
|
|
|
|
ZeroMemory(pdlf,sizeof(DL_FILTER));
|
|
StringCchCopyN(pdlf->tFilterBuf,COUNTOF(pdlf->tFilterBuf),lpszFileSpec,DL_FILTER_BUFSIZE);
|
|
pdlf->bExcludeFilter = bExcludeFilter;
|
|
|
|
if (!StringCchCompareX(lpszFileSpec,L"*.*") || !StringCchLen(lpszFileSpec,DL_FILTER_BUFSIZE))
|
|
return;
|
|
|
|
pdlf->nCount = 1;
|
|
pdlf->pFilter[0] = &pdlf->tFilterBuf[0]; // Zeile zum Ausprobieren
|
|
|
|
WCHAR* p = StrChr(pdlf->pFilter[pdlf->nCount - 1], L';');
|
|
while (p)
|
|
{
|
|
*p = L'\0'; // Replace L';' by L'\0'
|
|
pdlf->pFilter[pdlf->nCount] = (p + 1); // Next position after L';'
|
|
p = StrChr(pdlf->pFilter[pdlf->nCount], L';');
|
|
pdlf->nCount++; // Increase number of filters
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DirList_MatchFilter()
|
|
//
|
|
// Check if a specified item matches a given filter
|
|
//
|
|
bool DirList_MatchFilter(LPSHELLFOLDER lpsf,LPCITEMIDLIST pidl,PDL_FILTER pdlf)
|
|
{
|
|
|
|
int i;
|
|
WIN32_FIND_DATA fd;
|
|
bool bMatchSpec;
|
|
|
|
// Immediately return true if lpszFileSpec is *.* or NULL
|
|
if (pdlf->nCount == 0 && !pdlf->bExcludeFilter)
|
|
return true;
|
|
|
|
SHGetDataFromIDList(lpsf,pidl,SHGDFIL_FINDDATA,&fd,sizeof(WIN32_FIND_DATA));
|
|
|
|
// All the directories are added
|
|
if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
return(true);
|
|
|
|
// Check if exclude *.* after directories have been added
|
|
if (pdlf->nCount == 0 && pdlf->bExcludeFilter)
|
|
return false;
|
|
|
|
for (i = 0; i < pdlf->nCount; i++)
|
|
{
|
|
if (*pdlf->pFilter[i]) // Filters like L"\0" are ignored
|
|
{
|
|
bMatchSpec = PathMatchSpec(fd.cFileName,pdlf->pFilter[i]);
|
|
if (bMatchSpec)
|
|
{
|
|
if (!pdlf->bExcludeFilter)
|
|
return(true);
|
|
else
|
|
return(false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// No matching
|
|
return(pdlf->bExcludeFilter)?true:false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//==== DriveBox ===============================================================
|
|
|
|
//=============================================================================
|
|
//
|
|
// Internal Itemdata Structure
|
|
//
|
|
typedef struct tagDC_ITEMDATA
|
|
{
|
|
|
|
LPITEMIDLIST pidl;
|
|
LPSHELLFOLDER lpsf;
|
|
|
|
} DC_ITEMDATA, *LPDC_ITEMDATA;
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DriveBox_Init()
|
|
//
|
|
// Initializes the drive box
|
|
//
|
|
bool DriveBox_Init(HWND hwnd)
|
|
{
|
|
SHFILEINFO shfi;
|
|
|
|
HIMAGELIST hil = (HIMAGELIST)SHGetFileInfo(L"C:\\",FILE_ATTRIBUTE_DIRECTORY,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_SMALLICON | SHGFI_SYSICONINDEX | SHGFI_USEFILEATTRIBUTES);
|
|
SendMessage(hwnd,CBEM_SETIMAGELIST,0,(LPARAM)hil);
|
|
SendMessage(hwnd,CBEM_SETEXTENDEDSTYLE,CBES_EX_NOSIZELIMIT,CBES_EX_NOSIZELIMIT);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DriveBox_Fill
|
|
//
|
|
|
|
int DriveBox_Fill(HWND hwnd)
|
|
{
|
|
|
|
LPSHELLFOLDER lpsfDesktop;
|
|
LPSHELLFOLDER lpsf; // Workspace == CSIDL_DRIVES
|
|
|
|
LPITEMIDLIST pidl;
|
|
LPITEMIDLIST pidlEntry;
|
|
|
|
LPENUMIDLIST lpe;
|
|
|
|
COMBOBOXEXITEM cbei;
|
|
LPDC_ITEMDATA lpdcid;
|
|
|
|
ULONG dwAttributes = 0;
|
|
|
|
DWORD grfFlags = SHCONTF_FOLDERS;
|
|
|
|
|
|
// Init ComboBox
|
|
SendMessage(hwnd,WM_SETREDRAW,0,0);
|
|
SendMessage(hwnd,CB_RESETCONTENT,0,0);
|
|
|
|
ZeroMemory(&cbei,sizeof(COMBOBOXEXITEM));
|
|
cbei.mask = CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_LPARAM;
|
|
cbei.pszText = LPSTR_TEXTCALLBACK;
|
|
cbei.cchTextMax = MAX_PATH;
|
|
cbei.iImage = I_IMAGECALLBACK;
|
|
cbei.iSelectedImage = I_IMAGECALLBACK;
|
|
|
|
|
|
// Get pidl to [My Computer]
|
|
if (NOERROR == SHGetSpecialFolderLocation(hwnd,
|
|
CSIDL_DRIVES,
|
|
&pidl))
|
|
{
|
|
|
|
// Get Desktop Folder
|
|
if (NOERROR == SHGetDesktopFolder(&lpsfDesktop))
|
|
{
|
|
|
|
// Bind pidl to IShellFolder
|
|
if (NOERROR == lpsfDesktop->lpVtbl->BindToObject(
|
|
lpsfDesktop,
|
|
pidl,
|
|
NULL,
|
|
&IID_IShellFolder,
|
|
&lpsf))
|
|
|
|
{
|
|
|
|
// Create an Enumeration object for lpsf
|
|
if (NOERROR == lpsf->lpVtbl->EnumObjects(
|
|
lpsf,
|
|
hwnd,
|
|
grfFlags,
|
|
&lpe))
|
|
|
|
{
|
|
|
|
// Enumerate the contents of [My Computer]
|
|
while (NOERROR == lpe->lpVtbl->Next(
|
|
lpe,
|
|
1,
|
|
&pidlEntry,
|
|
NULL))
|
|
|
|
{
|
|
|
|
// Add item to the List if it is part of the
|
|
// Filesystem
|
|
dwAttributes = SFGAO_FILESYSTEM;
|
|
|
|
lpsf->lpVtbl->GetAttributesOf(
|
|
lpsf,
|
|
1,
|
|
&pidlEntry,
|
|
&dwAttributes);
|
|
|
|
if (dwAttributes & SFGAO_FILESYSTEM)
|
|
{
|
|
|
|
// Windows XP: check if pidlEntry is a drive
|
|
SHDESCRIPTIONID di;
|
|
HRESULT hr;
|
|
hr = SHGetDataFromIDList(lpsf,pidlEntry,SHGDFIL_DESCRIPTIONID,
|
|
&di,sizeof(SHDESCRIPTIONID));
|
|
if (hr != NOERROR || (di.dwDescriptionId >= SHDID_COMPUTER_DRIVE35 &&
|
|
di.dwDescriptionId <= SHDID_COMPUTER_OTHER))
|
|
{
|
|
|
|
lpdcid = CoTaskMemAlloc(sizeof(DC_ITEMDATA));
|
|
|
|
//lpdcid->pidl = IL_Copy(pidlEntry);
|
|
lpdcid->pidl = pidlEntry;
|
|
lpdcid->lpsf = lpsf;
|
|
|
|
lpsf->lpVtbl->AddRef(lpsf);
|
|
|
|
// Insert sorted ...
|
|
{
|
|
COMBOBOXEXITEM cbei2;
|
|
cbei2.mask = CBEIF_LPARAM;
|
|
cbei2.iItem = 0;
|
|
|
|
while ((SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei2)))
|
|
{
|
|
LPDC_ITEMDATA lpdcid2 = (LPDC_ITEMDATA)cbei2.lParam;
|
|
HRESULT hr2 = (lpdcid->lpsf->lpVtbl->CompareIDs(
|
|
lpdcid->lpsf,
|
|
0,
|
|
lpdcid->pidl,
|
|
lpdcid2->pidl));
|
|
|
|
if ((short)(SCODE_CODE(GetScode(hr2))) < 0)
|
|
break;
|
|
else
|
|
cbei2.iItem++;
|
|
}
|
|
|
|
cbei.iItem = cbei2.iItem;
|
|
cbei.lParam = (LPARAM)lpdcid;
|
|
SendMessage(hwnd,CBEM_INSERTITEM,0,(LPARAM)&cbei);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // IEnumIDList::Next()
|
|
|
|
lpe->lpVtbl->Release(lpe);
|
|
|
|
} // IShellFolder::EnumObjects()
|
|
|
|
lpsf->lpVtbl->Release(lpsf);
|
|
|
|
} // IShellFolder::BindToObject()
|
|
|
|
CoTaskMemFree(pidl);
|
|
|
|
} // SHGetSpecialFolderLocation()
|
|
|
|
lpsfDesktop->lpVtbl->Release(lpsfDesktop);
|
|
|
|
} // SHGetDesktopFolder()
|
|
|
|
|
|
SendMessage(hwnd,WM_SETREDRAW,1,0);
|
|
// Return number of items added to combo box
|
|
return ((int)SendMessage(hwnd,CB_GETCOUNT,0,0));
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DriveBox_GetSelDrive
|
|
//
|
|
bool DriveBox_GetSelDrive(HWND hwnd,LPWSTR lpszDrive,int nDrive,bool fNoSlash)
|
|
{
|
|
|
|
COMBOBOXEXITEM cbei;
|
|
LPDC_ITEMDATA lpdcid;
|
|
int i = (int)SendMessage(hwnd,CB_GETCURSEL,0,0);
|
|
|
|
// CB_ERR means no Selection
|
|
if (i == CB_ERR)
|
|
return false;
|
|
|
|
// Get DC_ITEMDATA* of selected Item
|
|
cbei.mask = CBEIF_LPARAM;
|
|
cbei.iItem = i;
|
|
SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
|
|
lpdcid = (LPDC_ITEMDATA)cbei.lParam;
|
|
|
|
// Get File System Path for Drive
|
|
IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,lpszDrive,nDrive);
|
|
|
|
// Remove Backslash if required (makes Drive relative!!!)
|
|
if (fNoSlash)
|
|
PathRemoveBackslash(lpszDrive);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DriveBox_SelectDrive
|
|
//
|
|
bool DriveBox_SelectDrive(HWND hwnd,LPCWSTR lpszPath)
|
|
{
|
|
|
|
COMBOBOXEXITEM cbei;
|
|
WCHAR szRoot[64] = { L'\0' };
|
|
|
|
int i;
|
|
int cbItems = (int)SendMessage(hwnd,CB_GETCOUNT,0,0);
|
|
|
|
// No Drives in Combo Box
|
|
if (!cbItems)
|
|
return false;
|
|
|
|
cbei.mask = CBEIF_LPARAM;
|
|
|
|
for (i = 0; i < cbItems; i++)
|
|
{
|
|
// Get DC_ITEMDATA* of Item i
|
|
cbei.iItem = i;
|
|
SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
|
|
LPDC_ITEMDATA lpdcid = (LPDC_ITEMDATA)cbei.lParam;
|
|
|
|
// Get File System Path for Drive
|
|
IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szRoot,64);
|
|
|
|
// Compare Root Directory with Path
|
|
if (PathIsSameRoot(lpszPath,szRoot))
|
|
{
|
|
// Select matching Drive
|
|
SendMessage(hwnd,CB_SETCURSEL,i,0);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
// Don't select anything
|
|
SendMessage(hwnd,CB_SETCURSEL,(WPARAM)-1,0);
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DriveBox_PropertyDlg()
|
|
//
|
|
// Shows standard Win95 Property Dlg for selected Drive
|
|
//
|
|
bool DriveBox_PropertyDlg(HWND hwnd)
|
|
{
|
|
|
|
COMBOBOXEXITEM cbei;
|
|
LPDC_ITEMDATA lpdcid;
|
|
int iItem;
|
|
LPCONTEXTMENU lpcm;
|
|
CMINVOKECOMMANDINFO cmi;
|
|
bool bSuccess = true;
|
|
|
|
static const char *lpVerb = "properties";
|
|
|
|
iItem = (int)SendMessage(hwnd,CB_GETCURSEL,0,0);
|
|
|
|
if (iItem == CB_ERR)
|
|
return false;
|
|
|
|
cbei.mask = CBEIF_LPARAM;
|
|
cbei.iItem = iItem;
|
|
SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
|
|
lpdcid = (LPDC_ITEMDATA)cbei.lParam;
|
|
|
|
if (NOERROR == lpdcid->lpsf->lpVtbl->GetUIObjectOf(
|
|
lpdcid->lpsf,
|
|
GetParent(hwnd), // Owner
|
|
1, // Number of objects
|
|
&lpdcid->pidl, // pidl
|
|
&IID_IContextMenu,
|
|
NULL,
|
|
&lpcm))
|
|
{
|
|
|
|
cmi.cbSize = sizeof(CMINVOKECOMMANDINFO);
|
|
cmi.fMask = 0;
|
|
cmi.hwnd = GetParent(hwnd);
|
|
cmi.lpVerb = lpVerb;
|
|
cmi.lpParameters = NULL;
|
|
cmi.lpDirectory = NULL;
|
|
cmi.nShow = SW_SHOWNORMAL;
|
|
cmi.dwHotKey = 0;
|
|
cmi.hIcon = NULL;
|
|
|
|
if (NOERROR != lpcm->lpVtbl->InvokeCommand(lpcm,&cmi))
|
|
bSuccess = false;
|
|
|
|
lpcm->lpVtbl->Release(lpcm);
|
|
|
|
}
|
|
|
|
else
|
|
bSuccess = false;
|
|
|
|
return(bSuccess);
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DriveBox_DeleteItem
|
|
//
|
|
LRESULT DriveBox_DeleteItem(HWND hwnd,LPARAM lParam)
|
|
{
|
|
|
|
NMCOMBOBOXEX *lpnmcbe;
|
|
COMBOBOXEXITEM cbei;
|
|
LPDC_ITEMDATA lpdcid;
|
|
|
|
lpnmcbe = (LPVOID)lParam;
|
|
cbei.iItem = lpnmcbe->ceItem.iItem;
|
|
|
|
cbei.mask = CBEIF_LPARAM;
|
|
SendMessage(hwnd,CBEM_GETITEM,0,(LPARAM)&cbei);
|
|
lpdcid = (LPDC_ITEMDATA)cbei.lParam;
|
|
|
|
// Free pidl
|
|
CoTaskMemFree(lpdcid->pidl);
|
|
// Release lpsf
|
|
lpdcid->lpsf->lpVtbl->Release(lpdcid->lpsf);
|
|
|
|
// Free lpdcid itself
|
|
CoTaskMemFree(lpdcid);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// DriveBox_GetDispInfo
|
|
//
|
|
LRESULT DriveBox_GetDispInfo(HWND hwnd,LPARAM lParam)
|
|
{
|
|
|
|
NMCOMBOBOXEX *lpnmcbe;
|
|
LPDC_ITEMDATA lpdcid;
|
|
SHFILEINFO shfi;
|
|
WCHAR szTemp[MAX_PATH] = { L'\0' };
|
|
|
|
lpnmcbe = (LPVOID)lParam;
|
|
lpdcid = (LPDC_ITEMDATA)lpnmcbe->ceItem.lParam;
|
|
|
|
if (!lpdcid)
|
|
return false;
|
|
|
|
// Get Display Name
|
|
if (lpnmcbe->ceItem.mask & CBEIF_TEXT)
|
|
IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_NORMAL,lpnmcbe->ceItem.pszText,lpnmcbe->ceItem.cchTextMax);
|
|
|
|
// Get Icon Index
|
|
if (lpnmcbe->ceItem.mask & (CBEIF_IMAGE | CBEIF_SELECTEDIMAGE))
|
|
{
|
|
DWORD dwAttributes = 0;
|
|
// get attributes of the shell object using its pidl.
|
|
lpdcid->lpsf->lpVtbl->GetAttributesOf(lpdcid->lpsf, 1, &lpdcid->pidl, &dwAttributes);
|
|
|
|
DWORD attr = 0;
|
|
if ((dwAttributes & SFGAO_FOLDER) == SFGAO_FOLDER)
|
|
attr = FILE_ATTRIBUTE_DIRECTORY;
|
|
else
|
|
attr = FILE_ATTRIBUTE_NORMAL;
|
|
|
|
IL_GetDisplayName(lpdcid->lpsf,lpdcid->pidl,SHGDN_FORPARSING,szTemp,MAX_PATH);
|
|
SHGetFileInfo(szTemp,attr,&shfi,sizeof(SHFILEINFO),
|
|
SHGFI_SYSICONINDEX | SHGFI_SMALLICON | SHGFI_USEFILEATTRIBUTES);
|
|
lpnmcbe->ceItem.iImage = shfi.iIcon;
|
|
lpnmcbe->ceItem.iSelectedImage = shfi.iIcon;
|
|
}
|
|
|
|
// Set values
|
|
lpnmcbe->ceItem.mask |= CBEIF_DI_SETITEM;
|
|
|
|
UNUSED(hwnd);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
//==== ItemID =================================================================
|
|
|
|
//=============================================================================
|
|
//
|
|
// IL_Create()
|
|
//
|
|
// Creates an ITEMIDLIST by concatenating pidl1 and pidl2
|
|
// cb1 and cb2 indicate the sizes of the pidls, where cb1
|
|
// can be zero and pidl1 can be NULL
|
|
//
|
|
// If cb2 is zero, the size of pidl2 is retrieved using
|
|
// IL_GetSize(pidl2)
|
|
//
|
|
LPITEMIDLIST IL_Create(LPCITEMIDLIST pidl1,UINT cb1,
|
|
LPCITEMIDLIST pidl2,UINT cb2)
|
|
{
|
|
|
|
LPITEMIDLIST pidl;
|
|
|
|
if (!pidl2)
|
|
return NULL;
|
|
|
|
if (!cb2)
|
|
cb2 = IL_GetSize(pidl2) + 2; // Space for terminating Bytes
|
|
|
|
if (!cb1)
|
|
cb1 = IL_GetSize(pidl1);
|
|
|
|
// Allocate Memory
|
|
pidl = CoTaskMemAlloc(cb1 + cb2);
|
|
|
|
// Init new ITEMIDLIST
|
|
if (pidl1)
|
|
CopyMemory(pidl,pidl1,cb1);
|
|
|
|
// pidl2 can't be NULL here
|
|
CopyMemory((LPBYTE)pidl + cb1,pidl2,cb2);
|
|
|
|
return pidl;
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// IL_GetSize()
|
|
//
|
|
// Retrieves the number of bytes in a pidl
|
|
// Does not add space for zero terminators !!
|
|
//
|
|
UINT IL_GetSize(LPCITEMIDLIST pidl)
|
|
{
|
|
|
|
LPITEMIDLIST pidlTmp;
|
|
UINT cb = 0;
|
|
|
|
if (!pidl)
|
|
return 0;
|
|
|
|
for (pidlTmp = (LPITEMIDLIST)pidl;
|
|
pidlTmp->mkid.cb;
|
|
pidlTmp = _IL_Next(pidlTmp))
|
|
|
|
cb += pidlTmp->mkid.cb;
|
|
|
|
|
|
return cb;
|
|
|
|
}
|
|
|
|
|
|
//=============================================================================
|
|
//
|
|
// IL_GetDisplayName()
|
|
//
|
|
// Gets the Display Name of a pidl. lpsf is the parent IShellFolder Interface
|
|
// dwFlags specify a SHGDN_xx value
|
|
//
|
|
bool IL_GetDisplayName(LPSHELLFOLDER lpsf,
|
|
LPCITEMIDLIST pidl,
|
|
DWORD dwFlags,
|
|
LPWSTR lpszDisplayName,
|
|
int nDisplayName)
|
|
{
|
|
STRRET str;
|
|
|
|
if (NOERROR == lpsf->lpVtbl->GetDisplayNameOf(lpsf,
|
|
pidl,
|
|
dwFlags,
|
|
&str))
|
|
{
|
|
return StrRetToBuf(&str,pidl,lpszDisplayName,nDisplayName);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
/// End of Dlapi.c \\\
|