我现在正在处理一个拖放问题,并试图将从windows shell拖动到我的应用程序中的项目的pidl。
如果被拖动的项是“我的电脑”或“控制面板”本身,则下面的代码可以获得正确的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);

有什么想法吗?谢谢
扎克@闪耀

最佳答案

如果我开发鼠标、网络连接和字体,我将在测试应用程序中获得以下输出:
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路径,而鼠标只返回相对路径/displayname。
如果检查IShellFolder::GetDisplayNameOf的文档,这是有意义的:
…他们不能保证
IShellFolder将返回请求的
名字的形式。如果那张表格不是
有,另一个可能是
返回.尤其是,没有
保证返回的名称
shgdn_for parsing标志将是
分析成功者
IShellFolder::分析显示名称。那里
也是一些旗帜的组合
可能会导致
getdisplaynameof/parsedisplayname
往返不还原物
标识符列表。这次事件是
例外,但你应该检查
一定要。
很明显,在处理controlpanel项时,需要保留pidl,并且只对ui中的显示字符串使用getdisplaynameof。
(鼠标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);
    }
}

关于windows - 拖动控制面板项目时,CIDA收到错误的PIDL,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4559717/

10-11 22:58