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); }
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); }