[转帖]调用explore打开指定文件所在的文件夹,并把目标文件设为选定状态,甚至.lnk文件也能自动找到它的目标执行程序文件。

来源:互联网 发布:cnki专利数据库 编辑:程序博客网 时间:2024/05/17 02:40
 

添加自定义的三个全局函数GetShellFolderViewDual、XZSHOpenFolderAndSelectItems和FindTarget,注意它们的先后顺序,用的时候使用如下方式就行了:
--------------------------------------------
CString strFileName="c://readme.txt";
FindTarget(strFileName);
--------------------------------------------

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中文版

 //显式链接Shell32.dll
 ghShell32 = LoadLibrary(_T("Shell32.DLL"));
 if (ghShell32 == NULL)
  return FALSE;
 //从Shell32.dll中找到SHOpenFolderAndSelectItems函数的地址
 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时的处理,
 /// 自已动手写一个与系统功能相同的代码

 pIdlFile = pidl= pidlFolder;
 /// 找出目标文件的偏移量
 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;
//用下面这个函数先初始化COM库,并把当前线程设为单线程模式(single-thread apartment(STA)),以便后面使用COM库函数
CoInitialize(NULL);  

 //获得IShellLink接口的指针,放在psl中
 hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
       IID_IShellLink, (LPVOID*)&psl);
 if (SUCCEEDED(hres))
 {
  // 设置目标文件
  psl->SetPath(str);
  /// 获得目标文件的ITEMIDLIST
  psl->GetIDList(&pidl);

  //获得IPersistFile接口的指针,放在ppf中
  hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf);
  if (SUCCEEDED(hres))
  {
   WCHAR wsz[MAX_PATH];           //    <=========下面三行代码完成字符串转为Unicode
#ifdef _UNICODE
   wcscpy(wsz, str);
#else
   //把字符串转为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);
   }
   ppf->Release();
  }

  /// 打开文件夹并选中项目
  XZSHOpenFolderAndSelectItems(pidl);

  psl->Release();
 }
CoUninitialize();
}

 

原文地址:

http://blog.csdn.net/Snow_Ice11111/archive/2006/02/11/596489.aspx

原创粉丝点击