C++ 显示不同目录中文件的“文件属性”对话框
我试图打开“默认文件属性”对话框,但无法为不同目录中的文件获取其工作属性。 我需要为不同目录(甚至驱动器)中的文件获取C++ 显示不同目录中文件的“文件属性”对话框,c++,winapi,com,C++,Winapi,Com,我试图打开“默认文件属性”对话框,但无法为不同目录中的文件获取其工作属性。 我需要为不同目录(甚至驱动器)中的文件获取IContextMenu*接口指针。 我希望在“属性”对话框中看到“各种文件夹” 这是我天真的做法: int main() { CoInitialize(NULL); LPOLESTR pszFile = OLESTR("c:\\Windows\\notepad.exe"); LPOLESTR pszFile2 = OLESTR("c:\\Windows\
IContextMenu*
接口指针。
我希望在“属性”对话框中看到“各种文件夹”
这是我天真的做法:
int main() {
CoInitialize(NULL);
LPOLESTR pszFile = OLESTR("c:\\Windows\\notepad.exe");
LPOLESTR pszFile2 = OLESTR("c:\\Windows\\System32\\notepad.exe");
LPITEMIDLIST pidl;
LPITEMIDLIST pidl2;
LPCITEMIDLIST pidlItem;
LPCITEMIDLIST pidlItem2;
HRESULT hr;
IShellFolder* pFolder;
IContextMenu* pContextMenu;
CMINVOKECOMMANDINFO cmi;
hr = SHGetDesktopFolder(&pFolder);
if (FAILED(hr)) return 0;
hr = pFolder->ParseDisplayName(HWND_DESKTOP, NULL, pszFile, NULL, &pidl, NULL);
hr = pFolder->ParseDisplayName(HWND_DESKTOP, NULL, pszFile2, NULL, &pidl2, NULL);
pFolder->Release();
if (FAILED(hr)) return 0;
hr = SHBindToParent(pidl, IID_IShellFolder, (void **)&pFolder, &pidlItem);
if (FAILED(hr)) {
SHFree(pidl);
return 0;
}
//pFolder->Release();
hr = SHBindToParent(pidl2, IID_IShellFolder, (void **)&pFolder, &pidlItem2);
if (FAILED(hr)) {
SHFree(pidl2);
return 0;
}
LPCITEMIDLIST list[] = {pidlItem, pidlItem2};
hr = pFolder->GetUIObjectOf(HWND_DESKTOP, 2, (LPCITEMIDLIST *)list, IID_IContextMenu, NULL, (void **)&pContextMenu);
pFolder->Release();
if (SUCCEEDED(hr)) {
ZeroMemory(&cmi, sizeof(cmi));
cmi.cbSize = sizeof(cmi);
cmi.lpVerb = "properties";
cmi.nShow = SW_SHOWNORMAL;
hr = pContextMenu->InvokeCommand(&cmi);
MessageBox(0, _T("Dummy message box"), 0, 0);
Sleep(10000); // Give the system time to show the dialog before exiting
pContextMenu->Release();
}
SHFree(pidl);
return 0;
}
我也试过了,但也没用。
我还尝试使用桌面IShellFolder作为我的PIDL的父级,但它也不起作用
有什么想法吗
IShellFolder::GetUIObjectOf()
仅适用于与所查询的IShellFolder
相关的单级PIDL。这在以下文件中明确说明:
指向ITEMIDLIST结构的指针数组的地址,每个指针唯一地标识相对于父文件夹的文件对象或子文件夹。每个项目标识符列表必须只包含一个SHITEMID结构,后跟一个终止零
您正在将两个绝对PIDL转换为各自文件夹的相对PIDL,但随后使用Windows\System32
文件夹的IShellFolder
检索两个文件的IContextMenu
。这对于属于Windows\
文件夹的相对PIDL不起作用,因为Windows\System32
文件夹的IShellFolder
只知道Windows\System32
文件夹中的文件
各种在线示例显示了当涉及多个文件时,从桌面的IShellFolder
查询IContextMenu
。这种方法仅在文件位于同一父文件夹(如中所示)时有效。当文件位于不同的文件夹中时,事情会变得更加复杂
代码中也有一些内存泄漏
处理这种情况的正确方法是使用以下功能:
显示一组文件的合并属性页。将显示所有文件共有的特性值,而不同的特性值将显示字符串(多个值)
使用桌面的IShellFolder
获取绝对PIDL的IDataObject
(这是允许GetUIObjectOf()
违反“每个项目标识符列表必须正好包含一个SHITEMID结构”规则的一次),然后将其传递给SHMultiFileProperties()
。例如:
int main()
{
CoInitialize(NULL);
LPOLESTR pszFile = OLESTR("c:\\Windows\\notepad.exe");
LPOLESTR pszFile2 = OLESTR("c:\\Windows\\System32\\notepad.exe");
LPITEMIDLIST pidl;
LPITEMIDLIST pidl2;
HRESULT hr;
IShellFolder* pDesktop;
IDataObject *pDataObject;
hr = SHGetDesktopFolder(&pDesktop);
if (FAILED(hr))
{
CoUninitialize();
return 0;
}
hr = pDesktop->ParseDisplayName(HWND_DESKTOP, NULL, pszFile, NULL, &pidl, NULL);
if (FAILED(hr)) {
pDesktop->Release();
CoUninitialize();
return 0;
}
hr = pDesktop->ParseDisplayName(HWND_DESKTOP, NULL, pszFile2, NULL, &pidl2, NULL);
if (FAILED(hr)) {
SHFree(pidl);
pDesktop->Release();
CoUninitialize();
return 0;
}
LPCITEMIDLIST list[] = {pidl, pidl2};
hr = pDesktop->GetUIObjectOf(HWND_DESKTOP, 2, (LPCITEMIDLIST *)list, IID_IDataObject, NULL, (void **)&pDataObject);
// alternatively, you can also use SHCreateDataObject() or CIDLData_CreateFromIDArray() to create the IDataObject
pDesktop->Release();
SHFree(pidl);
SHFree(pidl2);
if (SUCCEEDED(hr)) {
hr = SHMultiFileProperties(pDataObject, 0);
pDataObject->Release();
if (SUCCEEDED(hr)) {
MessageBox(0, _T("Dummy message box"), 0, 0);
Sleep(10000); // Give the system time to show the dialog before exiting
}
}
CoUninitialize();
return 0;
}
这是否意味着无法使用
IContextMenu
存档相同的行为?据我所知,文件管理器分别处理菜单项“属性”并执行SHMultiFileProperties
,而不是用于所有其他菜单项的IContextMenu::InvokeCommand
?但显示的菜单功能齐全,您可以复制、剪切、删除选定的文件,即使这些文件位于不同的目录中。使用IContextMenu
可以实现,但并不容易。Raymond Chen说:“您必须编写自己的复合上下文菜单。查找文件就是这样做的……这并不容易。您必须获取UIObjectOf(IContextMenu)对于组中的每个对象,然后取所有菜单项的交集,并将其作为组合的上下文菜单。或者,如果存在多个不同文件类型的文件,则可以执行“查找文件”的操作并将其下注。”不过,我怀疑编写“复合上下文菜单”是否适用于调用“属性”对话框。在对实现相同谓词的文件调用非可视操作时,这会更有意义。您只需在收集的IContextMenu
对象中循环,对每个对象调用所需的谓词。有趣的观察结果是,Total Commander的属性对话框对于不同驱动器上的文件无法正常工作(“常规”选项卡缺失)。这意味着TotalCmd不使用SHMultiFileProperties
函数。当我使用IContextMenu
编写测试代码,并使用CSIDL\u驱动器
或类似于PIDL父级的东西编写测试代码时,我也遇到了同样的问题。您可以尝试使用(及其相关兄弟)为跨多个文件夹的文件获取IContextMenu
。有关此主题的讨论,请参阅。