王朝网络
分享
 
 
 

如何实现快捷方式中的查找目标功能

王朝vc·作者佚名  2006-01-17
宽屏版  字体: |||超大  

如何实现快捷方式中的查找目标功能

作者:梁永喜

下载源代码

最近写一个开发辅助工具,在这个过程要做一个类似文件快捷方式中查找目标的功能,先查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;

HRESULT (WINAPI *gpfSHOpenFolderAndSelectItems)(LPCITEMIDLIST *pidlFolder, UINT cidl, LPCITEMIDLIST *apidl, DWORD dwFlags);

HINSTANCE ghShell32;

/// 只有WinXp及以上及系统才支持SHOpenFolderAndSelectItems() API

/// 那其它系统该怎么实现这个功能呢?只能采用其它的方法来处理

/// 首先用XP跟踪到SHOpenFolderAndSelectItems()API中,看它是如何处理的,再用同样的方法去实现

/// 其它系统的这个功能使用工具 VC6 .net 2003 MSDN Ollydbg v1.10中文版

ghShell32 = LoadLibrary(_T("Shell32.DLL"));

if (ghShell32 == NULL)

return FALSE;

gpfSHOpenFolderAndSelectItems =

(HRESULT (WINAPI*)(LPCITEMIDLIST*, UINT, LPCITEMIDLIST*, DWORD)) GetProcAddress(ghShell32, "SHOpenFolderAndSelectItems");

if (gpfSHOpenFolderAndSelectItems != NULL)

{

/// 可以获得SHOpenFolderAndSelectItems()函数的API地址

if (SUCCEEDED(gpfSHOpenFolderAndSelectItems((LPCITEMIDLIST*)pidlFolder,0,(LPCITEMIDLIST*)NULL,0)))

{

///直接调用系统的功能

FreeLibrary(ghShell32);

return TRUE;

}

FreeLibrary(ghShell32);

return FALSE;

}

FreeLibrary(ghShell32);

/// 当操作系统不支持SHOpenFolderAndSelectItems()函数的API时的处理,

/// 自已动手写一个与系统功能相同的代码

pidl = pidlFolder;

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;

}

return FALSE;

}

void FindTarget(CString str)

{

HRESULT hres;

IShellLink *psl;

ITEMIDLIST *pidl;

IPersistFile *ppf;

CoInitialize(NULL);

// Get a pointer to the IShellLink interface.

hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,

IID_IShellLink, (LPVOID*)&psl);

if (SUCCEEDED(hres))

{

// 设置目标文件

psl->SetPath(str);

/// 获得目标文件的ITEMIDLIST

psl->GetIDList(&pidl);

// Get a pointer to the IPersistFile interface.

hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);

if (SUCCEEDED(hres))

{

WCHAR wsz[MAX_PATH];

#ifdef _UNICODE

wcscpy(wsz, str);

#else

// Ensure that the string is Unicode.

MultiByteToWideChar(CP_ACP, 0, str, -1, wsz, MAX_PATH);

#endif

// Load the shortcut.

hres = ppf->Load(wsz, STGM_READ);

if (SUCCEEDED(hres))

{

/// 获得快捷方式的ITEMIDLIST

psl->GetIDList(&pidl);

}m

ppf->Release();

}

/// 打开文件夹并选中项目

XZSHOpenFolderAndSelectItems(pidl);

psl->Release();

}

CoUninitialize();

}

在VC6下编译后的代码,通过98,2k,XP的测试。

参考文章

http://www.pediy.com/bbshtml/BBS6/pediy6789.htm

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有