BOOL CIconMenu::AppendMenuIcon(UINT_PTR nIDNewItem, LPCTSTR lpszNewItem, UINT uIcon /* = 0 */, HMENU hsubmenu) { TCHAR menutextbuffer[255] = {0}; _tcscpy_s(menutextbuffer, 255, lpszNewItem); if (uIcon == 0) return CMenu::AppendMenu(MF_STRING | MF_ENABLED, nIDNewItem, menutextbuffer); MENUITEMINFO info = {0}; info.cbSize = sizeof(info); info.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID; info.fType = MFT_STRING; if(hsubmenu) { info.fMask |= MIIM_SUBMENU; info.hSubMenu = hsubmenu; } info.wID = (UINT)nIDNewItem; info.dwTypeData = menutextbuffer; if (SysInfo::Instance().IsVistaOrLater()) { info.fMask |= MIIM_BITMAP; info.hbmpItem = IconToBitmapPARGB32(uIcon); } else { info.fMask |= MIIM_BITMAP; info.hbmpItem = HBMMENU_CALLBACK; } icons[nIDNewItem] = uIcon; return InsertMenuItem((UINT)nIDNewItem, &info); }
UINT CGitExtensionsShellEx::AddMenuItem(HMENU hMenu, LPTSTR text, int resource, UINT uidFirstCmd, UINT id, UINT position, bool isSubMenu) { MENUITEMINFO mii; memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STRING | MIIM_ID; if (resource) { mii.fMask |= MIIM_BITMAP; mii.hbmpItem = IsVistaOrLater() ? IconToBitmapPARGB32(resource) : HBMMENU_CALLBACK; myIDMap[id] = resource; myIDMap[uidFirstCmd + id] = resource; } mii.wID = uidFirstCmd + id; std::wstring textEx; if (isSubMenu) mii.dwTypeData = text; else { textEx = std::wstring(L"GitEx ") + text; mii.dwTypeData = &textEx[0]; } InsertMenuItem(hMenu, position, TRUE, &mii); return id; }
HBITMAP IconBitmapUtils::IconToBitmapPARGB32(HINSTANCE hInst, UINT uIcon) { std::map<UINT, HBITMAP>::iterator bitmap_it = bitmaps.lower_bound(uIcon); if (bitmap_it != bitmaps.end() && bitmap_it->first == uIcon) return bitmap_it->second; HICON hIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(uIcon), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR); HBITMAP hBmp = IconToBitmapPARGB32(hIcon); DestroyIcon(hIcon); if(hBmp) bitmaps.insert(bitmap_it, std::make_pair(uIcon, hBmp)); return hBmp; }
HBITMAP IconBitmapUtils::IconToBitmapPARGB32(HINSTANCE hInst, UINT uIcon) { std::map<UINT, HBITMAP>::iterator bitmap_it = bitmaps.lower_bound(uIcon); if (bitmap_it != bitmaps.end() && bitmap_it->first == uIcon) return bitmap_it->second; int iconWidth = GetSystemMetrics(SM_CXSMICON); int iconHeight = GetSystemMetrics(SM_CYSMICON); auto hIcon = LoadIconEx(hInst, MAKEINTRESOURCE(uIcon), iconWidth, iconHeight); HBITMAP hBmp = IconToBitmapPARGB32(hIcon, iconWidth, iconHeight); DestroyIcon(hIcon); if(hBmp) bitmaps.insert(bitmap_it, std::make_pair(uIcon, hBmp)); return hBmp; }
void CGitExtensionsShellEx::AddMenuItem(HMENU hMenu, LPSTR text, int resource, int firstId, int id, UINT position) { MENUITEMINFO mii; memset(&mii, 0, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_STRING | MIIM_ID; if (resource) { mii.fMask |= MIIM_BITMAP; mii.hbmpItem = IsVistaOrLater() ? IconToBitmapPARGB32(resource) : HBMMENU_CALLBACK; myIDMap[id] = resource; myIDMap[firstId + id] = resource; } mii.wID = firstId + id; mii.dwTypeData = text; InsertMenuItem(hMenu, position, TRUE, &mii); }
STDMETHODIMP CGitExtensionsShellEx::QueryContextMenu ( HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags ) { // If the flags include CMF_DEFAULTONLY then we shouldn't do anything. if ( uFlags & CMF_DEFAULTONLY ) return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 ); int id = 0; CString szCascadeContextMenu = GetRegistryValue(HKEY_CURRENT_USER, "SOFTWARE\\GitExtensions\\GitExtensions", "ShellCascadeContextMenu"); CascadeContextMenu = !(szCascadeContextMenu == "False"); if (CascadeContextMenu) { // show context menu cascaded in submenu HMENU popupMenu = CreateMenu(); id = PopulateMenu(popupMenu, uidFirstCmd, id, true); MENUITEMINFO info; info.cbSize = sizeof( MENUITEMINFO ); info.fMask = MIIM_STRING | MIIM_ID | MIIM_BITMAP | MIIM_SUBMENU; info.wID = uidFirstCmd + 1; info.hbmpItem = IsVistaOrLater() ? IconToBitmapPARGB32(IDI_GITEXTENSIONS) : HBMMENU_CALLBACK; myIDMap[1] = IDI_GITEXTENSIONS; myIDMap[uidFirstCmd + 1] = IDI_GITEXTENSIONS; info.dwTypeData = _T("Git Extensions"); info.hSubMenu = popupMenu; InsertMenuItem(hmenu, 0, true, &info); } else { // show menu items directly id = PopulateMenu(hmenu, uidFirstCmd, id, false); } return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, id ); }
STDMETHODIMP CGitExtensionsShellEx::QueryContextMenu ( HMENU hMenu, UINT menuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags ) { // If the flags include CMF_DEFAULTONLY then we shouldn't do anything. if ( uFlags & CMF_DEFAULTONLY ) return S_OK; CString szCascadeShellMenuItems = GetRegistryValue(HKEY_CURRENT_USER, L"SOFTWARE\\GitExtensions\\GitExtensions", L"CascadeShellMenuItems"); if (szCascadeShellMenuItems.IsEmpty()) szCascadeShellMenuItems = "110111000111111111"; bool CascadeContextMenu = szCascadeShellMenuItems.Find('1') != -1; HMENU popupMenu = NULL; if (CascadeContextMenu) popupMenu = CreateMenu(); bool isValidDir = IsValidGitDir(m_szFile); bool isFile = IsFileExists(m_szFile); // preset values, if not used commandsId.clear(); UINT submenuIndex = 0; int id = 0; int cmdid; bool isSubMenu; if (isValidDir) { if (!isFile) { isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcBrowse); cmdid = AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Browse", IDI_ICONBROWSEFILEEXPLORER, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcBrowse; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCommit); cmdid = AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Commit", IDI_ICONCOMMIT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCommit; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcPull); cmdid = AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Pull", IDI_ICONPULL, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcPull; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcPush); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Push", IDI_ICONPUSH, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcPush; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcStash); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"View stash", IDI_ICONSTASH, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcStash; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcViewDiff); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"View changes", IDI_ICONVIEWCHANGES, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcViewDiff; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCheckoutBranch); if (isSubMenu && submenuIndex > 0) { InsertMenu(popupMenu, submenuIndex++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); ++id; } cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Checkout branch", IDI_ICONBRANCHCHECKOUT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCheckoutBranch; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCheckoutRevision); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Checkout revision", IDI_ICONREVISIONCHECKOUT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCheckoutRevision; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCreateBranch); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Create branch", IDI_ICONBRANCHCREATE, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCreateBranch; } isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcDiffTool); if (isSubMenu && submenuIndex > 0) { InsertMenu(popupMenu, submenuIndex++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); ++id; } cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Open with difftool", IDI_ICONVIEWCHANGES, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcDiffTool; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcFileHistory); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"File history", IDI_ICONFILEHISTORY, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcFileHistory; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcResetFileChanges); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Reset file changes", IDI_ICONTRESETFILETO, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcResetFileChanges; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcAddFiles); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Add files", IDI_ICONADDED, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcAddFiles; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcApplyPatch); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Apply patch", 0, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcApplyPatch; } else { isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcClone); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Clone", IDI_ICONCLONEREPOGIT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcClone; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCreateRepository); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Create new repository", IDI_ICONCREATEREPOSITORY, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCreateRepository; } isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcSettings); if (isSubMenu && submenuIndex > 0) { InsertMenu(popupMenu, submenuIndex++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); ++id; } cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Settings", IDI_ICONSETTINGS, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcSettings; ++id; if (CascadeContextMenu) { MENUITEMINFO info; info.cbSize = sizeof( MENUITEMINFO ); info.fMask = MIIM_STRING | MIIM_ID | MIIM_BITMAP | MIIM_SUBMENU; info.wID = uidFirstCmd + 1; info.hbmpItem = IsVistaOrLater() ? IconToBitmapPARGB32(IDI_GITEXTENSIONS) : HBMMENU_CALLBACK; myIDMap[1] = IDI_GITEXTENSIONS; myIDMap[uidFirstCmd + 1] = IDI_GITEXTENSIONS; info.dwTypeData = _T("Git Extensions"); info.hSubMenu = popupMenu; InsertMenuItem(hMenu, menuIndex, true, &info); } return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, id); }
// *** IContextMenu methods *** STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) { UINT idCmd = idCmdFirst; FORMATETC fmte = { CF_HDROP, (DVTARGETDEVICE FAR *)NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HRESULT hres = m_pDataObj->GetData(&fmte, &m_stgMedium); if (SUCCEEDED(hres)) { if (m_stgMedium.hGlobal) m_cbFiles = DragQueryFile((HDROP)m_stgMedium.hGlobal, (UINT)-1, 0, 0); } UINT nIndex = indexMenu++; InsertMenu(hMenu, nIndex, MF_STRING|MF_BYPOSITION, idCmd++, m_szMenuTitle); if (m_showIcon) { HBITMAP icon = NULL; if (m_winVer >= WINVER_VISTA) { icon = NULL; HICON hicon; DWORD menuIconWidth = GetSystemMetrics(SM_CXMENUCHECK); DWORD menuIconHeight = GetSystemMetrics(SM_CYMENUCHECK); HRESULT hr = LoadShellIcon(menuIconWidth, menuIconHeight, &hicon); if (SUCCEEDED(hr)) { icon = IconToBitmapPARGB32(hicon, menuIconWidth, menuIconHeight); DestroyIcon(hicon); } } else { icon = HBMMENU_CALLBACK; } if (icon != NULL) { MENUITEMINFO mii; ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(mii); mii.fMask = MIIM_BITMAP; mii.hbmpItem = icon; //mii.hbmpChecked = icon; //mii.hbmpUnchecked = icon; SetMenuItemInfo(hMenu, nIndex, MF_BYPOSITION, &mii); if (m_winVer >= WINVER_VISTA) { MENUINFO MenuInfo; MenuInfo.cbSize = sizeof(MenuInfo); MenuInfo.fMask = MIM_STYLE; MenuInfo.dwStyle = MNS_CHECKORBMP; SetMenuInfo(hMenu, &MenuInfo); } } } m_hMenu = hMenu; m_menuID = idCmd; return ResultFromShort(idCmd-idCmdFirst); }
STDMETHODIMP CGitExtensionsShellEx::QueryContextMenu( HMENU hMenu, UINT menuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags) { DBG_TRACE(L"CGitExtensionsShellEx::QueryContextMenu(menuIndex=%u,uidLastCmd=%u,uFlags=%u)", menuIndex, uidLastCmd, uFlags); // If the flags include CMF_DEFAULTONLY then we shouldn't do anything. if (uFlags & CMF_DEFAULTONLY) return S_OK; //check if we already added our menu entry for a folder. //we check that by iterating through all menu entries and check if //the dwItemData member points to our global ID string. That string is set //by our shell extension when the folder menu is inserted. TCHAR menubuf[MAX_PATH]; int count = GetMenuItemCount(hMenu); for (int i=0; i<count; ++i) { MENUITEMINFO miif; SecureZeroMemory(&miif, sizeof(MENUITEMINFO)); miif.cbSize = sizeof(MENUITEMINFO); miif.fMask = MIIM_DATA; miif.dwTypeData = menubuf; miif.cch = _countof(menubuf); GetMenuItemInfo(hMenu, i, TRUE, &miif); if (miif.dwItemData == (ULONG_PTR)_Module.GetModuleInstance()) { DBG_TRACE(L"Menu already added"); return S_OK; } } CString szCascadeShellMenuItems = GetRegistryValue(HKEY_CURRENT_USER, L"SOFTWARE\\GitExtensions", L"CascadeShellMenuItems"); if (szCascadeShellMenuItems.IsEmpty()) szCascadeShellMenuItems = "110111000111111111"; bool cascadeContextMenu = szCascadeShellMenuItems.Find('1') != -1; bool alwaysShowAllCommands = GetRegistryBoolValue(HKEY_CURRENT_USER, L"SOFTWARE\\GitExtensions", L"AlwaysShowAllCommands"); HMENU popupMenu = NULL; if (cascadeContextMenu) popupMenu = CreateMenu(); bool isValidDir = true; bool isFolder = true; if (!alwaysShowAllCommands) { isValidDir = IsValidGitDir(m_szFile); isFolder = !IsFileExists(m_szFile); } // preset values, if not used commandsId.clear(); UINT submenuIndex = 0; int id = 0; int cmdid; bool isSubMenu; if (alwaysShowAllCommands || !isValidDir) { isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcClone); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Clone...", IDI_ICONCLONEREPOGIT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcClone; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCreateRepository); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Create new repository...", IDI_ICONCREATEREPOSITORY, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCreateRepository; } if (isValidDir) { isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcBrowse); cmdid = AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Browse", IDI_ICONBROWSEFILEEXPLORER, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcBrowse; if (isFolder) { isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCommit); cmdid = AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Commit...", IDI_ICONCOMMIT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCommit; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcPull); cmdid = AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Pull...", IDI_ICONPULL, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcPull; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcPush); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Push...", IDI_ICONPUSH, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcPush; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcStash); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"View stash", IDI_ICONSTASH, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcStash; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcViewDiff); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"View changes", IDI_ICONVIEWCHANGES, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcViewDiff; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCheckoutBranch); if (isSubMenu && submenuIndex > 0) { InsertMenu(popupMenu, submenuIndex++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); ++id; } cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Checkout branch...", IDI_ICONBRANCHCHECKOUT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCheckoutBranch; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCheckoutRevision); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Checkout revision...", IDI_ICONREVISIONCHECKOUT, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCheckoutRevision; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcCreateBranch); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Create branch...", IDI_ICONBRANCHCREATE, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcCreateBranch; } isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcDiffTool); if (isSubMenu && submenuIndex > 0) { InsertMenu(popupMenu, submenuIndex++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); ++id; } cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Open with difftool", IDI_ICONVIEWCHANGES, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcDiffTool; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcFileHistory); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"File history", IDI_ICONFILEHISTORY, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcFileHistory; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcResetFileChanges); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Reset file changes...", IDI_ICONTRESETFILETO, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcResetFileChanges; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcAddFiles); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Add files...", IDI_ICONADDED, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcAddFiles; isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcApplyPatch); cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Apply patch...", 0, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcApplyPatch; } isSubMenu = DisplayInSubmenu(szCascadeShellMenuItems, gcSettings); if (isSubMenu && submenuIndex > 0) { InsertMenu(popupMenu, submenuIndex++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); ++id; } cmdid=AddMenuItem(!isSubMenu ? hMenu : popupMenu, L"Settings", IDI_ICONSETTINGS, uidFirstCmd, ++id, !isSubMenu ? menuIndex++ : submenuIndex++, isSubMenu); commandsId[cmdid]=gcSettings; ++id; if (cascadeContextMenu) { MENUITEMINFO info; info.cbSize = sizeof(MENUITEMINFO); info.fMask = MIIM_STRING | MIIM_ID | MIIM_BITMAP | MIIM_SUBMENU; info.wID = uidFirstCmd + 1; info.hbmpItem = IsVistaOrLater() ? IconToBitmapPARGB32(IDI_GITEXTENSIONS) : HBMMENU_CALLBACK; myIDMap[1] = IDI_GITEXTENSIONS; myIDMap[uidFirstCmd + 1] = IDI_GITEXTENSIONS; info.dwTypeData = _T("Git Extensions"); info.hSubMenu = popupMenu; InsertMenuItem(hMenu, menuIndex, true, &info); } return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, id); }
STDMETHODIMP CDeskBand::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT uFlags) { if ((uFlags & CMF_DEFAULTONLY)!=0) return S_OK; //we don't change the default action if (((uFlags & 0x000f)!=CMF_NORMAL)&&(!(uFlags & CMF_EXPLORE))&&(!(uFlags & CMF_VERBSONLY))) return S_OK; if ((m_ContextDirectory.empty()) && (m_ContextItems.empty())) return S_OK; if (m_ContextDirectory.empty()) { // folder is empty, but maybe files are selected if (m_ContextItems.empty()) return S_OK; // nothing selected - we don't have a menu to show // check whether a selected entry is an UID - those are namespace extensions // which we can't handle for (std::map<tstring, ULONG>::const_iterator it = m_ContextItems.begin(); it != m_ContextItems.end(); ++it) { if (_tcsncmp(it->first.c_str(), _T("::{"), 3)==0) return S_OK; } } else { // ignore namespace extensions if (_tcsncmp(m_ContextDirectory.c_str(), _T("::{"), 3)==0) return S_OK; } if (DWORD(CRegStdDWORD(_T("Software\\StefansTools\\StExBar\\ContextMenu"), TRUE)) == FALSE) return S_OK; //check if we already added our menu entry for a folder. //we check that by iterating through all menu entries and check if //the dwItemData member points to our global ID string. That string is set //by our shell extension when the folder menu is inserted. TCHAR menubuf[MAX_PATH]; int count = GetMenuItemCount(hMenu); for (int i=0; i<count; ++i) { MENUITEMINFO miif; SecureZeroMemory(&miif, sizeof(MENUITEMINFO)); miif.cbSize = sizeof(MENUITEMINFO); miif.fMask = MIIM_DATA; miif.dwTypeData = menubuf; miif.cch = _countof(menubuf); GetMenuItemInfo(hMenu, i, TRUE, &miif); if (miif.dwItemData == (ULONG_PTR)g_MenuIDString) return S_OK; } UINT idCmd = idCmdFirst; //create the sub menu HMENU subMenu = CreateMenu(); int indexSubMenu = 0; m_commands.LoadFromFile(); int index = 0; for (int j = 0; j < m_commands.GetCount(); ++j) { MENUITEMINFO menuiteminfo = {0}; Command cmd = m_commands.GetCommand(j); m_hotkeys[cmd.key] = j; if ((cmd.commandline.compare(INTERNALCOMMANDHIDDEN)==0)&&(cmd.name.compare(_T("Options")) == 0)) { cmd.commandline = INTERNALCOMMAND; // make sure the options button is never hidden. m_commands.SetCommand(j, cmd); } if ((cmd.name.compare(_T("StexBar Internal Edit Box")) == 0)|| (cmd.commandline.compare(INTERNALCOMMANDHIDDEN) == 0)|| (cmd.name.compare(_T("New Folder")) == 0)) { continue; } bool bEnabled = cmd.enabled_viewpath || (cmd.enabled_fileselected && !m_ContextItems.empty()) || (cmd.enabled_folderselected && (!m_ContextItems.empty() || !m_ContextDirectory.empty())) || (cmd.enabled_noselection && (m_ContextItems.empty())) || (cmd.enabled_selectedcount && (cmd.enabled_selectedcount == (int)!m_ContextItems.empty())); HICON hIcon = LoadCommandIcon(cmd); if (hIcon) { menuiteminfo.hbmpItem = IsWindowsVistaOrGreater() ? IconToBitmapPARGB32(hIcon) : HBMMENU_CALLBACK; DestroyIcon(hIcon); } else menuiteminfo.hbmpItem = NULL; if (!cmd.separator) m_tooltips[j] = cmd.name.c_str(); myIDMap[idCmd - idCmdFirst] = j; myIDMap[idCmd] = j; menuiteminfo.cbSize = sizeof(menuiteminfo); menuiteminfo.fMask = cmd.separator ? MIIM_FTYPE : MIIM_FTYPE | MIIM_ID | MIIM_BITMAP | MIIM_STRING | MIIM_STATE; menuiteminfo.fType = cmd.separator ? MFT_SEPARATOR : MFT_STRING; menuiteminfo.fState = bEnabled ? MFS_ENABLED : MFS_DISABLED; TCHAR menutextbuf[100]; _tcscpy_s(menutextbuf, _countof(menutextbuf), m_commands.GetCommandPtr(j)->name.c_str()); menuiteminfo.dwTypeData = menutextbuf; menuiteminfo.wID = idCmd++; InsertMenuItem(subMenu, indexSubMenu++, TRUE, &menuiteminfo); index++; } //add sub menu to main context menu //don't use InsertMenu because this will lead to multiple menu entries in the explorer file menu. //see http://support.microsoft.com/default.aspx?scid=kb;en-us;214477 for details of that. MENUITEMINFO menuiteminfo = {0}; SecureZeroMemory(&menuiteminfo, sizeof(menuiteminfo)); menuiteminfo.cbSize = sizeof(menuiteminfo); menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_STRING; menuiteminfo.fType = MFT_STRING; menuiteminfo.dwTypeData = _T("StEx"); menuiteminfo.hSubMenu = subMenu; menuiteminfo.wID = idCmd++; InsertMenuItem(hMenu, indexMenu++, TRUE, &menuiteminfo); //return number of menu items added return ResultFromScode(MAKE_SCODE(SEVERITY_SUCCESS, 0, (USHORT)(idCmd - idCmdFirst))); }