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

Native menu rendering with icons patch (W2k, XP, Vista)

From: Adam Strzelecki <ono_at_java.pl>
Date: 2007-05-31 14:44:43 CEST

Hello TortoiseSVN developers!

I'd like to share a method of rendering icons at menus that I did once
for TortoiseCVS. Actually right now you're using MFT_OWNERDRAW to render
a menu and MIIM_CHECKMARKS for the case ownerdraw is off.

The 2nd method was some time ago default & only method for TortoiseCVS,
and it was producing quite ugly icons, and now it is default one for
TortoiseSVN on Vista to keep the original menu style.

Actually since Windows 2000 MIIM_CHECKMARKS or OWNERDRAW menus is not
the only way of having nice menu icons. Actually Windows API offeres you
setting a menu item bitmap callback (hbmpItem = HBMMENU_CALLBACK), where
you can draw the icon yourself, but let Windows to draw everything else,
keeping the original menu style (Vista too). Now TSVN because of full
ownerdraw is NOT respecting visual style of menu neither on XP nor Vista.

Anyway I'm attaching the patch for TortoiseSVN.

Theoretically you could get rid of old ownerdraw code at all, where you
pain all the texts, because it is useless on Win2k or never systems, and
on old Win9x (is it supported) anyway you can use MIIM_CHECKMARKS.
HBMMENU_CALLBACK code is much lighter as it doesn't need to do much on
WM_ITEMMEASURE -> just as some space for icon, neither on WM_ITEMDRAW,
just drawing icon with DrawIconEx.

Cheers,

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

Index: src/TortoiseShell/ContextMenu.cpp
===================================================================
--- src/TortoiseShell/ContextMenu.cpp (wersja 9609)
+++ src/TortoiseShell/ContextMenu.cpp (kopia robocza)
@@ -180,6 +180,12 @@
                                    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();
@@ -550,7 +556,21 @@
         _tcscat_s(menutextbuffer, 255, stringtablebuffer);
         if (ownerdrawn==1)
         {
- InsertMenu(menu, pos, MF_BYPOSITION | MF_STRING | MF_OWNERDRAW, id, menutextbuffer);
+ if (fullver >= 0x0501)
+ {
+ MENUITEMINFO menuiteminfo;
+ ZeroMemory(&menuiteminfo, sizeof(menuiteminfo));
+ menuiteminfo.cbSize = sizeof(menuiteminfo);
+ menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;
+ menuiteminfo.fType = MFT_STRING;
+ menuiteminfo.dwTypeData = menutextbuffer;
+ menuiteminfo.cch = (UINT)min(_tcslen(menuiteminfo.dwTypeData), UINT_MAX);
+ menuiteminfo.hbmpItem = HBMMENU_CALLBACK;
+ menuiteminfo.wID = id;
+ InsertMenuItem(menu, pos, TRUE, &menuiteminfo);
+ }
+ else
+ InsertMenu(menu, pos, MF_BYPOSITION | MF_STRING | MF_OWNERDRAW, id, menutextbuffer);
         }
         else if (ownerdrawn==0)
         {
@@ -827,13 +847,9 @@
         // On Vista, owner drawn menus force the context menu to the 'old' UI style.
         // Since we like improved UIs, we don't want to do that so we simply
         // don't draw the menus on Vista ourselves.
- OSVERSIONINFOEX inf;
- ZeroMemory(&inf, sizeof(OSVERSIONINFOEX));
- inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
- GetVersionEx((OSVERSIONINFO *)&inf);
- WORD fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);
- if (fullver >= 0x0600)
- ownerdrawn = 0;
+ // WORD fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);
+ // if (fullver >= 0x0600)
+ // ownerdrawn = 0;
 
         //check if we already added our menu entry for a folder.
         //we check that by iterating through all menu entries and check if
@@ -985,12 +1001,18 @@
         ZeroMemory(&menuiteminfo, sizeof(menuiteminfo));
         menuiteminfo.cbSize = sizeof(menuiteminfo);
         if ((ownerdrawn==1)&&(fullver >= 0x0501))
- menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA;
+ menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;
         else if (ownerdrawn == 0)
                 menuiteminfo.fMask = MIIM_STRING | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA;
         else
                 menuiteminfo.fMask = MIIM_STRING | MIIM_ID | MIIM_SUBMENU| MIIM_DATA;
- menuiteminfo.fType = MFT_OWNERDRAW;
+ if ((ownerdrawn==1)&&(fullver >= 0x0501))
+ {
+ menuiteminfo.fType = MFT_STRING;
+ menuiteminfo.hbmpItem = HBMMENU_CALLBACK;
+ }
+ else
+ menuiteminfo.fType = MFT_OWNERDRAW;
          menuiteminfo.dwTypeData = _T("TortoiseSVN\0\0");
         menuiteminfo.cch = (UINT)min(_tcslen(menuiteminfo.dwTypeData), UINT_MAX);
 
@@ -1664,6 +1686,13 @@
                         if (lpmis==NULL)
                                 break;
                         *pResult = TRUE;
+ if (fullver >= 0x0501)
+ {
+ lpmis->itemWidth += 2;
+ if(lpmis->itemHeight < 16)
+ lpmis->itemHeight = 16;
+ break;
+ }
                         lpmis->itemWidth = 0;
                         lpmis->itemHeight = 0;
                         POINT size;
@@ -1701,6 +1730,19 @@
                         resource = GetMenuTextFromResource(myIDMap[lpdis->itemID]);
                         if (resource == NULL)
                                 return S_OK;
+ if (fullver >= 0x0501)
+ {
+ HICON hIcon = (HICON)LoadImage(GetModuleHandle(_T("TortoiseSVN")), resource, IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR | LR_SHARED);
+ if (hIcon == NULL)
+ return S_OK;
+ DrawIconEx(lpdis->hDC,
+ lpdis->rcItem.left - 16,
+ lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top - 16) / 2,
+ hIcon, 16, 16,
+ 0, NULL, DI_NORMAL);
+ *pResult = TRUE;
+ break;
+ }
                         szItem = stringtablebuffer;
                         int ix, iy;
                         RECT rt, rtTemp;
@@ -2060,12 +2102,18 @@
                 GetVersionEx((OSVERSIONINFO *)&inf);
                 WORD fullver = MAKEWORD(inf.dwMinorVersion, inf.dwMajorVersion);
                 if ((ownerdrawn==1)&&(fullver >= 0x0501))
- menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU;
+ menuiteminfo.fMask = MIIM_FTYPE | MIIM_ID | MIIM_SUBMENU | MIIM_DATA | MIIM_BITMAP | MIIM_STRING;
                 else if (ownerdrawn == 0)
                         menuiteminfo.fMask = MIIM_STRING | MIIM_ID | MIIM_SUBMENU | MIIM_CHECKMARKS | MIIM_DATA;
                 else
                         menuiteminfo.fMask = MIIM_STRING | MIIM_ID | MIIM_SUBMENU| MIIM_DATA;
- menuiteminfo.fType = MFT_OWNERDRAW;
+ if ((ownerdrawn==1)&&(fullver >= 0x0501))
+ {
+ menuiteminfo.fType = MFT_STRING;
+ menuiteminfo.hbmpItem = HBMMENU_CALLBACK;
+ }
+ else
+ menuiteminfo.fType = MFT_OWNERDRAW;
                 HBITMAP bmp = IconToBitmap(IDI_IGNORE, (COLORREF)GetSysColor(COLOR_MENU));
                 menuiteminfo.hbmpChecked = bmp;
                 menuiteminfo.hbmpUnchecked = bmp;
Index: src/TortoiseShell/ShellExt.h
===================================================================
--- src/TortoiseShell/ShellExt.h (wersja 9609)
+++ src/TortoiseShell/ShellExt.h (kopia robocza)
@@ -161,6 +161,7 @@
         };
 
         static MenuInfo menuInfo[];
+ WORD fullver;
         FileState m_State;
         ULONG m_cRef;
         //std::map<int,std::string> verbMap;

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tortoisesvn.tigris.org
For additional commands, e-mail: dev-help@tortoisesvn.tigris.org
Received on Thu May 31 14:45:01 2007

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