我现在正在处理拖放问题,并尝试将项目的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);
有什么想法吗?谢谢
扎克@闪耀
答案 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);
}
}