我有一个命名空间扩展,它提供了一个服务器中的文件/文件夹的虚拟视图。
在IContextMenu::QueryContextMenu()我已经添加了一些自定义菜单项。
我还在IShellFolder::GetAttributesOf()设置了几个SGAOF标志,以获得上下文菜单中的重命名,删除和属性。
有什么办法可以让我的名字空间扩展项目的上下文菜单中的“ 发送到 ”选项? 一旦启用这些命令,我该如何处理这些命令? 请指教。
添加新function时是否必须更改COM接口的UID?
当用户没有足够的权限时,隐藏com-server OLE错误消息
在Win 10中卸载DLL时debugging崩溃,但不是Win 7
沉迷于win32api + COM和SO的答案
在* nix系统上是否有与COM等价的function? 如果不是,那么nix的可重用性是什么?
这是Denis Anisimovbuild议的那个代码
const CLSID SendToCLSID = { 0x7BA4C740,0x9E81,0x11CF,{ 0x99,0xD3,0x00,0xAA,0x4A,0xE8,0x37 } }; HRESULT CMyNSEContextMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder,IDataObject *pDataObj,HKEY hkeyProgID ) { OutputDebugString(L"CMyNSEContextMenu::Initializen"); //Other initialization code ... ... if (_pdtobj) { _pdtobj->Release(); _pdtobj = NULL; } _mpidlFolder = pidlFolder; _pdtobj = pDataObj; if (pDataObj) { _pdtobj->AddRef(); CoCreateInstance(SendToCLSID,NULL,CLSCTX_INPROC_SERVER,IID_IContextMenu,(LPVOID*)&_pSendToMenu); } return S_OK; } HRESULT CMyNSEContextMenu::QueryContextMenu(HMENU hmenu,UINT indexMenu,UINT idCmdFirst,UINT idCmdLast,UINT uFlags ) { OutputDebugString(L"CMyNSEContextMenu::QueryContextMenun"); UNREFERENCED_ParaMETER(indexMenu); UNREFERENCED_ParaMETER(idCmdFirst); //Get File Name IShellItemArray *psia=NULL; HRESULT hr; USHORT items = 0; //Adding other menu items AddMenuItem(hmenu,indexMenu++,idCmdFirst + MENUVERB_XXX,IDS_COMMAND_XXX,IDB_XXX); items++; IShellExtinit *pShellExtinitSendTo = NULL; _pSendToMenu->QueryInterface(IID_IShellExtinit,(LPVOID*)&pShellExtinitSendTo); pShellExtinitSendTo->Initialize(NULL,_pdtobj,0); // your IDataObject with CFSTR_SHELLIDLIST format) hr = _pSendToMenu->QueryContextMenu(hmenu,indexMenu,idCmdFirst,idCmdLast,uFlags); if (SUCCEEDED(hr)) { items += HRESULT_CODE(hr); } return MAKE_HRESULT(SEVERITY_SUCCESS,(USHORT)(items)); } HRESULT CMyNSEContextMenu::HandleMenuMsg( UINT uMsg,WParaM wParam,LParaM lParam ) { IContextMenu2 *pSendToMenu = NULL; _pSendToMenu->QueryInterface(IID_IContextMenu2,(LPVOID*)&pSendToMenu); return pSendToMenu->HandleMenuMsg(uMsg,wParam,lParam); } HRESULT CMyNSEContextMenu::HandleMenuMsg2( UINT uMsg,LParaM lParam,LRESULT *plResult ) { IContextMenu3 *pSendToMenu = NULL; _pSendToMenu->QueryInterface(IID_IContextMenu3,(LPVOID*)&pSendToMenu); return pSendToMenu->HandleMenuMsg2(uMsg,lParam,plResult); } HRESULT CMyNSEContextMenu::GetCommandString(UINT_PTR idCmd,UINT uType,UINT * pRes,LPSTR pszName,UINT cchMax ) { OutputDebugString(L"CMyNSEContextMenu::GetCommandStringn"); return _pSendToMenu->GetCommandString(idCmd,uType,pRes,pszName,cchMax); }
默认的上下文菜单是作为GetUIObjectOf的一部分创build的。 MyNSEContextMenu类的实例是通过Classfactory。
HRESULT CMyNSEShellFolder::GetUIObjectOf(HWND hwnd,UINT cidl,PCUITEMID_CHILD_ARRAY apidl,REFIID riid,UINT * /* prgfInOut */,void **ppv) { OutputDebugString(L"CMyNSEShellFolder::GetUIObjectOfn"); *ppv = NULL; HRESULT hr = E_NOINTERFACE; if (riid == IID_IContextMenu) { // The default context menu will call back for IQueryAssociations to determine the // file associations with which to populate the menu. DEFCONTEXTMENU const dcm = { hwnd,m_pidl,static_cast<IShellFolder2 *>(this),cidl,apidl,NULL }; hr = SHCreateDefaultContextMenu(&dcm,riid,ppv); } //Others .... .... else if (riid == IID_IQueryAssociations) { else { ASSOCIATIONELEMENT const rgAssocItem[] = { { ASSOcclASS_PROGID_STR,L"MyNSE_Type"},}; hr = AssocCreateForClasses(rgAssocItem,ARRAYSIZE(rgAssocItem),ppv); } } ... ... return hr; } //Called from the class factory HRESULT CMyNSEContextMenu_CreateInstance(REFIID riid,void **ppv) { *ppv = NULL; CMyNSEContextMenu* pContextMenu = new (std::nothrow) CMyNSEContextMenu(); HRESULT hr = pContextMenu ? S_OK : E_OUTOFMEMORY; if (SUCCEEDED(hr)) { hr = pContextMenu->QueryInterface(riid,ppv); pContextMenu->Release(); } return hr; }
相关registry如下
HKEY_LOCAL_MACHINE,L"Software\Classes\CLSID\%s",szContextMenuClassID,(LPBYTE)g_szExtTitle,REG_SZ,HKEY_LOCAL_MACHINE,L"Software\Classes\CLSID\%s\InprocServer32",(LPBYTE)L"%s",L"ThreadingModel",(LPBYTE)L"Apartment",L"Software\Classes\CLSID\%s\ProgID",szFolderViewImplClassID,(LPBYTE)L"MyNSE_Type",// For performance,only context menu verbs that register this are considered when the user double-clicks. HKEY_CLASSES_ROOT,L"CLSID\%s\ShellEx\MayChangeDefaultMenu",(LPBYTE)L"",// register the context menu handler under the MyNSE_Type type. HKEY_CLASSES_ROOT,L"MyNSE_Type\shellex\ContextMenuHandlers\%s",(LPBYTE)szContextMenuClassID,
什么是使用win32inet.WinHttpGetProxyForUrl正确的方法
如何访问UPnP设备的服务?
这个问题的根本原因是什么“R6016 – 线程数据空间不足”
如何为第三方定义的COM接口注册代理/存根?
SendTo只是实现IContextMenu(2,3)的简单外壳扩展。 在Windows 7中,扩展的CLSID是{7BA4C740-9E81-11CF-99D3-00AA004AE837}(别忘了在你想支持的其他Windows版本中检查正确的CLSID)。 所以只需要使用这样的东西:
function TMenuWithSentTo.QueryContextMenu(Menu: HMENU; indexMenu,uFlags: UINT): HResult; const SendToCLSID: TGUID = '{7BA4C740-9E81-11CF-99D3-00AA004AE837}'; var ShellExtinit: IShellExtinit; begin Result := 0; // Add you menu items here CoCreateInstance(SendToCLSID,nil,IContextMenu,FSendToMenu); FSendToMenu.QueryInterface(IShellExtinit,ShellExtinit); ShellExtinit.Initialize(nil,FDataObject,0); // your IDataObject with CFSTR_SHELLIDLIST format Result := Result + FSendToMenu.QueryContextMenu(Menu,uFlags); // Add you menu items here end; function TMenuWithSentTo.InvokeCommand(var lpici: TCMInvokeCommandInfo): HResult; begin if IsMyCommand(lpici) then begin // Process your command here Result := S_OK; end else Result := FSendToMenu.InvokeCommand(lpici); end; function TMenuWithSentTo.GetCommandString(idCmd: UINT_PTR; uFlags: UINT; pwReserved: PUINT; pszName: LPSTR; cchMax: UINT): HResult; begin if IsMyCommandID(idCmd) then begin // Process your command here Result := S_OK; end else FSendToMenu.GetCommandString(idCmd); end; function TMenuWithSentTo.HandleMenuMsg(uMsg: UINT; WParam: WParaM; LParam: LParaM): HResult; var SendToMenu2: IContextMenu2; begin if IsMyMessage(uMsg,WParam,LParam) then begin // Process your command here Result := S_OK; end else begin FSendToMenu.QueryInterface(IContextMenu2,SendToMenu2); Result := SendToMenu2.HandleMenuMsg(uMsg,LParam); end; end; function TMenuWithSentTo.HandleMenuMsg2(uMsg: UINT; wParam: WParaM; lParam: LParaM; var lpResult: LRESULT): HResult; var SendToMenu3: IContextMenu3; begin if IsMyMessage(uMsg,LParam) then begin // Process your command here Result := S_OK; end else begin FSendToMenu.QueryInterface(IContextMenu3,SendToMenu3); Result := SendToMenu3.HandleMenuMsg(uMsg,LParam); end; end;
但是你应该准备好SendTo的一些命令会被隐藏起来,有些命令不能正常工作,因为有些命令会请求真实的文件,但是你只有虚拟的。
正常发送到菜单:
发送到NSE的菜单:
简单的方法是将一个快捷方式添加到SendTo文件夹。 要发现这一点,只需将%APPDATA%MicrosoftwindowsSendTo粘贴到资源管理器窗口即可。
这只适用于如果你有一个命令行程序,文件名作为参数。 如果这不是您所需要的,请编辑您的问题,并详细说明如何访问您的扩展代码。 另外,如果这是C#请标记它。
SendTo的注册表项可以在HKEY_CLASSES_ROOT AllFilesystemObjects shellex ContextMenuHandlers找到。 至少从Vista到Windows 8的价值是{7BA4C740-9E81-11CF-99D3-00AA004AE837}。 你可以写这个键的外壳扩展。 我过去做过这个,但是没有任何可以帮助的源代码。 文档在这里: http : //msdn.microsoft.com/en-us/library/windows/desktop/cc144067%28v=vs.85%29.aspx 。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。