| 首页 | 新闻 | 网页 | 设计 | 色彩 | 原创 | 视觉 | 素材 | 动漫 | 酷站 | 策划 | 文案 | 访谈 | 运营 | 编程 | 数据库 | 服务器 | 下载 | 图库 | 
您的位置: 幽幽天空 > 网页 > 编程开发 > Visual C++教程 > 文章正文 用户登录
为什么创业者总是
如何实现SWF转VCD
SWF高质量转换为V
SWF转VCD完整篇
FLASH转化为VCD 没
用V2组件制作单选
使用Visual Studi
在VC中用OLE DB读
用VC程序来创建SQ
用VB编写抽奖程序

用VC6.0实现快捷方式中的查找目标功能           

用VC6.0实现快捷方式中的查找目标功能

作者:佚名 来源:不详 更新:2006-8-25 21:05:35 错误报告 我要投稿
  最近写一个开发辅助工具,在这个过程要做一个类似文件快捷方式中查找目标的功能,先查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的测试。
文章录入:skyuu    责任编辑:skyuu 
  • 上一篇文章:

  • 下一篇文章:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    发表评论:
    姓名:  评 分: 1分 2分 3分 4分 5分
     
  • 严禁发表危害国家安全、政治、黄色淫秽等内容的评论。
  • 用户需对自己在使用幽幽天空服务过程中的行为承担法律责任。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表机友个人观点,与本网站立场无关。