Skip to content

Commit 7bc25ae

Browse files
committed
patch 7.4.724
Problem: Vim icon does not show in Windows context menu. (issue 249) Solution: Load the icon in GvimExt.
1 parent 4032cfd commit 7bc25ae

3 files changed

Lines changed: 95 additions & 35 deletions

File tree

src/GvimExt/gvimext.cpp

Lines changed: 89 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,24 @@ getGvimName(char *name, int runtime)
7979
strcpy(name, searchpath((char *)"gvim.bat"));
8080
if (name[0] == 0)
8181
strcpy(name, "gvim"); // finds gvim.bat or gvim.exe
82-
83-
// avoid that Vim tries to expand wildcards in the file names
84-
strcat(name, " --literal");
8582
}
8683
}
8784

8885
static void
89-
getGvimNameW(wchar_t *nameW)
86+
getGvimInvocation(char *name, int runtime)
87+
{
88+
getGvimName(name, runtime);
89+
// avoid that Vim tries to expand wildcards in the file names
90+
strcat(name, " --literal");
91+
}
92+
93+
static void
94+
getGvimInvocationW(wchar_t *nameW)
9095
{
9196
char *name;
9297

9398
name = (char *)malloc(BUFSIZE);
94-
getGvimName(name, 0);
99+
getGvimInvocation(name, 0);
95100
mbstowcs(nameW, name, BUFSIZE);
96101
free(name);
97102
}
@@ -123,6 +128,26 @@ getRuntimeDir(char *buf)
123128
}
124129
}
125130

131+
HBITMAP IconToBitmap(HICON hIcon, HBRUSH hBackground, int width, int height)
132+
{
133+
HDC hDC = GetDC(NULL);
134+
HDC hMemDC = CreateCompatibleDC(hDC);
135+
HBITMAP hMemBmp = CreateCompatibleBitmap(hDC, width, height);
136+
HBITMAP hResultBmp = NULL;
137+
HGDIOBJ hOrgBMP = SelectObject(hMemDC, hMemBmp);
138+
139+
DrawIconEx(hMemDC, 0, 0, hIcon, width, height, 0, hBackground, DI_NORMAL);
140+
141+
hResultBmp = hMemBmp;
142+
hMemBmp = NULL;
143+
144+
SelectObject(hMemDC, hOrgBMP);
145+
DeleteDC(hMemDC);
146+
ReleaseDC(NULL, hDC);
147+
DestroyIcon(hIcon);
148+
return hResultBmp;
149+
}
150+
126151
//
127152
// GETTEXT: translated messages and menu entries
128153
//
@@ -404,7 +429,7 @@ STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid,
404429
{
405430
*ppv = NULL;
406431

407-
// Any interface on this object is the object pointer
432+
// any interface on this object is the object pointer
408433

409434
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
410435
{
@@ -448,7 +473,7 @@ STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN pUnkOuter,
448473
// QueryInterface with IID_IShellExtInit--this is how shell extensions are
449474
// initialized.
450475

451-
LPCSHELLEXT pShellExt = new CShellExt(); //Create the CShellExt object
476+
LPCSHELLEXT pShellExt = new CShellExt(); // create the CShellExt object
452477

453478
if (NULL == pShellExt)
454479
return E_OUTOFMEMORY;
@@ -469,6 +494,8 @@ CShellExt::CShellExt()
469494
m_pDataObj = NULL;
470495

471496
inc_cRefThisDLL();
497+
498+
LoadMenuIcon();
472499
}
473500

474501
CShellExt::~CShellExt()
@@ -477,6 +504,9 @@ CShellExt::~CShellExt()
477504
m_pDataObj->Release();
478505

479506
dec_cRefThisDLL();
507+
508+
if (m_hVimIconBitmap)
509+
DeleteObject(m_hVimIconBitmap);
480510
}
481511

482512
STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv)
@@ -597,6 +627,7 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,
597627

598628
HKEY keyhandle;
599629
bool showExisting = true;
630+
bool showIcons = true;
600631

601632
// Check whether "Edit with existing Vim" entries are disabled.
602633
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0,
@@ -605,35 +636,43 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,
605636
if (RegQueryValueEx(keyhandle, "DisableEditWithExisting", 0, NULL,
606637
NULL, NULL) == ERROR_SUCCESS)
607638
showExisting = false;
639+
if (RegQueryValueEx(keyhandle, "DisableContextMenuIcons", 0, NULL,
640+
NULL, NULL) == ERROR_SUCCESS)
641+
showIcons = false;
608642
RegCloseKey(keyhandle);
609643
}
610644

611645
// Retrieve all the vim instances, unless disabled.
612646
if (showExisting)
613647
EnumWindows(EnumWindowsProc, (LPARAM)this);
614648

649+
MENUITEMINFO mii = { sizeof(MENUITEMINFO) };
650+
mii.fMask = MIIM_STRING | MIIM_ID;
651+
if (showIcons)
652+
{
653+
mii.fMask |= MIIM_BITMAP;
654+
mii.hbmpItem = m_hVimIconBitmap;
655+
}
656+
615657
if (cbFiles > 1)
616658
{
617-
InsertMenu(hMenu,
618-
indexMenu++,
619-
MF_STRING|MF_BYPOSITION,
620-
idCmd++,
621-
_("Edit with &multiple Vims"));
622-
623-
InsertMenu(hMenu,
624-
indexMenu++,
625-
MF_STRING|MF_BYPOSITION,
626-
idCmd++,
627-
_("Edit with single &Vim"));
659+
mii.wID = idCmd++;
660+
mii.dwTypeData = _("Edit with &multiple Vims");
661+
mii.cch = lstrlen(mii.dwTypeData);
662+
InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
663+
664+
mii.wID = idCmd++;
665+
mii.dwTypeData = _("Edit with single &Vim");
666+
mii.cch = lstrlen(mii.dwTypeData);
667+
InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
628668

629669
if (cbFiles <= 4)
630670
{
631671
// Can edit up to 4 files in diff mode
632-
InsertMenu(hMenu,
633-
indexMenu++,
634-
MF_STRING|MF_BYPOSITION,
635-
idCmd++,
636-
_("Diff with Vim"));
672+
mii.wID = idCmd++;
673+
mii.dwTypeData = _("Diff with Vim");
674+
mii.cch = lstrlen(mii.dwTypeData);
675+
InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
637676
m_edit_existing_off = 3;
638677
}
639678
else
@@ -642,11 +681,10 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,
642681
}
643682
else
644683
{
645-
InsertMenu(hMenu,
646-
indexMenu++,
647-
MF_STRING|MF_BYPOSITION,
648-
idCmd++,
649-
_("Edit with &Vim"));
684+
mii.wID = idCmd++;
685+
mii.dwTypeData = _("Edit with &Vim");
686+
mii.cch = lstrlen(mii.dwTypeData);
687+
InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
650688
m_edit_existing_off = 1;
651689
}
652690

@@ -672,11 +710,11 @@ STDMETHODIMP CShellExt::QueryContextMenu(HMENU hMenu,
672710
temp[BUFSIZE - 1] = '\0';
673711
strncat(temp, title, BUFSIZE - 1 - strlen(temp));
674712
temp[BUFSIZE - 1] = '\0';
675-
InsertMenu(hMenu,
676-
indexMenu++,
677-
MF_STRING|MF_BYPOSITION,
678-
idCmd++,
679-
temp);
713+
714+
mii.wID = idCmd++;
715+
mii.dwTypeData = temp;
716+
mii.cch = lstrlen(mii.dwTypeData);
717+
InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
680718
}
681719
// InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
682720

@@ -813,6 +851,22 @@ BOOL CALLBACK CShellExt::EnumWindowsProc(HWND hWnd, LPARAM lParam)
813851
return TRUE; // continue enumeration (otherwise this would be false)
814852
}
815853

854+
BOOL CShellExt::LoadMenuIcon()
855+
{
856+
char vimExeFile[BUFSIZE];
857+
getGvimName(vimExeFile, 1);
858+
if (vimExeFile[0] == '\0')
859+
return FALSE;
860+
HICON hVimIcon;
861+
if (ExtractIconEx(vimExeFile, 0, NULL, &hVimIcon, 1) == 0)
862+
return FALSE;
863+
m_hVimIconBitmap = IconToBitmap(hVimIcon,
864+
GetSysColorBrush(COLOR_MENU),
865+
GetSystemMetrics(SM_CXSMICON),
866+
GetSystemMetrics(SM_CYSMICON));
867+
return TRUE;
868+
}
869+
816870
#ifdef WIN32
817871
// This symbol is not defined in older versions of the SDK or Visual C++.
818872

@@ -893,7 +947,7 @@ STDMETHODIMP CShellExt::InvokeGvim(HWND hParent,
893947
m_szFileUserClickedOn,
894948
sizeof(m_szFileUserClickedOn));
895949

896-
getGvimNameW(cmdStrW);
950+
getGvimInvocationW(cmdStrW);
897951
wcscat(cmdStrW, L" \"");
898952

899953
if ((wcslen(cmdStrW) + wcslen(m_szFileUserClickedOn) + 2) < BUFSIZE)
@@ -961,7 +1015,7 @@ STDMETHODIMP CShellExt::InvokeSingleGvim(HWND hParent,
9611015

9621016
cmdlen = BUFSIZE;
9631017
cmdStrW = (wchar_t *) malloc(cmdlen * sizeof(wchar_t));
964-
getGvimNameW(cmdStrW);
1018+
getGvimInvocationW(cmdStrW);
9651019

9661020
if (useDiff)
9671021
wcscat(cmdStrW, L" -d");

src/GvimExt/gvimext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,14 @@ typedef CShellExtClassFactory *LPCSHELLEXTCLASSFACTORY;
110110
class CShellExt : public IContextMenu,
111111
IShellExtInit
112112
{
113+
private:
114+
BOOL LoadMenuIcon();
115+
113116
protected:
114117
ULONG m_cRef;
115118
LPDATAOBJECT m_pDataObj;
116119
UINT m_edit_existing_off;
120+
HBITMAP m_hVimIconBitmap;
117121

118122
// For some reason, this callback must be static
119123
static BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam);

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,8 @@ static char *(features[]) =
741741

742742
static int included_patches[] =
743743
{ /* Add new patch number below this line */
744+
/**/
745+
724,
744746
/**/
745747
723,
746748
/**/

0 commit comments

Comments
 (0)