我有一个同时使用
SHCreateShellFolderView
和 SHCreateDefaultContextMenu
的命名空间扩展。我还使用 IShellFolderViewCB
和 IContextMenuCB
创建默认对象。大多数预期功能都可以正常工作。例如:我可以双击“文件夹”项目来浏览它们,然后双击“非文件夹”项目来让应用程序根据提供的路径启动。
我的
IShellFolder
“文件夹”和“非文件夹”对象都有:
dwAttributes |= SFGAO_FILESYSTEM;
dwAttributes |= SFGAO_HASPROPSHEET;
dwAttributes |= SFGAO_CANCOPY;
dwAttributes |= SFGAO_CANMOVE;
dwAttributes |= SFGAO_CANLINK;
dwAttributes |= SFGAO_CANRENAME;
dwAttributes |= SFGAO_CANDELETE;
我的每个
IShellFolder
“文件夹”(目录)对象还具有:
dwAttributes |= SFGAO_STORAGEANCESTOR;
dwAttributes |= SFGAO_STORAGE;
dwAttributes |= SFGAO_FILESYSANCESTOR;
dwAttributes |= SFGAO_FOLDER;
dwAttributes |= SFGAO_BROWSABLE;
dwAttributes |= SFGAO_HASSUBFOLDER;
dwAttributes |= SFGAO_DROPTARGET;
在这两种情况下,我都会做正确的事情:
*pdwAttributes &= dwAttributes;
当我右键单击
CDefView
中列出的“文件夹”对象之一以调出该文件夹的上下文菜单时,我可以清楚地看到 Paste
已启用(深色,不是灰色)。
当我单击
CDefView
的空白背景区域时,会调出与空白区域(不是任何列出的项目)对应的文件夹的上下文菜单,即创建的树形控件的文件夹视图中,Paste
和 Paste shortcut
存在,但始终呈灰色,无论剪贴板上有什么。
我尝试了以下方法来获取
Paste
和 Paste
快捷方式以停止变灰:
SFGAO_*
标志。IContextMenuCB::Callback
的调用。IShellFolderViewCB::MessageSFVCB
的调用。IContextmenu
中生成的 IShellFolder::CreateViewObject
的关联。IShellFolder::CreateViewObject
中生成关联的代码经过调整后目前是这样的:
else if (riid == IID_IContextMenu)
{
ASSOCIATIONELEMENT rgClasses[5];
unsigned short int i = 0;
rgClasses[i++] = { ASSOCCLASS_PROGID_STR, 0, TEXT("Directory\\Background") };
rgClasses[i++] = { ASSOCCLASS_PROGID_STR, 0, TEXT("Folder") };
rgClasses[i++] = { ASSOCCLASS_PROGID_STR, 0, TEXT("Directory") };
rgClasses[i++] = { ASSOCCLASS_PROGID_STR, 0, TEXT("AllFilesystemObjects") };
IQueryAssociations *pIQueryAssociationInfo = 0;
hr = AssocCreateForClasses(&rgClasses[0], 1, IID_PPV_ARGS(&pIQueryAssociationInfo));
if (SUCCEEDED(hr))
{
DEFCONTEXTMENU dcm = { hwndOwner, 0, this->pidl_absolute, this, 0, NULL, pIQueryAssociationInfo, 0, NULL };
hr = SHCreateDefaultContextMenu(&dcm, riid, ppvOut);
}
}
要使
Paste
和 Paste shortcut
停止为 CDefView
中的背景上下文菜单变灰,需要什么?
更新:
当用户单击视图 (ShellView) 中列出的一项或多项时,shell 会调用
IShellFolder::GetUIObjectOf
。当用户单击视图的背景 (IShellView
) 时,shell 会调用 IShellFolder::CreateViewObject
。请注意区别:单击文件夹“上”会导致 shell 选择调用哪个 Object::Method
,即使文件夹是相同的。这意味着,当用户在视图的背景(空白区域)中右键单击时,从技术上讲,用户单击了正在呈现该视图(其子视图)的文件夹。但是,由于用户以这种方式单击文件夹“上”,所以 shell 选择 IShellFolder::CreateViewObject
,而不是项目列表之一。以下调用堆栈说明了 shell 正在执行的操作。
用户单击树视图中的文件夹。 shell 调用
IShellFolder::CreateViewObject
,请求
IDropTarget
。BlockSet.dll!PartitionShellFolder::CreateViewObject(HWND__ * hwndOwner, const _GUID & riid, void * * ppvOut) Line 610 C++
shell32.dll!CDefView::CreateViewWindow3(struct IShellBrowser *,struct IShellView *,unsigned long,enum FOLDERFLAGS,enum FOLDERFLAGS,enum FOLDERVIEWMODE,struct _GUID const *,struct tagRECT const *,struct HWND__ * *) Unknown
ExplorerFrame.dll!FileCabinet_CreateViewWindow2(struct IShellBrowser *,struct tagFolderSetDataBase *,struct IShellView *,struct IShellView *,struct tagRECT *,struct HWND__ * *) Unknown
ExplorerFrame.dll!CShellBrowser::CreateViewWindow(struct IShellItem *,struct IShellView *,struct IShellView *,struct tagRECT *,struct HWND__ * *) Unknown
ExplorerFrame.dll!CShellViewFactory::_CreateNewConnection(struct HWND__ *,struct IShellItem *,struct IUnknown *,struct IUnknown * *) Unknown
ExplorerFrame.dll!CShellViewFactory::BeginCreateConnection(struct HWND__ *,struct IShellItem *,struct IUnknown *,struct IConnectionCreatedCallback *) Unknown
ExplorerFrame.dll!CShellBrowser::_CreateConnectionForItem(struct IShellItem *,unsigned long,unsigned long) Unknown
ExplorerFrame.dll!CShellBrowser::_CreateNewConnection(struct IShellItem *,unsigned long,unsigned long) Unknown
ExplorerFrame.dll!CShellBrowser::_NavigateToPidl(struct _ITEMIDLIST_ABSOLUTE const *,unsigned long,unsigned long) Unknown
ExplorerFrame.dll!CShellBrowser::_OnGoto(void) Unknown
ExplorerFrame.dll!CShellBrowser::WndProcBS(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
ExplorerFrame.dll!IEFrameWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchMessageWorker() Unknown
ExplorerFrame.dll!CExplorerFrame::FrameMessagePump(void) Unknown
ExplorerFrame.dll!BrowserThreadProc(struct IETHREADPARAM *) Unknown
ExplorerFrame.dll!BrowserNewThreadProc(void *) Unknown
ExplorerFrame.dll!CExplorerTask::InternalResumeRT(void) Unknown
ExplorerFrame.dll!CRunnableTask::Run(void) Unknown
shell32.dll!CShellTask::TT_Run(bool *) Unknown
shell32.dll!CShellTaskThread::ThreadProc(void) Unknown
shell32.dll!CShellTaskThread::s_ThreadProc(void *) Unknown
shlwapi.dll!WrapperThreadProc(void *) Unknown
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown
用户右键单击视图的空白区域 (
IShellView
)。请注意调用堆栈顶部附近名为
Def_IsPasteAvailable
的函数。在此调用堆栈之后,shell 立即调用四 (4) 个调用:IDropTarget::Enter
、IDropTarget::Leave
、IDropTarget::Enter
、IDropTarget::Leave
。BlockSet.dll!DropTarget::DragEnter(IDataObject * pDataObj, unsigned long grfKeyState, _POINTL pt, unsigned long * pdwEffect) Line 80 C++
shell32.dll!Def_IsPasteAvailable() Unknown
shell32.dll!Def_InitEditCommands() Unknown
shell32.dll!CDefView::_Create_BackgrndHMENU(unsigned int,struct _GUID const &,void * *) Unknown
shell32.dll!CDefView::_CBackgrndMenu_CreateInstance(struct _GUID const &,void * *) Unknown
shell32.dll!CDefView::GetItemObject(unsigned int,struct _GUID const &,void * *) Unknown
shell32.dll!CDefView::OnBackgroundContextMenu(struct tagPOINT const *) Unknown
ExplorerFrame.dll!UIItemsView::ShowContextMenu(struct tagPOINT const *) Unknown
ExplorerFrame.dll!CItemsView::ShowContextMenu(struct tagPOINT const *) Unknown
shell32.dll!CDefView::_OnContextMenu(__int64) Unknown
shell32.dll!CDefView::WndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
shell32.dll!CDefView::s_WndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!CallWindowProcAorW() Unknown
user32.dll!CallWindowProcW() Unknown
duser.dll!WndBridge::RawWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchClientMessage() Unknown
user32.dll!__fnDWORD() Unknown
ntdll.dll!KiUserCallbackDispatcherContinue() Unknown
user32.dll!NtUserMessageCall() Unknown
user32.dll!RealDefWindowProcWorker() Unknown
user32.dll!RealDefWindowProcW() Unknown
uxtheme.dll!_ThemeDefWindowProc(HWND__ * hwnd, unsigned int uMsg, unsigned __int64 wParam, __int64 lParam, int bUnicode) Line 1058 C++
uxtheme.dll!ThemeDefWindowProcW(HWND__ * hwnd, unsigned int uMsg, unsigned __int64 wParam, __int64 lParam) Line 1076 C++
user32.dll!DefWindowProcW() Unknown
ExplorerFrame.dll!UIItemsView::WndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
dui70.dll!DirectUI::HWNDElement::StaticWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!CallWindowProcAorW() Unknown
user32.dll!CallWindowProcW() Unknown
duser.dll!ExtraInfoWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!CallWindowProcAorW() Unknown
user32.dll!CallWindowProcW() Unknown
comctl32.dll!CallOriginalWndProc() Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!UIItemsView::_UIItemsViewSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64) Unknown
ExplorerFrame.dll!UIItemsView::s_UIItemsViewSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64,unsigned __int64) Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!CToolTipManager::_PropertyToolTipSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64) Unknown
ExplorerFrame.dll!CToolTipManager::s_PropertyToolTipSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64,unsigned __int64) Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!DefSubclassProc() Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!MasterSubclassProc() Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchMessageWorker() Unknown
ExplorerFrame.dll!CExplorerFrame::FrameMessagePump(void) Unknown
ExplorerFrame.dll!BrowserThreadProc(struct IETHREADPARAM *) Unknown
ExplorerFrame.dll!BrowserNewThreadProc(void *) Unknown
ExplorerFrame.dll!CExplorerTask::InternalResumeRT(void) Unknown
ExplorerFrame.dll!CRunnableTask::Run(void) Unknown
shell32.dll!CShellTask::TT_Run(bool *) Unknown
shell32.dll!CShellTaskThread::ThreadProc(void) Unknown
shell32.dll!CShellTaskThread::s_ThreadProc(void *) Unknown
shlwapi.dll!WrapperThreadProc(void *) Unknown
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown
shell 调用
IShellFolder::CreateViewObject
,请求
IContextMenu
:BlockSet.dll!PartitionShellFolder::CreateViewObject(HWND__ * hwndOwner, const _GUID & riid, void * * ppvOut) Line 571 C++
shell32.dll!CDefView::_CBackgrndMenu_CreateInstance(struct _GUID const &,void * *) Unknown
shell32.dll!CDefView::GetItemObject(unsigned int,struct _GUID const &,void * *) Unknown
shell32.dll!CDefView::OnBackgroundContextMenu(struct tagPOINT const *) Unknown
ExplorerFrame.dll!UIItemsView::ShowContextMenu(struct tagPOINT const *) Unknown
ExplorerFrame.dll!CItemsView::ShowContextMenu(struct tagPOINT const *) Unknown
shell32.dll!CDefView::_OnContextMenu(__int64) Unknown
shell32.dll!CDefView::WndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
shell32.dll!CDefView::s_WndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!CallWindowProcAorW() Unknown
user32.dll!CallWindowProcW() Unknown
duser.dll!WndBridge::RawWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchClientMessage() Unknown
user32.dll!__fnDWORD() Unknown
ntdll.dll!KiUserCallbackDispatcherContinue() Unknown
user32.dll!NtUserMessageCall() Unknown
user32.dll!RealDefWindowProcWorker() Unknown
user32.dll!RealDefWindowProcW() Unknown
uxtheme.dll!_ThemeDefWindowProc(HWND__ * hwnd, unsigned int uMsg, unsigned __int64 wParam, __int64 lParam, int bUnicode) Line 1058 C++
uxtheme.dll!ThemeDefWindowProcW(HWND__ * hwnd, unsigned int uMsg, unsigned __int64 wParam, __int64 lParam) Line 1076 C++
user32.dll!DefWindowProcW() Unknown
ExplorerFrame.dll!UIItemsView::WndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
dui70.dll!DirectUI::HWNDElement::StaticWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!CallWindowProcAorW() Unknown
user32.dll!CallWindowProcW() Unknown
duser.dll!ExtraInfoWndProc(struct HWND__ *,unsigned int,unsigned __int64,__int64) Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!CallWindowProcAorW() Unknown
user32.dll!CallWindowProcW() Unknown
comctl32.dll!CallOriginalWndProc() Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!UIItemsView::_UIItemsViewSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64) Unknown
ExplorerFrame.dll!UIItemsView::s_UIItemsViewSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64,unsigned __int64) Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!DefSubclassProc() Unknown
ExplorerFrame.dll!CToolTipManager::_PropertyToolTipSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64) Unknown
ExplorerFrame.dll!CToolTipManager::s_PropertyToolTipSubclassProc(struct HWND__ *,unsigned int,unsigned __int64,__int64,unsigned __int64,unsigned __int64) Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!DefSubclassProc() Unknown
comctl32.dll!CallNextSubclassProc() Unknown
comctl32.dll!MasterSubclassProc() Unknown
user32.dll!UserCallWinProcCheckWow() Unknown
user32.dll!DispatchMessageWorker() Unknown
ExplorerFrame.dll!CExplorerFrame::FrameMessagePump(void) Unknown
ExplorerFrame.dll!BrowserThreadProc(struct IETHREADPARAM *) Unknown
ExplorerFrame.dll!BrowserNewThreadProc(void *) Unknown
ExplorerFrame.dll!CExplorerTask::InternalResumeRT(void) Unknown
ExplorerFrame.dll!CRunnableTask::Run(void) Unknown
shell32.dll!CShellTask::TT_Run(bool *) Unknown
shell32.dll!CShellTaskThread::ThreadProc(void) Unknown
shell32.dll!CShellTaskThread::s_ThreadProc(void *) Unknown
shlwapi.dll!WrapperThreadProc(void *) Unknown
kernel32.dll!BaseThreadInitThunk() Unknown
ntdll.dll!RtlUserThreadStart() Unknown
当右键单击此文件夹视图中的一项(或多个选定项)(或树视图中的项)时,Shell 将为各种接口调用
并传递 PIDL所选项目。 当右键单击没有项目的文件夹视图时,它将为各种接口调用
IShellFolder::CreateViewObject,因为没有 PIDL 可供使用,因为它与显示的文件夹本身有关。 对于右键单击上下文菜单的
IContextMenu
以及其他接口,例如用于拖放以及复制/粘贴操作的
IDropTarget来说,情况也是如此。 要询问
IDropTarget
,Shell 文件夹必须公开
SFGAO_DROPTARGET“指定的项目是放置目标” 属性。 我在这里创建了一个Shell命名空间扩展示例https://github.com/smourier/ExplorerDataProvider/tree/main
基于微软官方的one,演示了(有限)IDropTarget
支持,足以用于“粘贴” “要启用的菜单项。