找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 2567|回复: 3

如何恢复快捷方式的"查找目标"功能

[复制链接]
发表于 2007-5-8 15:26:35 | 显示全部楼层 |阅读模式
刚装好的系统发现右击快捷方式查找目标点了没反应!
重新注册了SHELL32.DLL之后还是不行!
用了好多修复工具也还不行!
本人又不想再重装系统..
请问一下个位高手有什么解决的方法?:'(
发表于 2007-5-8 16:20:59 | 显示全部楼层
先查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的测试。



在网上找的,不知道是不是你想要的
回复

使用道具 举报

发表于 2007-5-8 17:39:03 | 显示全部楼层
原帖由 kices 于 2007-5-8 16:20 发表
先查MSDN98,大家不要见笑,我现在一直都用它,没有相应的API,后又. Net 2003中的MSDN,找到了可以实现该功能的API,SHOpenFolderAndSelectItems()函数,它的原型如下:
(具体用法参考MSDN)“Opens a Micro ...

这些代码怎么用啊
回复

使用道具 举报

发表于 2007-5-8 20:49:59 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1|闽公网安备35020302032614号 )

GMT+8, 2026-4-20 01:59

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表