BOOL CRecBinViewer::ExecCommand (int iItem, LPCTSTR lpszCommand) { if (iItem >= static_cast<int>(m_List.size ())) return FALSE; BOOL bReturn = FALSE; LPITEMIDLIST pidl = NULL; LPCONTEXTMENU pCtxMenu = NULL; HRESULT hr = S_OK; pidl = m_List[iItem].m_PIDL; if (NULL != m_pFolder2) hr = m_pFolder2->GetUIObjectOf (m_hWnd, 1, (LPCITEMIDLIST *)&pidl, IID_IContextMenu, NULL, (LPVOID *)&pCtxMenu); else hr = m_pRecycleBin->GetUIObjectOf (m_hWnd, 1, (LPCITEMIDLIST *)&pidl, IID_IContextMenu, NULL, (LPVOID *)&pCtxMenu); if (SUCCEEDED (hr)) bReturn = ExecCommand (pCtxMenu, lpszCommand); pCtxMenu->Release(); return bReturn; }
UINT CShellContextMenu::ShowContextMenu(QWidget * pParentWidget, QPoint pt, QMenu* pMenu ) { HWND hWnd = pParentWidget->winId(); int iMenuType = 0; // to know which version of IContextMenu is supported LPCONTEXTMENU pContextMenu; // common pointer to IContextMenu and higher version interface if (!GetContextMenu ((void**) &pContextMenu, iMenuType)) return (0); // something went wrong if (!m_hMenu) { DestroyMenu( m_hMenu ); m_hMenu = CreatePopupMenu (); } int i; QList<QAction*> actionList = pMenu->actions(); for( i=0; i<actionList.count(); ++i ) { QString s = actionList.at(i)->text(); if (!s.isEmpty()) AppendMenuW( m_hMenu, MF_STRING, i+1, (LPCWSTR)s.utf16() ); } AppendMenuW( m_hMenu, MF_SEPARATOR, i+1, L"" ); // lets fill the our popupmenu pContextMenu->QueryContextMenu (m_hMenu, GetMenuItemCount (m_hMenu), MIN_ID, MAX_ID, CMF_NORMAL | CMF_EXPLORE); // subclass window to handle menurelated messages in CShellContextMenu WNDPROC OldWndProc; if (iMenuType > 1) // only subclass if its version 2 or 3 { OldWndProc = (WNDPROC) SetWindowLongPtr (hWnd, GWLP_WNDPROC, (LONG_PTR) HookWndProc); if (iMenuType == 2) g_IContext2 = (LPCONTEXTMENU2) pContextMenu; else // version 3 g_IContext3 = (LPCONTEXTMENU3) pContextMenu; } else OldWndProc = NULL; UINT idCommand = TrackPopupMenu (m_hMenu,TPM_RETURNCMD | TPM_LEFTALIGN, pt.x(), pt.y(), 0, pParentWidget->winId(), 0); if (OldWndProc) // unsubclass SetWindowLongPtr (hWnd, GWLP_WNDPROC, (LONG_PTR) OldWndProc); if (idCommand >= MIN_ID && idCommand <= MAX_ID) // see if returned idCommand belongs to shell menu entries { InvokeCommand (pContextMenu, idCommand - MIN_ID); // execute related command idCommand = 0; } pContextMenu->Release(); g_IContext2 = NULL; g_IContext3 = NULL; return (idCommand); }
// Shows standard Win95 Property Dlg for selected Item BOOL DirList_PropertyDlg(HWND hwnd, int iItem) { LV_ITEM lvi; LPLV_ITEMDATA lplvid; LPCONTEXTMENU lpcm; CMINVOKECOMMANDINFO cmi; BOOL bSuccess = TRUE; static const char* lpVerb = "properties"; if (iItem == -1) { if (ListView_GetSelectedCount(hwnd)) iItem = ListView_GetNextItem(hwnd, -1, LVNI_ALL | LVNI_SELECTED); else return FALSE; } lvi.mask = LVIF_PARAM; lvi.iItem = iItem; lvi.iSubItem = 0; if (!ListView_GetItem(hwnd, &lvi)) return FALSE; lplvid = (LPLV_ITEMDATA)lvi.lParam; if (NOERROR == lplvid->lpsf->GetUIObjectOf(GetParent(hwnd), // Owner 1, // Number of objects (LPCITEMIDLIST*)&lplvid->pidl, // pidl IID_IContextMenu, NULL, (void**)&lpcm)) { cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); cmi.fMask = 0; cmi.hwnd = GetParent(hwnd); cmi.lpVerb = lpVerb; cmi.lpParameters = NULL; cmi.lpDirectory = NULL; cmi.nShow = SW_SHOWNORMAL; cmi.dwHotKey = 0; cmi.hIcon = NULL; if (NOERROR != lpcm->InvokeCommand(&cmi)) bSuccess = FALSE; lpcm->Release(); } else bSuccess = FALSE; return bSuccess; }
UINT CShellContextMenu::ShowContextMenu(HWND hWnd, CPoint pt) { int iMenuType = 0; // to know which version of IContextMenu is supported LPCONTEXTMENU pContextMenu; // common pointer to IContextMenu and higher version interface if(!GetContextMenu((LPVOID*)&pContextMenu, iMenuType)) return 0; // something went wrong if(!m_Menu) { delete m_Menu; m_Menu = NULL; m_Menu = new CMenu; m_Menu->CreatePopupMenu(); } // lets fill the popupmenu pContextMenu->QueryContextMenu(m_Menu->m_hMenu, m_Menu->GetMenuItemCount(), ID_SHELLCONTEXTMENU_MIN, ID_SHELLCONTEXTMENU_MAX, CMF_NORMAL | CMF_EXPLORE); // subclass window to handle menurelated messages in CShellContextMenu WNDPROC OldWndProc; if(iMenuType > 1) // only subclass if its version 2 or 3 { OldWndProc = (WNDPROC) SetWindowLong(hWnd, GWL_WNDPROC, (DWORD) HookWndProc); if(iMenuType == 2) g_IContext2 = (LPCONTEXTMENU2) pContextMenu; else // version 3 g_IContext3 = (LPCONTEXTMENU3) pContextMenu; } else OldWndProc = NULL; UINT idCommand = m_Menu->TrackPopupMenu(TPM_RETURNCMD | TPM_LEFTALIGN, pt.x, pt.y, hWnd); if(OldWndProc) // unsubclass SetWindowLong(hWnd, GWL_WNDPROC, (DWORD) OldWndProc); if(idCommand >= ID_SHELLCONTEXTMENU_MIN && idCommand <= ID_SHELLCONTEXTMENU_MAX) { InvokeCommand(pContextMenu, idCommand - ID_SHELLCONTEXTMENU_MIN); idCommand = 0; } pContextMenu->Release(); g_IContext2 = NULL; g_IContext3 = NULL; return idCommand; }
UINT CShellContextMenu::ShowContextMenu(CWnd *pWnd, CPoint pt) { int iMenuType = 0; // to know which version of IContextMenu is supported LPCONTEXTMENU pContextMenu; // common pointer to IContextMenu and higher version interface if (!GetContextMenu ((void**) &pContextMenu, iMenuType)) return (0); // something went wrong if (m_Menu) { delete m_Menu; m_Menu = NULL; } m_Menu = new CMenu; m_Menu->CreatePopupMenu (); // lets fill the our popupmenu pContextMenu->QueryContextMenu (m_Menu->m_hMenu, m_Menu->GetMenuItemCount (), MIN_ID, MAX_ID, CMF_NORMAL | CMF_EXPLORE); // subclass window to handle menurelated messages in CShellContextMenu WNDPROC OldWndProc; if (iMenuType > 1) // only subclass if its version 2 or 3 { OldWndProc = (WNDPROC) SetWindowLong (pWnd->m_hWnd, GWL_WNDPROC, (DWORD) HookWndProc); if (iMenuType == 2) g_IContext2 = (LPCONTEXTMENU2) pContextMenu; else // version 3 g_IContext3 = (LPCONTEXTMENU3) pContextMenu; } else OldWndProc = NULL; UINT idCommand = m_Menu->TrackPopupMenu (TPM_RETURNCMD | TPM_LEFTALIGN, pt.x, pt.y, pWnd); if (OldWndProc) // unsubclass SetWindowLong (pWnd->m_hWnd, GWL_WNDPROC, (DWORD) OldWndProc); if (idCommand >= MIN_ID && idCommand <= MAX_ID) // see if returned idCommand belongs to shell menu entries { InvokeCommand (pContextMenu, idCommand - MIN_ID); // execute related command idCommand = 0; } pContextMenu->Release(); g_IContext2 = NULL; g_IContext3 = NULL; return (idCommand); }
// Shows standard Win95 Property Dlg for selected Drive BOOL DriveBox_PropertyDlg(HWND hwnd) { COMBOBOXEXITEM cbei; LPDC_ITEMDATA lpdcid; int iItem; LPCONTEXTMENU lpcm; CMINVOKECOMMANDINFO cmi; BOOL bSuccess = TRUE; static const char* lpVerb = "properties"; iItem = (int)SendMessage(hwnd, CB_GETCURSEL, 0, 0); if (iItem == CB_ERR) return FALSE; cbei.mask = CBEIF_LPARAM; cbei.iItem = iItem; SendMessage(hwnd, CBEM_GETITEM, 0, (LPARAM)&cbei); lpdcid = (LPDC_ITEMDATA)cbei.lParam; if (NOERROR == lpdcid->lpsf->GetUIObjectOf(GetParent(hwnd), // Owner 1, // Number of objects (LPCITEMIDLIST*)&lpdcid->pidl, // pidl IID_IContextMenu, NULL, (void**)&lpcm)) { cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); cmi.fMask = 0; cmi.hwnd = GetParent(hwnd); cmi.lpVerb = lpVerb; cmi.lpParameters = NULL; cmi.lpDirectory = NULL; cmi.nShow = SW_SHOWNORMAL; cmi.dwHotKey = 0; cmi.hIcon = NULL; if (NOERROR != lpcm->InvokeCommand(&cmi)) bSuccess = FALSE; lpcm->Release(); } else bSuccess = FALSE; return bSuccess; }
UINT CShellContextMenu::ShowContextMenu(CWnd *pWnd, POINT pt) { int iMenuType = 0; // to know which version of IContextMenu is supported LPCONTEXTMENU pContextMenu; // common pointer to IContextMenu and higher version interface if (!GetContextMenu ((void**) &pContextMenu, iMenuType)) return (0); // something went wrong if (!m_Menu) { delete m_Menu; m_Menu = NULL; m_Menu = new CMenu; m_Menu->CreatePopupMenu (); m_Menu->AppendMenu(MF_STRING, WM_MENU_FILE,_T("打开文件所在目录")); // lets fill the our popupmenu pContextMenu->QueryContextMenu(m_Menu->m_hMenu, m_Menu->GetMenuItemCount(), MIN_ID, MAX_ID, CMF_NORMAL | CMF_EXPLORE); } if (iMenuType > 1) // only subclass if its version 2 or 3 { if (iMenuType == 2) g_IContext2 = (LPCONTEXTMENU2) pContextMenu; else // version 3 g_IContext3 = (LPCONTEXTMENU3) pContextMenu; } UINT idCommand = m_Menu->TrackPopupMenu (TPM_RETURNCMD | TPM_LEFTALIGN, pt.x, pt.y, pWnd); if (idCommand >= MIN_ID && idCommand <= MAX_ID) // see if returned idCommand belongs to shell menu entries { InvokeCommand (pContextMenu, idCommand - MIN_ID); // execute related command idCommand = 0; } pContextMenu->Release(); g_IContext2 = NULL; g_IContext3 = NULL; return (idCommand); }
BOOL CRecBinViewer::ExecCommandOnSelection (LPCTSTR lpszCommand) { if (!m_pGridCtrl) return false; int nItems = m_List.size(); LPITEMIDLIST *pidlArray = (LPITEMIDLIST *) malloc ( (nItems) * sizeof (LPITEMIDLIST)); int selCount = 0; for (POSITION pos = m_pGridCtrl->m_SelectedCellMap.GetStartPosition(); pos != NULL; ) { DWORD key; CCellID cell; m_pGridCtrl->m_SelectedCellMap.GetNextAssoc(pos, key, (CCellID&)cell); if (cell.col == 0) { pidlArray[selCount] = m_List[cell.row -1].m_PIDL; selCount++; } } HRESULT hr = S_OK; LPCONTEXTMENU pCtxMenu = NULL; if (NULL != m_pFolder2) hr = m_pFolder2->GetUIObjectOf (m_hWnd, selCount, (LPCITEMIDLIST *)pidlArray, IID_IContextMenu, NULL, (LPVOID *)&pCtxMenu); else hr = m_pRecycleBin->GetUIObjectOf (m_hWnd, selCount, (LPCITEMIDLIST *)pidlArray, IID_IContextMenu, NULL, (LPVOID *)&pCtxMenu); BOOL bReturn = FALSE; if (SUCCEEDED (hr)) bReturn = ExecCommand (pCtxMenu, lpszCommand); pCtxMenu->Release(); free (pidlArray); return bReturn; }
/**************************************************************************** * * FUNCTION: DoTheMenuThing(HWND hwnd, * LPSHELLFOLDER lpsfParent, * LPITEMIDLIST lpi, * LPPOINT lppt) * * PURPOSE: Displays a popup context menu, given a parent shell folder, * relative item id and screen location. * * PARAMETERS: * hwnd - Parent window handle * lpsfParent - Pointer to parent shell folder. * lpi - Pointer to item id that is relative to lpsfParent * lppt - Screen location of where to popup the menu. * * RETURN VALUE: * Returns TRUE on success, FALSE on failure * ****************************************************************************/ BOOL CShellPidl::DoTheMenuThing(HWND hwnd, LPSHELLFOLDER lpsfParent, LPITEMIDLIST lpi, LPPOINT lppt) { LPCONTEXTMENU lpcm; HRESULT hr; char szTemp[64]; CMINVOKECOMMANDINFO cmi; DWORD dwAttribs=0; int idCmd; HMENU hMenu; BOOL bSuccess=TRUE; hr=lpsfParent->GetUIObjectOf(hwnd, 1, //Number of objects to get attributes of (const struct _ITEMIDLIST **)&lpi, IID_IContextMenu, 0, (LPVOID *)&lpcm); if (SUCCEEDED(hr)) { hMenu = CreatePopupMenu(); if (hMenu) { hr=lpcm->QueryContextMenu(hMenu, 0, 1, 0x7fff, CMF_EXPLORE); if (SUCCEEDED(hr)) { idCmd=TrackPopupMenu(hMenu, TPM_LEFTALIGN | TPM_RETURNCMD | TPM_RIGHTBUTTON, lppt->x, lppt->y, 0, hwnd, NULL); if (idCmd) { cmi.cbSize = sizeof(CMINVOKECOMMANDINFO); cmi.fMask = 0; cmi.hwnd = hwnd; cmi.lpVerb = MAKEINTRESOURCE(idCmd-1); cmi.lpParameters = NULL; cmi.lpDirectory = NULL; cmi.nShow = SW_SHOWNORMAL; cmi.dwHotKey = 0; cmi.hIcon = NULL; hr=lpcm->InvokeCommand(&cmi); if (!SUCCEEDED(hr)) { wsprintf(szTemp, "InvokeCommand failed. hr=%lx", hr); AfxMessageBox(szTemp); } } } else bSuccess = FALSE; DestroyMenu(hMenu); } else bSuccess = FALSE; lpcm->Release(); } else { wsprintf(szTemp, "GetUIObjectOf failed! hr=%lx", hr); AfxMessageBox(szTemp ); bSuccess = FALSE; } return bSuccess; }
LRESULT CSEShellView::OnNotify( LPNMHDR pNmhdr ) { TRACE_FUNCTION(); if( pNmhdr ) { if( pNmhdr->code == NM_DBLCLK ) { int iIndex = ListView_GetNextItem( m_hWnd, -1, LVNI_FOCUSED ); if (iIndex == -1) { return S_OK; } LV_ITEM item = {0}; item.iItem = iIndex; item.iSubItem = 0; item.mask = LVIF_PARAM; ListView_GetItem( m_hWnd, &item ); if ( item.lParam ) { LPITEMIDLIST pItem = m_pidlManager.Copy( ITEMLISTPTR(item.lParam) ); if( m_pidlManager.GetItemType( pItem ) == CPidlManager::FOLDER ) { LOG(_T("%s 打开文件夹 %s"), __TFUNCTION__, m_pidlManager.GetItemName( pItem ) ); //打开文件夹 m_pShellBrowser->BrowseObject( pItem , SBSP_DEFBROWSER | SBSP_RELATIVE ); } else { TCHAR szPath[MAX_PATH] = {0}; DWORD dwLen = MAX_PATH; LPITEMIDLIST pFullItem = m_pidlManager.Concatenate(m_pFolder->GetRootPath(), pItem ); m_pidlManager.GetFullName( pFullItem, szPath, &dwLen ); m_pidlManager.ReplaceRoot( szPath ); m_pidlManager.Delete( pFullItem ); //打开文件 LONG ret = (LONG)(LONG_PTR)ShellExecute(NULL, _T("open"), szPath, NULL, NULL, SW_SHOWNORMAL); if ( ret > 32 ) { return TRUE; } switch ( ret ) { case ERROR_BAD_FORMAT: { ::MessageBox( NULL, _T("文件已损坏"), _T("提示"), MB_OK ); } break; case SE_ERR_ASSOCINCOMPLETE: case SE_ERR_NOASSOC: { TCHAR szRunParam[MAX_PATH<<1] = {0}; _sntprintf( szRunParam, MAX_PATH<<1, _T("shell32.dll,OpenAs_RunDLL \"%s\""), szPath ); ShellExecute(NULL, NULL, _T("rundll32.exe "), szRunParam, NULL, SW_SHOW); } break; default: { } } } m_pidlManager.Delete( pItem ); pItem = NULL; } } else if( pNmhdr->code == NM_RCLICK ) { LPITEMIDLIST* ppIdl = NULL; int nSelCount = ListView_GetSelectedCount(m_hWnd); if ( nSelCount > 0 ) { ppIdl = (LPITEMIDLIST*)_Module.m_Allocator.Alloc( sizeof(LPITEMIDLIST)*nSelCount ); int iIndex = ListView_GetNextItem( m_hWnd, -1, LVIS_SELECTED ); LV_ITEM item = {0}; item.iSubItem = 0; item.mask = LVIF_PARAM; int _i = 0; while( iIndex >= 0 && _i < nSelCount ) { item.iItem = iIndex; ListView_GetItem( m_hWnd, &item ); ppIdl[_i] = m_pidlManager.Copy( ITEMLISTPTR(item.lParam) ); ++_i; iIndex = ListView_GetNextItem( m_hWnd, -1, LVIS_SELECTED ); } } LPCONTEXTMENU pMenu = NULL; HRESULT hr = E_FAIL; hr = m_pFolder->GetUIObjectOf( m_hWnd, nSelCount, \ (LPCITEMIDLIST*)ppIdl, IID_IContextMenu, NULL, (void**)&pMenu ); if ( FAILED(hr) || !pMenu) { LOG(_T("IID_IContextMenu Failed")); if ( nSelCount > 0 ) { for ( int _i = 0; _i < nSelCount; ++_i ) { m_pidlManager.Delete( ppIdl[_i] ); } _Module.m_Allocator.Free( ppIdl ); } return S_OK; } HMENU hMenu = ::CreatePopupMenu(); if ( !hMenu ) { if ( nSelCount > 0 ) { for ( int _i = 0; _i < nSelCount; ++_i ) { m_pidlManager.Delete( ppIdl[_i] ); } _Module.m_Allocator.Free( ppIdl ); } return S_OK; } hr = pMenu->QueryContextMenu( hMenu, 0, 10, 32767, CMF_NORMAL | CMF_EXPLORE ); if ( FAILED(hr) ) { if ( nSelCount > 0 ) { for ( int _i = 0; _i < nSelCount; ++_i ) { m_pidlManager.Delete( ppIdl[_i] ); } _Module.m_Allocator.Free( ppIdl ); } DestroyMenu( hMenu ); return hr; } POINT point = {0}; GetCursorPos( &point ); UINT command = (UINT)TrackPopupMenu ( hMenu, TPM_RETURNCMD | TPM_LEFTALIGN, point.x, point.y, 0, m_hWnd, NULL ); CMINVOKECOMMANDINFO cmi = {0}; cmi.cbSize = sizeof (CMINVOKECOMMANDINFO); cmi.lpVerb = (LPSTR) MAKEINTRESOURCE (command-10); cmi.nShow = SW_SHOWNORMAL; pMenu->InvokeCommand( &cmi ); pMenu->Release(); if ( nSelCount > 0 ) { for ( int _i = 0; _i < nSelCount; ++_i ) { m_pidlManager.Delete( ppIdl[_i] ); } _Module.m_Allocator.Free( ppIdl ); } DestroyMenu( hMenu ); } } TRACE_RETURN S_OK; }
BOOL COXShellNamespaceNavigator::InvokeCommand(const LPSHELLFOLDER lpParentFolder, const LPITEMIDLIST lpRelativeIDL, UINT nCmdID, DWORD dwFlags) const { // If any command from popup menu was selected then it should be // applied to corresponding shell object. // So we have to fill CMINVOKECOMMANDINFO structure CMINVOKECOMMANDINFO cmici={ sizeof(CMINVOKECOMMANDINFO) }; cmici.fMask=0; cmici.hwnd=m_pOwnerWnd!=NULL ? m_pOwnerWnd->GetSafeHwnd() : NULL; cmici.lpVerb=LPCSTR((UINT_PTR)nCmdID-1); cmici.lpParameters=NULL; cmici.lpDirectory=NULL; cmici.nShow=SW_SHOWNORMAL; cmici.dwHotKey=0; cmici.hIcon=NULL; // We can request IContextMenu interface using // IShellFolder::GetUIObjectOf method. // /* HRESULT GetUIObjectOf( HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl, REFIID riid, UINT *prgfInOut, LPVOID *ppvOut ); Retrieves an OLE interface that can be used to carry out actions on the specified file objects or folders. Returns NOERROR if successful, E_NOINTERFACE if the interface is not supported, or an OLE-defined error value otherwise. hwndOwner - Handle to the owner window that the client should specify if it displays a dialog box or message box. cidl - Number of file objects or subfolders specified in the apidl parameter. apidl - Address of an array of pointers to ITEMIDLIST structures, each of which uniquely identifies a file object or subfolder relative to the parent folder. Each item identifier list must contain exactly one SHITEMID structure followed by a terminating zero. riid - Identifier of the COM interface object to return. This can be any valid interface identifier that can be created for an item. The most common identifiers used by the shell are listed in the comments at the end of this reference. prgfInOut - Reserved. ppvOut - Address that receives the interface pointer. If an error occurs, a NULL pointer is returned in this address. If cidl is greater than one, the GetUIObjectOf implementation should only succeed if it can create one object for all items specified in apidl. If the implementation cannot create one object for all items, this method should fail. The following are the most common interface identifiers the shell uses when requesting an interface from this method. The list also indicates if cidl can be greater than one for the requested interface. Interface Identifier Allowed cidl Value IContextMenu The cidl parameter can be greater than or equal to one. IContextMenu2 The cidl parameter can be greater than or equal to one. IDataObject The cidl parameter can be greater than or equal to one. IDropTarget The cidl parameter can only be one. IExtractIcon The cidl parameter can only be one. IQueryInfo The cidl parameter can only be one. */ LPCONTEXTMENU lpcm; HRESULT hResult=lpParentFolder-> GetUIObjectOf(m_pOwnerWnd!=NULL ? m_pOwnerWnd->GetSafeHwnd() : NULL, 1, (const struct _ITEMIDLIST**)&(lpRelativeIDL), IID_IContextMenu, 0, (LPVOID*)&lpcm); if(FAILED(hResult)) return FALSE; // In order to apply specified command we use // IContextMenu::InvokeCommand() method. /* HRESULT InvokeCommand( LPCMINVOKECOMMANDINFO lpici ); Carries out the command associated with a context menu item. Returns NOERROR if successful, or an OLE-defined error code otherwise. lpici - Address of a CMINVOKECOMMANDINFO structure containing information about the command. typedef struct _CMInvokeCommandInfo{ DWORD cbSize; DWORD fMask; HWND hwnd; LPCSTR lpVerb; LPCSTR lpParameters; LPCSTR lpDirectory; int nShow; DWORD dwHotKey; HANDLE hIcon; } CMINVOKECOMMANDINFO, *LPCMINVOKECOMMANDINFO; Contains information about a context menu command. cbSize - Contains the size of this structure, in bytes. fMask - Zero, or one or more of the following flags: CMIC_MASK_HOTKEY - The dwHotKey member is valid. CMIC_MASK_ICON - The hIcon member is valid. CMIC_MASK_FLAG_NO_UI- The system is prevented from displaying user interface elements (for example, error messages) while carrying out a command. hwnd - Handle of the window that is the owner of the context menu. An extension can also use this handle as the owner of any message boxes or dialog boxes it displays. lpVerb - A 32-bit value that contains zero in the high-order word and a menu-identifier offset of the command to carry out in the low-order word. The shell specifies this value (using the MAKEINTRESOURCE macro) when the user chooses a menu command. If the high-order word is not zero, this member is the address of a null-terminated string specifying the language-independent name of the command to carry out. This member is typically a string when a command is being activated by an application. The system provides predefined constant values for the following command strings. Value String CMDSTR_NEWFOLDER "NewFolder" CMDSTR_VIEWDETAILS "ViewDetails" CMDSTR_VIEWLIST "ViewList" lpParameters - Optional parameters. This member is always NULL for menu items inserted by a shell extension. lpDirectory - Optional working directory name. This member is always NULL for menu items inserted by a shell extension. nShow - Set of SW_ values to pass to the ShowWindow function if the command displays a window or starts an application. dwHotKey - Optional hot key to assign to any application activated by the command. If the fMask parameter does not specify CMIC_MASK_HOTKEY, this member is ignored. hIcon - Icon to use for any application activated by the command. If the fMask member does not specify CMIC_MASK_ICON, this member is ignored. The shell calls this method when the user chooses a command that the handler added to a context menu. This method may also be called by an application without any corresponding user action. */ HMENU hMenu=::CreatePopupMenu(); if(hMenu==NULL) { TRACE(_T("COXShellNamespaceNavigator::GetObjectContextMenu: CreatePopupMenu() failed\n")); return NULL; } hResult=lpcm->QueryContextMenu(hMenu,0,1,0x7fff,dwFlags); if(FAILED(hResult)) { TRACE(_T("COXShellNamespaceNavigator::GetObjectContextMenu: QueryContextMenu() failed\n")); ::DestroyMenu(hMenu); return NULL; } hResult=lpcm->InvokeCommand(&cmici); ::DestroyMenu(hMenu); lpcm->Release(); if(FAILED(hResult)) { TRACE(_T("COXShellNamespaceNavigator::InvokeCommand: InvokeCommand() failed\n")); return FALSE; } return TRUE; }
HMENU COXShellNamespaceNavigator:: GetObjectContextMenu(const LPSHELLFOLDER lpParentFolder, const LPITEMIDLIST lpRelativeIDL, DWORD dwFlags) const { // We can request IContextMenu interface using // IShellFolder::GetUIObjectOf method. // /* HRESULT GetUIObjectOf( HWND hwndOwner, UINT cidl, LPCITEMIDLIST *apidl, REFIID riid, UINT *prgfInOut, LPVOID *ppvOut ); Retrieves an OLE interface that can be used to carry out actions on the specified file objects or folders. Returns NOERROR if successful, E_NOINTERFACE if the interface is not supported, or an OLE-defined error value otherwise. hwndOwner - Handle to the owner window that the client should specify if it displays a dialog box or message box. cidl - Number of file objects or subfolders specified in the apidl parameter. apidl - Address of an array of pointers to ITEMIDLIST structures, each of which uniquely identifies a file object or subfolder relative to the parent folder. Each item identifier list must contain exactly one SHITEMID structure followed by a terminating zero. riid - Identifier of the COM interface object to return. This can be any valid interface identifier that can be created for an item. The most common identifiers used by the shell are listed in the comments at the end of this reference. prgfInOut - Reserved. ppvOut - Address that receives the interface pointer. If an error occurs, a NULL pointer is returned in this address. If cidl is greater than one, the GetUIObjectOf implementation should only succeed if it can create one object for all items specified in apidl. If the implementation cannot create one object for all items, this method should fail. The following are the most common interface identifiers the shell uses when requesting an interface from this method. The list also indicates if cidl can be greater than one for the requested interface. Interface Identifier Allowed cidl Value IContextMenu The cidl parameter can be greater than or equal to one. IContextMenu2 The cidl parameter can be greater than or equal to one. IDataObject The cidl parameter can be greater than or equal to one. IDropTarget The cidl parameter can only be one. IExtractIcon The cidl parameter can only be one. IQueryInfo The cidl parameter can only be one. */ LPCONTEXTMENU lpcm; HRESULT hResult=lpParentFolder-> GetUIObjectOf(m_pOwnerWnd!=NULL ? m_pOwnerWnd->GetSafeHwnd() : NULL, 1, (const struct _ITEMIDLIST**)&(lpRelativeIDL),IID_IContextMenu,0, (LPVOID*)&lpcm); if(FAILED(hResult)) return NULL; // Use IContextMenu::QueryContextMenu method to get handle to popup menu. // /* HRESULT QueryContextMenu( HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags ); Adds menu items to the specified menu. The menu items should be inserted in the menu at the position specified by indexMenu, and their menu item identifiers must be between the idCmdFirst and idCmdLast parameter values. Returns an HRESULT structure in which, if the method is successful, the code member contains the menu identifier of the last menu item added plus one. hmenu - Handle to the menu. The handler should specify this handle when adding menu items. indexMenu - Zero-based position at which to insert the first menu item. idCmdFirst - Minimum value that the handler can specify for a menu item identifier. idCmdLast - Maximum value that the handler can specify for a menu item identifier. uFlags - Optional flags specifying how the context menu can be changed. Can be any combination of the following values: CMF_CANRENAME - This flag is set if the calling application supports renaming of items. A context menu extension or drag-and-drop handler should ignore this flag. A namespace extension should add a rename item to the menu if applicable. CMF_DEFAULTONLY - This flag is set when the user is activating the default action, typically by double-clicking. This flag provides a hint for the context menu extension to add nothing if it does not modify the default item in the menu. A context menu extension or drag-and-drop handler should not add any menu items if this value is specified. A namespace extension should add only the default item (if any). CMF_EXPLORE - This flag is set when Windows Explorer's tree window is present. Context menu handlers should ignore this value. CMF_INCLUDESTATIC - This flag is set when a static menu is being constructed. Only the browser should use this flag. All other context menu extensions should ignore this flag. CMF_NODEFAULT - This flag is set if no item in the menu should be the default item. A context menu extension or drag-and-drop handler should ignore this flag. A namespace extension should not set any of the menu items to the default. CMF_NORMAL - Indicates normal operation. A context menu extension, namespace extension, or drag-and-drop handler can add all menu items. CMF_NOVERBS - This flag is set for items displayed in the "Send To:" menu. Context menu handlers should ignore this value. CMF_VERBSONLY - This flag is set if the context menu is for a shortcut object. Context menu handlers should ignore this value. The remaining bits of the low-order word are reserved by the system. The high-order word may be used for context-specific communications. The CMF_RESERVED value can be used to mask out the low-order word. The actual identifier of each menu item should be idCmdFirst plus a menu identifier offset in the range zero through (idCmdLast ... idCmdFirst). */ // // Create popup menu and populate it using above described method HMENU hMenu=::CreatePopupMenu(); if(hMenu==NULL) { TRACE(_T("COXShellNamespaceNavigator::GetObjectContextMenu: CreatePopupMenu() failed\n")); return NULL; } hResult=lpcm->QueryContextMenu(hMenu,0,1,0x7fff,dwFlags); if(FAILED(hResult)) { TRACE(_T("COXShellNamespaceNavigator::GetObjectContextMenu: QueryContextMenu() failed\n")); return NULL; } lpcm->Release(); return hMenu; }