[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: Native menu rendering with icons patch (W2k, XP, Vista) (Fixed mistake)

From: Adam Strzelecki <ono_at_java.pl>
Date: 2007-06-11 14:28:36 CEST

Hi Again,

Sorry for spamming so much... but I found a little mistake in my patch.
Updating here.

Sorry once more for so many mails at once.

Best regards,

-- 
: nanoANT Adam Strzelecki :
:       nanoant.com       :

Index: src/TortoiseShell/ContextMenu.cpp
===================================================================
--- src/TortoiseShell/ContextMenu.cpp (wersja 9717)
+++ src/TortoiseShell/ContextMenu.cpp (kopia robocza)
@@ -180,12 +180,6 @@
                                    LPDATAOBJECT pDataObj,
                                    HKEY /* hRegKey */)
 {
- OSVERSIONINFOEX inf;
- ZeroMemory(&inf, sizeof(OSVERSIONINFOEX));
- inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- GetVersionEx((OSVERSIONINFO *)&inf);
- fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);
-
         ATLTRACE("Shell :: Initialize\n");
         PreserveChdir preserveChdir;
         files_.clear();
@@ -540,7 +534,7 @@
         return NOERROR;
 }
 
-void CShellExt::InsertSVNMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UINT stringid, UINT icon, UINT idCmdFirst, SVNCommands com)
+void CShellExt::InsertSVNMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UINT stringid, UINT icon, UINT idCmdFirst, SVNCommands com, UINT uFlags)
 {
         TCHAR menutextbuffer[255] = {0};
         TCHAR verbsbuffer[255] = {0};
@@ -553,10 +547,10 @@
                 _tcscpy_s(menutextbuffer, 255, _T("SVN "));
         }
         _tcscat_s(menutextbuffer, 255, stringtablebuffer);
- if ((fullver >= 0x600)||(fullver <= 0x500))
+ if ((fullver < 0x500)||(fullver == 0x500 && !uFlags))
         {
                 InsertMenu(menu, pos, MF_BYPOSITION | MF_STRING , id, menutextbuffer);
- HBITMAP bmp = IconToBitmap(icon, (COLORREF)GetSysColor(COLOR_MENU));
+ HBITMAP bmp = IconToBitmap(icon);
                 SetMenuItemBitmaps(menu, pos, MF_BYPOSITION, bmp, bmp);
         }
         else
@@ -566,7 +560,7 @@
                 menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_BITMAP | MIIM_STRING;
                 menuiteminfo.fType = MFT_STRING;
                 menuiteminfo.dwTypeData = menutextbuffer;
- menuiteminfo.hbmpItem = HBMMENU_CALLBACK;
+ menuiteminfo.hbmpItem = (fullver >= 0x600) ? IconToBitmapPARGB32(icon) : HBMMENU_CALLBACK;
                 menuiteminfo.wID = id;
                 InsertMenuItem(menu, pos, TRUE, &menuiteminfo);
         }
@@ -596,7 +590,7 @@
                 mySubMenuMap[pos] = com;
 }
 
-HBITMAP CShellExt::IconToBitmap(UINT uIcon, COLORREF transparentColor)
+HBITMAP CShellExt::IconToBitmap(UINT uIcon)
 {
         std::map<UINT, HBITMAP>::iterator bitmap_it = bitmaps.lower_bound(uIcon);
         if (bitmap_it != bitmaps.end() && bitmap_it->first == uIcon)
@@ -606,22 +600,21 @@
         if (!hIcon)
                 return NULL;
 
- RECT rect;
+ RECT rect;
 
         rect.right = ::GetSystemMetrics(SM_CXMENUCHECK);
         rect.bottom = ::GetSystemMetrics(SM_CYMENUCHECK);
 
- rect.left =
- rect.top = 0;
+ rect.left = rect.top = 0;
 
- HWND desktop = ::GetDesktopWindow();
+ HWND desktop = ::GetDesktopWindow();
         if (desktop == NULL)
         {
                 DestroyIcon(hIcon);
                 return NULL;
         }
 
- HDC screen_dev = ::GetDC(desktop);
+ HDC screen_dev = ::GetDC(desktop);
         if (screen_dev == NULL)
         {
                 DestroyIcon(hIcon);
@@ -655,8 +648,9 @@
                 return NULL;
         }
 
- // Fill the background of the compatible DC with the given colour
- ::SetBkColor(dst_hdc, transparentColor);
+ // Fill the background of the compatible DC with the white colour
+ // that is taken by menu routines as transparent
+ ::SetBkColor(dst_hdc, RGB(255, 255, 255));
         ::ExtTextOut(dst_hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);
 
         // Draw the icon into the compatible DC
@@ -726,7 +720,7 @@
         if (((uFlags & 0x000f)!=CMF_NORMAL)&&(!(uFlags & CMF_EXPLORE))&&(!(uFlags & CMF_VERBSONLY)))
                 return NOERROR;
 
- if (folder_.size() == 0)
+ if (folder_.size() == 0)
                 return NOERROR; // no target? this should never happen, but we shouldn't crash anyway just because we can't handle this.
 
         //the drop handler only has eight commands, but not all are visible at the same time:
@@ -737,21 +731,21 @@
         UINT idCmd = idCmdFirst;
 
         if ((itemStates & ITEMIS_FOLDERINSVN)&&((itemStates & ITEMIS_INSVN)&&((~itemStates) & ITEMIS_ADDED)))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPMOVEMENU, 0, idCmdFirst, ShellMenuDropMove);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPMOVEMENU, 0, idCmdFirst, ShellMenuDropMove, uFlags);
         if ((itemStates & ITEMIS_FOLDERINSVN)&&(itemStates & ITEMIS_INSVN)&&(itemStates & ITEMIS_ONLYONE)&&((~itemStates) & ITEMIS_ADDED))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPMOVERENAMEMENU, 0, idCmdFirst, ShellMenuDropMoveRename);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPMOVERENAMEMENU, 0, idCmdFirst, ShellMenuDropMoveRename, uFlags);
         if ((itemStates & ITEMIS_FOLDERINSVN)&&(itemStates & ITEMIS_INSVN)&&((~itemStates) & ITEMIS_ADDED))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYMENU, 0, idCmdFirst, ShellMenuDropCopy);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYMENU, 0, idCmdFirst, ShellMenuDropCopy, uFlags);
         if ((itemStates & ITEMIS_FOLDERINSVN)&&(itemStates & ITEMIS_INSVN)&&(itemStates & ITEMIS_ONLYONE)&&((~itemStates) & ITEMIS_ADDED))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYRENAMEMENU, 0, idCmdFirst, ShellMenuDropCopyRename);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYRENAMEMENU, 0, idCmdFirst, ShellMenuDropCopyRename, uFlags);
         if ((itemStates & ITEMIS_FOLDERINSVN)&&((~itemStates) & ITEMIS_INSVN))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYADDMENU, 0, idCmdFirst, ShellMenuDropCopyAdd);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPCOPYADDMENU, 0, idCmdFirst, ShellMenuDropCopyAdd, uFlags);
         if (((itemStates & ITEMIS_FOLDERINSVN)==0)&&(itemStates & ITEMIS_INSVN))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPEXPORTMENU, 0, idCmdFirst, ShellMenuDropExport);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPEXPORTMENU, 0, idCmdFirst, ShellMenuDropExport, uFlags);
         if (((itemStates & ITEMIS_FOLDERINSVN)==0)&&(itemStates & ITEMIS_INSVN))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPEXPORTEXTENDEDMENU, 0, idCmdFirst, ShellMenuDropExportExtended);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_DROPEXPORTEXTENDEDMENU, 0, idCmdFirst, ShellMenuDropExportExtended, uFlags);
         if ((itemStates & ITEMIS_FOLDERINSVN)&&(itemStates & ITEMIS_PATCHFILE))
- InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_MENUAPPLYPATCH, 0, idCmdFirst, ShellMenuApplyPatch);
+ InsertSVNMenu(FALSE, hMenu, indexMenu++, idCmd++, IDS_MENUAPPLYPATCH, 0, idCmdFirst, ShellMenuApplyPatch, uFlags);
         if (idCmd != idCmdFirst)
                 InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
 
@@ -965,7 +959,8 @@
                                                                                 menuInfo[menuIndex].menuTextID,
                                                                                 menuInfo[menuIndex].iconID,
                                                                                 idCmdFirst,
- menuInfo[menuIndex].command);
+ menuInfo[menuIndex].command,
+ uFlags);
                                                 if (!bIsTop)
                                                         bMenuEntryAdded = true;
                                         }
@@ -981,48 +976,51 @@
         MENUITEMINFO menuiteminfo;
         ZeroMemory(&menuiteminfo, sizeof(menuiteminfo));
         menuiteminfo.cbSize = sizeof(menuiteminfo);
- if ((fullver >= 0x600)||(fullver <= 0x500))
- menuiteminfo.fMask = MIIM_STRING | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA;
- else
- {
- menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;
- menuiteminfo.hbmpItem = HBMMENU_CALLBACK;
- }
         menuiteminfo.fType = MFT_STRING;
          menuiteminfo.dwTypeData = _T("TortoiseSVN\0\0");
 
- HBITMAP bmp = NULL;
+ UINT uIcon = IDI_APP;
         if (folder_.size())
         {
- bmp = IconToBitmap(IDI_MENUFOLDER, (COLORREF)GetSysColor(COLOR_MENU));
+ uIcon = IDI_MENUFOLDER;
                 myIDMap[idCmd - idCmdFirst] = ShellSubMenuFolder;
                 myIDMap[idCmd] = ShellSubMenuFolder;
                 menuiteminfo.dwItemData = (ULONG_PTR)g_MenuIDString;
         }
         else if (((~itemStates) & ITEMIS_SHORTCUT) && (files_.size()==1))
         {
- bmp = IconToBitmap(IDI_MENUFILE, (COLORREF)GetSysColor(COLOR_MENU));
+ uIcon = IDI_MENUFILE;
                 myIDMap[idCmd - idCmdFirst] = ShellSubMenuFile;
                 myIDMap[idCmd] = ShellSubMenuFile;
         }
         else if ((itemStates & ITEMIS_SHORTCUT) && (files_.size()==1))
         {
- bmp = IconToBitmap(IDI_MENULINK, (COLORREF)GetSysColor(COLOR_MENU));
+ uIcon = IDI_MENULINK;
                 myIDMap[idCmd - idCmdFirst] = ShellSubMenuLink;
                 myIDMap[idCmd] = ShellSubMenuLink;
         }
         else if (files_.size() > 1)
         {
- bmp = IconToBitmap(IDI_MENUMULTIPLE, (COLORREF)GetSysColor(COLOR_MENU));
+ uIcon = IDI_MENUMULTIPLE;
                 myIDMap[idCmd - idCmdFirst] = ShellSubMenuMultiple;
                 myIDMap[idCmd] = ShellSubMenuMultiple;
         }
         else
         {
- bmp = IconToBitmap(IDI_APP, (COLORREF)GetSysColor(COLOR_MENU));
                 myIDMap[idCmd - idCmdFirst] = ShellSubMenu;
                 myIDMap[idCmd] = ShellSubMenu;
         }
+ HBITMAP bmp = NULL;
+ if ((fullver < 0x500)||(fullver == 0x500 && !uFlags))
+ {
+ bmp = IconToBitmap(uIcon);
+ menuiteminfo.fMask = MIIM_STRING | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA;
+ }
+ else
+ {
+ menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;
+ menuiteminfo.hbmpItem = (fullver >= 0x600) ? IconToBitmapPARGB32(uIcon) : HBMMENU_CALLBACK;
+ }
         menuiteminfo.hbmpChecked = bmp;
         menuiteminfo.hbmpUnchecked = bmp;
         menuiteminfo.hSubMenu = subMenu;
@@ -1567,7 +1565,7 @@
                                          UINT FAR * /*reserved*/,
                                          LPSTR pszName,
                                          UINT cchMax)
-{
+{
         //do we know the id?
         std::map<UINT_PTR, UINT_PTR>::const_iterator id_it = myIDMap.lower_bound(idCmd);
         if (id_it == myIDMap.end() || id_it->first != idCmd)
@@ -1636,8 +1634,8 @@
 
 STDMETHODIMP CShellExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
 {
- LRESULT res;
- return HandleMenuMsg2(uMsg, wParam, lParam, &res);
+ LRESULT res;
+ return HandleMenuMsg2(uMsg, wParam, lParam, &res);
 }
 
 STDMETHODIMP CShellExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pResult)
@@ -1857,7 +1855,7 @@
         {
                 // check if the item name is ignored or the mask
                 size_t p = 0;
- while ( (p=ignoredprops.find( ignorepath,p )) != -1 )
+ while ( (p=ignoredprops.find( ignorepath,p )) != -1 )
                 {
                         if ( (p==0 || ignoredprops[p-1]==TCHAR('\n'))
                                 && (p+_tcslen(ignorepath)==ignoredprops.length() || ignoredprops[p+_tcslen(ignorepath)+1]==TCHAR('\n')) )
@@ -1948,8 +1946,8 @@
                 menuiteminfo.cbSize = sizeof(menuiteminfo);
                 menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;
                 menuiteminfo.fType = MFT_STRING;
- menuiteminfo.hbmpItem = HBMMENU_CALLBACK;
- HBITMAP bmp = IconToBitmap(IDI_IGNORE, (COLORREF)GetSysColor(COLOR_MENU));
+ HBITMAP bmp = (fullver >= 0x600) ? IconToBitmapPARGB32(IDI_IGNORE) : IconToBitmap(IDI_IGNORE);
+ menuiteminfo.hbmpItem = (fullver >= 0x600) ? bmp : HBMMENU_CALLBACK;
                 menuiteminfo.hbmpChecked = bmp;
                 menuiteminfo.hbmpUnchecked = bmp;
                 menuiteminfo.hSubMenu = ignoresubmenu;
@@ -1976,4 +1974,25 @@
         }
 }
 
+HBITMAP CShellExt::IconToBitmapPARGB32(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;
+ if (!m_gdipToken)
+ return NULL;
+ HICON hIcon = (HICON)LoadImage(g_hResInst, MAKEINTRESOURCE(uIcon), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);
+ if (!hIcon)
+ return NULL;
+ Bitmap icon(hIcon);
+ Bitmap bmp(16, 16, PixelFormat32bppPARGB);
+ Graphics g(&bmp);
+ g.DrawImage(&icon, 0, 0, 16, 16);
 
+ HBITMAP hBmp = NULL;
+ bmp.GetHBITMAP(Color(255, 0, 0, 0), &hBmp);
+
+ if(hBmp)
+ bitmaps.insert(bitmap_it, std::make_pair(uIcon, hBmp));
+ return hBmp;
+}
Index: src/TortoiseShell/ShellExt.cpp
===================================================================
--- src/TortoiseShell/ShellExt.cpp (wersja 9717)
+++ src/TortoiseShell/ShellExt.cpp (kopia robocza)
@@ -31,9 +31,16 @@
 
 std::set<CShellExt *> g_exts;
 
+
 // *********************** CShellExt *************************
 CShellExt::CShellExt(FileState state)
 {
+ OSVERSIONINFOEX inf;
+ ZeroMemory(&inf, sizeof(OSVERSIONINFOEX));
+ inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ GetVersionEx((OSVERSIONINFO *)&inf);
+ fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);
+
     m_State = state;
 
     m_cRef = 0L;
@@ -47,6 +54,13 @@
     };
     InitCommonControlsEx(&used);
         LoadLangDll();
+
+ m_gdipToken = NULL;
+ if(fullver >= 0x600)
+ {
+ GdiplusStartupInput gdiplusStartupInput;
+ GdiplusStartup(&m_gdipToken, &gdiplusStartupInput, NULL);
+ }
 }
 
 CShellExt::~CShellExt()
@@ -59,6 +73,9 @@
         bitmaps.clear();
         g_cRefThisDll--;
         g_exts.erase(this);
+
+ if(m_gdipToken)
+ GdiplusShutdown(m_gdipToken);
 }
 
 void LoadLangDll()
Index: src/TortoiseShell/ShellExt.h
===================================================================
--- src/TortoiseShell/ShellExt.h (wersja 9717)
+++ src/TortoiseShell/ShellExt.h (kopia robocza)
@@ -25,6 +25,10 @@
 #include "RemoteCacheLink.h"
 #include "SVNFolderStatus.h"
 
+// GdiPlus includes
+#include <GdiPlus.h>
+using namespace Gdiplus;
+
 extern UINT g_cRefThisDll; // Reference count of this DLL.
 extern HINSTANCE g_hmodThisDll; // Instance handle for this DLL
 extern SVNFolderStatus * g_pCachedStatus; // status cache
@@ -162,6 +166,7 @@
 
         static MenuInfo menuInfo[];
         WORD fullver;
+ ULONG_PTR m_gdipToken;
         FileState m_State;
         ULONG m_cRef;
         //std::map<int,std::string> verbMap;
@@ -185,12 +190,13 @@
         std::map<UINT, HBITMAP> bitmaps;
 #define MAKESTRING(ID) LoadStringEx(g_hResInst, ID, stringtablebuffer, sizeof(stringtablebuffer)/sizeof(TCHAR), (WORD)CRegStdWORD(_T("Software\\TortoiseSVN\\LanguageID"), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)))
 private:
- void InsertSVNMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UINT stringid, UINT icon, UINT idCmdFirst, SVNCommands com);
+ void InsertSVNMenu(BOOL istop, HMENU menu, UINT pos, UINT_PTR id, UINT stringid, UINT icon, UINT idCmdFirst, SVNCommands com, UINT uFlags);
         void InsertIgnoreSubmenus(UINT &idCmd, UINT idCmdFirst, HMENU hMenu, HMENU subMenu, UINT &indexMenu, int &indexSubMenu, unsigned __int64 topmenu);
         stdstring WriteFileListToTempFile();
         LPCTSTR GetMenuTextFromResource(int id);
         void GetColumnStatus(const TCHAR * path, BOOL bIsDir);
- HBITMAP IconToBitmap(UINT uIcon, COLORREF transparentColor);
+ HBITMAP IconToBitmap(UINT uIcon);
+ HBITMAP IconToBitmapPARGB32(UINT uIcon);
         int GetInstalledOverlays(); ///< returns the maximum number of overlays TSVN shall use
         STDMETHODIMP QueryDropContext(UINT uFlags, UINT idCmdFirst, HMENU hMenu, UINT &indexMenu);
         bool IsIllegalFolder(std::wstring folder, int * cslidarray);

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tortoisesvn.tigris.org
For additional commands, e-mail: dev-help@tortoisesvn.tigris.org
Received on Mon Jun 11 14:29:00 2007

This is an archived mail posted to the TortoiseSVN Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.