📄 shellcontextmenu.cpp
字号:
if (SUCCEEDED(hr) && dwEffect)
{
hr = pDT->Drop(pDO, MK_LBUTTON, pt, &dwEffect);
}
else
{
hr = pDT->DragLeave();
}
pDT->Release();
}
pidlDrop.m_pidl = NULL;
}
}
else
{
DWORD dwItemData=0;
CMenu *pMenu=NULL;
STL_FOR_ITERATOR(vecODMenu,m_OwnerDrawMenus)
{
pMenu = STL_GET_CURRENT(m_OwnerDrawMenus);
if (pMenu && pMenu->GetMenuItemCount() > 0)
{
// switch to original item data
if ((UINT)iCmd >= pMenu->GetMenuItemID(0) && (UINT)iCmd <= pMenu->GetMenuItemID(pMenu->GetMenuItemCount()-1))
{
dwItemData = g_CoolMenuManager.SwitchContextItemData(pMenu,iCmd,0,FALSE);
break;
}
}
}
CWaitCursor w;
// Shell command
CMINVOKECOMMANDINFO cmi;
cmi.cbSize = sizeof(cmi);
cmi.fMask = 0;
cmi.hwnd = m_hWnd;
cmi.lpVerb = T2CA(MAKEINTRESOURCE(iCmd - IDM_SHELLCTXFIRST));
cmi.lpParameters = NULL;
cmi.lpDirectory = NULL;
cmi.nShow = SW_SHOWNORMAL;
cmi.dwHotKey = 0;
cmi.hIcon = NULL;
m_lpcm->InvokeCommand(&cmi);
// switch back to our item data
if (dwItemData)
{
g_CoolMenuManager.SwitchContextItemData(pMenu,iCmd,dwItemData,FALSE);
}
}
}
// retrieves the shell context menu for a file
void CShellContextMenu::SetMenu(CMenu *pMenu)
{
if (m_sAbsPath.IsEmpty())
return;
ASSERT(m_psfParent);
HRESULT hr = m_psfParent->GetUIObjectOf(m_hWnd, m_cidl, (LPCITEMIDLIST*)m_ppidl, IID_IContextMenu, NULL, (LPVOID *)&m_lpcm);
// NOTE: Slight change to return here but change it back if you want: PO
if (FAILED(hr))
return;
g_CoolMenuManager.UnconvertMenu(pMenu);
g_CoolMenuManager.SetShellContextMenu(m_lpcm,IDM_SHELLCTXFIRST,IDM_SHELLCTXLAST);
pMenu->DeleteMenu(0, MF_BYPOSITION);
hr = m_lpcm->QueryContextMenu(*pMenu, 0, IDM_SHELLCTXFIRST,
IDM_SHELLCTXLAST, CMF_EXPLORE);
/////////////////////////////
// Additions Philip Oldaker
// Check for IContextMenu2 used by owner draw menus
CMenu *pSubMenu;
int count = pMenu->GetMenuItemCount();
for (int i = 0; i < count; i++)
{
CMenuItemInfo mii;
mii.fMask = MIIM_TYPE | MIIM_ID;
pMenu->GetMenuItemInfo(i,&mii,TRUE);
if (mii.fType & MFT_OWNERDRAW)
{
TRACE(_T("OwnerDraw menu item found in CShellContextMenu\n"));
g_CoolMenuManager.AddShellContextMenu(pMenu,m_lpcm,i);
STL_ADD_ITEM(m_OwnerDrawMenus,pMenu);
}
pSubMenu = pMenu->GetSubMenu(i);
/////////////////////////////
// Additions Philip Oldaker
// Search for owner draw menus and add the ICM2 pointer
if (pSubMenu)
{
// NOTE: Remove the TRACE statements if not needed
UINT nSubCount = pSubMenu->GetMenuItemCount();
TRACE(_T("Count=%u\n"),nSubCount);
for(UINT m=0;m < nSubCount;m++)
{
CMenuItemInfo mii;
mii.fMask = MIIM_TYPE;
pSubMenu->GetMenuItemInfo(m,&mii,TRUE);
if (mii.fType & MFT_OWNERDRAW)
{
TRACE(_T("OwnerDraw submenu found in CShellContextMenu\n"));
g_CoolMenuManager.AddShellContextMenu(pSubMenu,m_lpcm,m);
STL_ADD_ITEM(m_OwnerDrawMenus,pSubMenu);
}
}
}
/////////////////////////////
// find the "Send To" and the new "Open With" submenu: look for a defined menu item id
if (pSubMenu && pSubMenu->GetMenuItemCount() == 1)
{
CString str;
pSubMenu->GetMenuString(0,str,MF_BYPOSITION);
UINT idmFirst = pSubMenu->GetMenuItemID(0);
TRACE(_T("Menu Item %s=%d\n"),str,idmFirst);
/////////////////////////////
// Additions Philip Oldaker
// Populate the OpenWith menu
if (idmFirst == IDM_OPENWITHID1 || idmFirst == IDM_OPENWITHID2)
{
// ok - found it. now populate it
IContextMenu2 *lpcm2=NULL;
HRESULT hr = m_lpcm->QueryInterface(IID_IContextMenu2,(LPVOID*)&lpcm2);
if (SUCCEEDED(hr))
{
hr = lpcm2->HandleMenuMsg(WM_INITMENUPOPUP,(WPARAM)pSubMenu->GetSafeHmenu(),0);
lpcm2->Release();
// We need the extension to search the registry for valid applications
CString sExt(GetExt(m_sAbsPath));
// No extension then there's nothing to do
if (sExt.IsEmpty())
continue;
FillOpenWithMenu(pSubMenu,sExt);
STL_ADD_ITEM(m_OwnerDrawMenus,pSubMenu);
}
}
else if (idmFirst == IDM_SENDTOID)
{
UINT idm = IDM_SENDTOFIRST;
// ok - found it. now populate it
m_pSendToMenu = CMenu::FromHandle(::CreatePopupMenu());
ASSERT_VALID(m_pSendToMenu);
pSubMenu->DestroyMenu();
pMenu->ModifyMenu(i, MF_BYPOSITION | MF_POPUP,
(UINT)m_pSendToMenu->m_hMenu, str);
FillSendToMenu(m_pSendToMenu, stat_data.m_sfSendTo, idm);
}
/////////////////////////////
}
}
// Not needed I think :PO
return;
}
////////////////////////////
// Additions: Philip Oldaker
// Scan the registry looking for a OpenWithList key in this format
// Entry MRUList contains the alphabetical order eg. afgrde for each entry
// each of these entries points to the application name which in turn
// has the command and display name
////////////////////////////
void CShellContextMenu::FillOpenWithMenu(CMenu *pMenu,const CString &sExt)
{
HKEY hKey;
CString sFileExtKey(szFileExtKey);
AddKey(sFileExtKey,sExt);
AddKey(sFileExtKey,szOpenWithListKey);
if (RegOpenKeyEx(HKEY_CURRENT_USER,sFileExtKey,0,KEY_READ,&hKey) != ERROR_SUCCESS)
return;
BYTE szMRUList[_MAX_PATH];
szMRUList[0] = 0;
DWORD dwSize=sizeof(szMRUList);
DWORD dwType=REG_SZ;
RegQueryValueEx(hKey,szMRUListEntry,NULL,&dwType,szMRUList,&dwSize);
int nLen = _tcslen((LPCTSTR)szMRUList);
TCHAR szOpenWithItemEntry[sizeof(TCHAR)*2];
ZeroMemory(szOpenWithItemEntry,sizeof(szOpenWithItemEntry));
BYTE szOpenWithItem[_MAX_PATH];
CString sDisplayName;
HICON hIconApp;
CString sCommand;
CString sMenuText;
for(int i=0;i < nLen;i++)
{
szOpenWithItemEntry[0] = szMRUList[i];
dwSize = sizeof(szOpenWithItem);
RegQueryValueEx(hKey,szOpenWithItemEntry,NULL,&dwType,szOpenWithItem,&dwSize);
GetAppDetails(szOpenWithItem, sDisplayName, sCommand, hIconApp);
if (!sCommand.IsEmpty())
{
for(UINT idm=0;idm < pMenu->GetMenuItemCount();idm++)
{
pMenu->GetMenuString(idm,sMenuText,MF_BYPOSITION);
if (sMenuText == sDisplayName)
{
g_CoolMenuManager.ConvertMenuItem(pMenu, idm);
CCoolMenuManager::SetItemIcon(*pMenu, hIconApp, idm, TRUE);
break;
}
}
}
}
RegCloseKey(hKey);
}
void CShellContextMenu::FillSendToMenu(CMenu *pMenu, LPSHELLFOLDER pSF,
UINT &idm)
{
if (pSF == NULL)
return;
USES_CONVERSION;
CPIDL pidl, abspidl;
LPENUMIDLIST peidl;
HRESULT hr;
STRRET str;
UINT idmStart = idm;
LPSHELLFOLDER pSubSF;
SHFILEINFO sfi;
vecCMSort vMenuItems;
int idx_folder = 0; // folder insertion index
hr = pSF->EnumObjects(m_hWnd,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl);
if (FAILED(hr))
return;
g_CoolMenuManager.ConvertMenu(pMenu);
while (peidl->Next(1, pidl, NULL) == S_OK &&
idm < IDM_SENDTOLAST)
{
hr = pSF->GetDisplayNameOf(pidl, SHGDN_NORMAL, &str);
if (SUCCEEDED(hr))
{
ULONG ulAttrs = (unsigned)-1;
pSF->GetAttributesOf(1, pidl, &ulAttrs);
abspidl.MakeAbsPIDLOf(pSF, pidl);
SHGetFileInfo((LPCTSTR)abspidl.m_pidl, 0, &sfi, sizeof(sfi),
SHGFI_PIDL | SHGFI_ICON | SHGFI_SMALLICON);
pidl.ExtractCStr(str);
if (ulAttrs & SFGAO_FOLDER) // folder?
{
// create new submenu & recurse
HMENU hSubMenu = ::CreateMenu();
pMenu->InsertMenu(idx_folder,
MF_POPUP | MF_BYPOSITION | MF_STRING,
(UINT)hSubMenu, A2T(str.cStr));
g_CoolMenuManager.ConvertMenuItem(pMenu,
idx_folder);
CCoolMenuManager::SetItemIcon(*pMenu,
sfi.hIcon, idx_folder, TRUE);
idx_folder++;
hr = pSF->BindToObject(pidl, NULL,
IID_IShellFolder, (LPVOID *)&pSubSF);
if (!SUCCEEDED(hr)) pSubSF = NULL;
FillSendToMenu(CMenu::FromHandle(hSubMenu), pSubSF,
idm);
if (pSubSF) pSubSF->Release();
abspidl.Free();
}
else
{
CShCMSort *pSMI = new CShCMSort(idm,pidl.m_pidl,sfi.hIcon,A2T(str.cStr),(DWORD)abspidl.m_pidl);
STL_ADD_ITEM(vMenuItems,pSMI);
idm++;
}
abspidl.m_pidl = NULL;
}
}
peidl->Release();
// Addition: Philip Oldaker
// To keep it familiar the SendTo menu is sorted
STL_SORT(vMenuItems,pSF,STL_SORT_FUNC);
CShCMSort *pItem=NULL;
STL_FOR_ITERATOR(vecCMSort,vMenuItems)
{
pItem = STL_GET_CURRENT(vMenuItems);
pMenu->AppendMenu(MF_STRING, pItem->GetItemID(), pItem->GetText());
g_CoolMenuManager.ConvertMenuItem(pMenu,
pMenu->GetMenuItemCount() - 1);
CCoolMenuManager::SetItemIcon(*pMenu,
pItem->GetIcon(), pItem->GetItemID());
CCoolMenuManager::SetItemData(*pMenu,
(void*)pItem->GetItemData(), pItem->GetItemID());
CPIDL toFree(pItem->GetPidl());
delete pItem;
}
STL_ERASE_ALL(vMenuItems);
//////////////////////////////////
// If the menu is still empty (the user has an empty SendTo folder),
// then add a disabled "(empty)" item so we have at least something
// to display.
if (idm == idmStart)
{
pMenu->AppendMenu(MF_GRAYED | MF_DISABLED | MF_STRING, idm,
_T("(empty)"));
idm++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -