最近寫一個開發輔助工具,在這個過程要做一個類似文件快捷方式中查找目標的功能,先查MSDN98,大家不要見笑,我現在一直都用它,沒有相應的API,后又. Net 2003中的MSDN,找到了可以實現該功能的API,SHOpenFolderAndSelectItems()函數,它的原型如下:
(具體用法參考MSDN)“Opens a Microsoft® Windows® Explorer window with specified items in a particular folder selected.”
HRESULT SHOpenFolderAndSelectItems( LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST *apidl, DWORD dwFlags ); 但是,它需要Windows XP及上,若在Win2000或Win98如何實現它呢?于是我就上網搜索,幾經周折最終搜到的一篇文章,但它只是利用工具通過反匯編Windows API函數得到的代碼,可能可以實現與快捷方式相同的對話框(我沒有試過),但其代碼可讀性非常差,我只能參考一下大概的流程,他提到一個非常重要的一點,那就是使用一個未公開的API函數SHGetIDispatchForFolder,它可幫助我打開文件夾。好不多說了,下面是關鍵的部分:
查找目標功能,分為兩個步驟,首先打開或找到目標文件所在的文件夾,其次在打開的文件夾中選中相應的項目(即文件)。在說這個步驟之前,先認識一下,下面兩個結構
typedef struct _SHITEMID { USHORT cb; BYTE abID[1]; } SHITEMID, * LPSHITEMID; typedef const SHITEMID * LPCSHITEMID;
typedef struct _ITEMIDLIST { SHITEMID mkid; } ITEMIDLIST, * LPITEMIDLIST; typedef const ITEMIDLIST * LPCITEMIDLIST;
這兩個結構的數據保存的是項目定義符列表(僅是字面翻譯),這個結構所表示的文件夾及文件除了正常的,還包括一些特殊的文件夾及文件(如目錄,我的電腦等),SHGetIDispatchForFolder函數正是用它的做為參數,可以打開一些特殊的文件夾。SHGetIDispatchForFolder函數的原型是 : HRESULT (WINAPI*gpfSHGetIDispatchForFolder)(ITEMIDLIST* pidl, IWebBrowserApp** ppIWebBrowserApp); 通常快捷方式給我的ITEMIDLIST是包含文件名的,若直接調用上面的函數,它將直接會打開出目標文件,而不是打開文件夾。下面是區分文件及文件夾的代碼:
pIdlFile = pidl; /// 找出目標文件中文件名的偏移量 while (cb = pIdlFile->mkid.cb) { pidl2 = pIdlFile; pIdlFile = (ITEMIDLIST*)((BYTE*)pIdlFile + cb); }
cb = pidl2->mkid.cb; pidl2->mkid.cb = 0; 下面是打開文件夾及選中文件的代碼,相信大家不難理解。 /// 打開目標文件所在的文件夾 if (SUCCEEDED(GetShellFolderViewDual(pidl, &pIShellFolderViewDual))) { pidl2->mkid.cb = cb; // 0 Deselect the item. // 1 Select the item. // 3 Put the item in edit mode. // 4 Deselect all but the specified item. // 8 Ensure the item is displayed in the view. // 0x10 Give the item the focus. COleVariant bszFile(pidl2); if(pIShellFolderViewDual != NULL) { /// 選中相應的選項 pIShellFolderViewDual->SelectItem(bszFile, 0x1d); pIShellFolderViewDual->Release(); } return TRUE; } 源代碼中包含了一個DEMO。下面是完整的函數,可以直接調用FindTarget(CString str)參數為文件名,若是快捷方式則會自動指向其目標。若代碼中已做過COM的初始化工作,請刪除CoInitialize(NULL);及CoUninitialize();語句。
HRESULT GetShellFolderViewDual(ITEMIDLIST* pidl, IShellFolderViewDual** ppIShellFolderViewDual) { IWebBrowserApp* pIWebBrowserApp; IDispatch* pDoc; HWND hWnd; HRESULT hr; HINSTANCE ghSHDOCVW;
HRESULT (WINAPI*gpfSHGetIDispatchForFolder)(ITEMIDLIST* pidl, IWebBrowserApp** ppIWebBrowserApp);
*ppIShellFolderViewDual = NULL;
ghSHDOCVW = LoadLibrary(_T("SHDOCVW.DLL")); if (ghSHDOCVW == NULL) return FALSE;
pIWebBrowserApp=NULL; gpfSHGetIDispatchForFolder = (HRESULT (WINAPI*)(ITEMIDLIST*, IWebBrowserApp**)) GetProcAddress(ghSHDOCVW, "SHGetIDispatchForFolder"); if (gpfSHGetIDispatchForFolder == NULL) return FALSE;
/// 調用未公開的API函數 SHGetIDispatchForFolder if (SUCCEEDED(gpfSHGetIDispatchForFolder(pidl, &pIWebBrowserApp))) { if (SUCCEEDED(pIWebBrowserApp->get_HWND((long*)&hWnd))) { SetForegroundWindow(hWnd); ShowWindow(hWnd, SW_SHOWNORMAL); }
if (SUCCEEDED(hr = pIWebBrowserApp->get_Document(&pDoc))) { pDoc->QueryInterface(IID_IShellFolderViewDual, (void**) ppIShellFolderViewDual); pDoc->Release(); }
pIWebBrowserApp->Release(); } FreeLibrary(ghSHDOCVW);
return TRUE; }
BOOL XZSHOpenFolderAndSelectItems(ITEMIDLIST *pidlFolder) { ITEMIDLIST *pidl, *pidl2; ITEMIDLIST* pIdlFile; USHORT cb; IShellFolderViewDual* pIShellFolderViewDual; [1] [2] 下一頁
|