默认IShellView背景上下文菜单中的粘贴和粘贴快捷方式变灰

问题描述 投票:0回答:1

我有一个同时使用

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
快捷方式以停止变灰:

  1. 调整
    SFGAO_*
    标志。
  2. 禁用
    IContextMenuCB::Callback
    的调用。
  3. 禁用
    IShellFolderViewCB::MessageSFVCB
    的调用。
  4. 调整
    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

	
c++ windows com windows-shell shell-namespace-extension
1个回答
0
投票
五个基本组件之一

Windows Explorer File Basic Components 当右键单击此文件夹视图中的一项(或多个选定项)(或树视图中的项)时,Shell 将为各种接口调用

IShellFolder::GetUIObjectOf

并传递 PIDL所选项目。 当右键单击没有项目的文件夹视图时,它将为各种接口调用

IShellFolder::CreateViewObject

,因为没有 PIDL 可供使用,因为它与显示的文件夹本身有关。 对于右键单击上下文菜单的

IContextMenu

以及其他接口,例如用于拖放以及复制/粘贴操作的

IDropTarget
来说,情况也是如此。 要询问

IDropTarget

,Shell 文件夹必须公开

SFGAO_DROPTARGET
“指定的项目是放置目标” 属性。 我在这里创建了一个Shell命名空间扩展示例

https://github.com/smourier/ExplorerDataProvider/tree/main

基于微软官方的one,演示了(有限)IDropTarget支持,足以用于“粘贴” “要启用的菜单项。

PS:GetUIObjectOf 和 CreateViewObject 通常可以共享很多代码,只是以通用的方式处理 PIDL 的存在或不存在。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.