拖动控制面板项时,错误的PIDL来自CIDA

时间:2010-12-30 03:05:41

标签: windows winapi windows-shell

我现在正在处理拖放问题,并尝试将项目的PIDL从Windows shell拖到我的应用程序。

如果拖动的项目是“我的电脑”或“控制面板”本身,下面的代码可以获得正确的PIDL,但是当拖动的项目是“控制面板”中的项目时它不起作用。

我的代码出了什么问题?


#define GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
#define GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])

STGMEDIUM medium;

UINT fmt = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
FORMATETC fe= {fmt, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
HRESULT GETDATA_RESULT = pDataObject->GetData(&fe, &medium);

if (SUCCEEDED(GETDATA_RESULT))
{
    LPIDA pida = (LPIDA)GlobalLock(medium.hGlobal);
    LPCITEMIDLIST pidlFolder = GetPIDLFolder(pida);

    int n = pida->cidl;  // the n is always correct
    if( n > 0 )
    {
        LPCITEMIDLIST pidlItem = GetPIDLItem(pida, 0);
        // the pidlItem is wrong when the dragged object is an item in 'Control Panel'
    }

    GlobalUnlock(medium.hGlobal);
}
ReleaseStgMedium(&medium);

有什么想法吗?谢谢

扎克@闪耀

1 个答案:

答案 0 :(得分:3)

如果我是D& D鼠标,网络连接和字体,我在测试应用程序中获得以下输出:

  • 0 Mouse | sfgao=4 hr=0
  • 1 ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\::{7007ACC7-3202-11D1-AAD2-00805FC1270E} | sfgao=20000004 hr=0
  • 2 C:\WINDOWS\Fonts | sfgao=60000004 hr=0

网络连接和字体pidl可以转换为完全限定的shell路径,而Mouse只返回相对路径/显示名称。   如果您查看IShellFolder :: GetDisplayNameOf:

的文档,这是有道理的
  

......他们不保证这一点   IShellFolder将返回请求的内容   形式的名称。如果那个表格不是   可用,可能是另一个   回。特别是没有   保证返回的名称   SHGDN_FORPARSING标志将是   成功解析   的IShellFolder :: ParseDisplayName。那里   也是一些旗帜的组合   这可能会导致   GetDisplayNameOf / ParseDisplayName   往返不归还原件   标识符列表。这种情况是   特殊,但你应该检查   一定不会。

很明显,在处理controlpanel项目时,您需要保持pidl并且只使用GetDisplayNameOf来显示UI中的显示字符串。 (鼠标pidl上的IShellLink :: SetIDList将创建一个工作快捷方式,因此pidl有效)

void OnDrop(IDataObject*pDO) 
{
    STGMEDIUM medium;
    UINT fmt = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
    FORMATETC fe= {fmt, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
    HRESULT hr = pDO->GetData(&fe, &medium);
    if (SUCCEEDED(hr)) 
    {
        LPIDA pida = (LPIDA)GlobalLock(medium.hGlobal);
        if (pida) 
        {
            LPCITEMIDLIST pidlFolder = GetPIDLFolder(pida);
            for (UINT i=0; i<pida->cidl; ++i) 
            {
                LPCITEMIDLIST pidlItem = GetPIDLItem(pida,i);
                LPITEMIDLIST pidlAbsolute = ILCombine(pidlFolder,pidlItem);
                if (pidlAbsolute) 
                {
                    IShellFolder*pParentSF;
                    hr= SHBindToParent(pidlAbsolute,IID_IShellFolder,(void**)&pParentSF,&pidlItem);
                    if (SUCCEEDED(hr))
                    {
                        STRRET str; 
                        hr= pParentSF->GetDisplayNameOf(pidlItem, SHGDN_FORPARSING, &str);
                        if (SUCCEEDED(hr))
                        {
                            TCHAR szName[MAX_PATH];
                            hr= StrRetToBuf(&str,pidlItem,szName,MAX_PATH);
                            if (SUCCEEDED(hr)) 
                            {
                                SFGAOF sfgao = SFGAO_FOLDER|SFGAO_FILESYSTEM|SFGAO_HASSUBFOLDER|SFGAO_CANLINK;
                                hr= pParentSF->GetAttributesOf(1,&pidlItem,&sfgao);
                                TRACE(_T("%u %s | sfgao=%X hr=%X\n"),i,szName,sfgao,hr);
                                CreateTestShortcut(pidlAbsolute);
                            }
                        }
                        pParentSF->Release();
                    }
                    ILFree(pidlAbsolute);
                }
            }
            GlobalUnlock(medium.hGlobal);
        }
        ReleaseStgMedium(&medium);
    }
}
相关问题