comparison src/GvimExt/gvimext.cpp @ 6805:81cb471657e0 v7.4.724

patch 7.4.724 Problem: Vim icon does not show in Windows context menu. (issue 249) Solution: Load the icon in GvimExt.
author Bram Moolenaar <bram@vim.org>
date Mon, 04 May 2015 18:27:36 +0200
parents 04736b4030ec
children 1e48ffa2d697
comparison
equal deleted inserted replaced
6804:0d87f7311e5b 6805:81cb471657e0
77 // search for the batch file or a name without a path. 77 // search for the batch file or a name without a path.
78 if (name[0] == 0) 78 if (name[0] == 0)
79 strcpy(name, searchpath((char *)"gvim.bat")); 79 strcpy(name, searchpath((char *)"gvim.bat"));
80 if (name[0] == 0) 80 if (name[0] == 0)
81 strcpy(name, "gvim"); // finds gvim.bat or gvim.exe 81 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");
85 } 82 }
86 } 83 }
87 84
88 static void 85 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)
90 { 95 {
91 char *name; 96 char *name;
92 97
93 name = (char *)malloc(BUFSIZE); 98 name = (char *)malloc(BUFSIZE);
94 getGvimName(name, 0); 99 getGvimInvocation(name, 0);
95 mbstowcs(nameW, name, BUFSIZE); 100 mbstowcs(nameW, name, BUFSIZE);
96 free(name); 101 free(name);
97 } 102 }
98 103
99 // 104 //
119 { 124 {
120 buf[idx + 1] = 0; 125 buf[idx + 1] = 0;
121 break; 126 break;
122 } 127 }
123 } 128 }
129 }
130
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;
124 } 149 }
125 150
126 // 151 //
127 // GETTEXT: translated messages and menu entries 152 // GETTEXT: translated messages and menu entries
128 // 153 //
402 STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid, 427 STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID riid,
403 LPVOID FAR *ppv) 428 LPVOID FAR *ppv)
404 { 429 {
405 *ppv = NULL; 430 *ppv = NULL;
406 431
407 // Any interface on this object is the object pointer 432 // any interface on this object is the object pointer
408 433
409 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory)) 434 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
410 { 435 {
411 *ppv = (LPCLASSFACTORY)this; 436 *ppv = (LPCLASSFACTORY)this;
412 437
446 471
447 // Create the main shell extension object. The shell will then call 472 // Create the main shell extension object. The shell will then call
448 // QueryInterface with IID_IShellExtInit--this is how shell extensions are 473 // QueryInterface with IID_IShellExtInit--this is how shell extensions are
449 // initialized. 474 // initialized.
450 475
451 LPCSHELLEXT pShellExt = new CShellExt(); //Create the CShellExt object 476 LPCSHELLEXT pShellExt = new CShellExt(); // create the CShellExt object
452 477
453 if (NULL == pShellExt) 478 if (NULL == pShellExt)
454 return E_OUTOFMEMORY; 479 return E_OUTOFMEMORY;
455 480
456 return pShellExt->QueryInterface(riid, ppvObj); 481 return pShellExt->QueryInterface(riid, ppvObj);
467 { 492 {
468 m_cRef = 0L; 493 m_cRef = 0L;
469 m_pDataObj = NULL; 494 m_pDataObj = NULL;
470 495
471 inc_cRefThisDLL(); 496 inc_cRefThisDLL();
497
498 LoadMenuIcon();
472 } 499 }
473 500
474 CShellExt::~CShellExt() 501 CShellExt::~CShellExt()
475 { 502 {
476 if (m_pDataObj) 503 if (m_pDataObj)
477 m_pDataObj->Release(); 504 m_pDataObj->Release();
478 505
479 dec_cRefThisDLL(); 506 dec_cRefThisDLL();
507
508 if (m_hVimIconBitmap)
509 DeleteObject(m_hVimIconBitmap);
480 } 510 }
481 511
482 STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv) 512 STDMETHODIMP CShellExt::QueryInterface(REFIID riid, LPVOID FAR *ppv)
483 { 513 {
484 *ppv = NULL; 514 *ppv = NULL;
595 // Initialize m_cntOfHWnd to 0 625 // Initialize m_cntOfHWnd to 0
596 m_cntOfHWnd = 0; 626 m_cntOfHWnd = 0;
597 627
598 HKEY keyhandle; 628 HKEY keyhandle;
599 bool showExisting = true; 629 bool showExisting = true;
630 bool showIcons = true;
600 631
601 // Check whether "Edit with existing Vim" entries are disabled. 632 // Check whether "Edit with existing Vim" entries are disabled.
602 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0, 633 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Vim\\Gvim", 0,
603 KEY_READ, &keyhandle) == ERROR_SUCCESS) 634 KEY_READ, &keyhandle) == ERROR_SUCCESS)
604 { 635 {
605 if (RegQueryValueEx(keyhandle, "DisableEditWithExisting", 0, NULL, 636 if (RegQueryValueEx(keyhandle, "DisableEditWithExisting", 0, NULL,
606 NULL, NULL) == ERROR_SUCCESS) 637 NULL, NULL) == ERROR_SUCCESS)
607 showExisting = false; 638 showExisting = false;
639 if (RegQueryValueEx(keyhandle, "DisableContextMenuIcons", 0, NULL,
640 NULL, NULL) == ERROR_SUCCESS)
641 showIcons = false;
608 RegCloseKey(keyhandle); 642 RegCloseKey(keyhandle);
609 } 643 }
610 644
611 // Retrieve all the vim instances, unless disabled. 645 // Retrieve all the vim instances, unless disabled.
612 if (showExisting) 646 if (showExisting)
613 EnumWindows(EnumWindowsProc, (LPARAM)this); 647 EnumWindows(EnumWindowsProc, (LPARAM)this);
614 648
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
615 if (cbFiles > 1) 657 if (cbFiles > 1)
616 { 658 {
617 InsertMenu(hMenu, 659 mii.wID = idCmd++;
618 indexMenu++, 660 mii.dwTypeData = _("Edit with &multiple Vims");
619 MF_STRING|MF_BYPOSITION, 661 mii.cch = lstrlen(mii.dwTypeData);
620 idCmd++, 662 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
621 _("Edit with &multiple Vims")); 663
622 664 mii.wID = idCmd++;
623 InsertMenu(hMenu, 665 mii.dwTypeData = _("Edit with single &Vim");
624 indexMenu++, 666 mii.cch = lstrlen(mii.dwTypeData);
625 MF_STRING|MF_BYPOSITION, 667 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
626 idCmd++,
627 _("Edit with single &Vim"));
628 668
629 if (cbFiles <= 4) 669 if (cbFiles <= 4)
630 { 670 {
631 // Can edit up to 4 files in diff mode 671 // Can edit up to 4 files in diff mode
632 InsertMenu(hMenu, 672 mii.wID = idCmd++;
633 indexMenu++, 673 mii.dwTypeData = _("Diff with Vim");
634 MF_STRING|MF_BYPOSITION, 674 mii.cch = lstrlen(mii.dwTypeData);
635 idCmd++, 675 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
636 _("Diff with Vim"));
637 m_edit_existing_off = 3; 676 m_edit_existing_off = 3;
638 } 677 }
639 else 678 else
640 m_edit_existing_off = 2; 679 m_edit_existing_off = 2;
641 680
642 } 681 }
643 else 682 else
644 { 683 {
645 InsertMenu(hMenu, 684 mii.wID = idCmd++;
646 indexMenu++, 685 mii.dwTypeData = _("Edit with &Vim");
647 MF_STRING|MF_BYPOSITION, 686 mii.cch = lstrlen(mii.dwTypeData);
648 idCmd++, 687 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
649 _("Edit with &Vim"));
650 m_edit_existing_off = 1; 688 m_edit_existing_off = 1;
651 } 689 }
652 690
653 // Now display all the vim instances 691 // Now display all the vim instances
654 for (int i = 0; i < m_cntOfHWnd; i++) 692 for (int i = 0; i < m_cntOfHWnd; i++)
670 // Now concatenate 708 // Now concatenate
671 strncpy(temp, _("Edit with existing Vim - "), BUFSIZE - 1); 709 strncpy(temp, _("Edit with existing Vim - "), BUFSIZE - 1);
672 temp[BUFSIZE - 1] = '\0'; 710 temp[BUFSIZE - 1] = '\0';
673 strncat(temp, title, BUFSIZE - 1 - strlen(temp)); 711 strncat(temp, title, BUFSIZE - 1 - strlen(temp));
674 temp[BUFSIZE - 1] = '\0'; 712 temp[BUFSIZE - 1] = '\0';
675 InsertMenu(hMenu, 713
676 indexMenu++, 714 mii.wID = idCmd++;
677 MF_STRING|MF_BYPOSITION, 715 mii.dwTypeData = temp;
678 idCmd++, 716 mii.cch = lstrlen(mii.dwTypeData);
679 temp); 717 InsertMenuItem(hMenu, indexMenu++, TRUE, &mii);
680 } 718 }
681 // InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL); 719 // InsertMenu(hMenu, indexMenu++, MF_SEPARATOR|MF_BYPOSITION, 0, NULL);
682 720
683 // Must return number of menu items we added. 721 // Must return number of menu items we added.
684 return ResultFromShort(idCmd-idCmdFirst); 722 return ResultFromShort(idCmd-idCmdFirst);
811 cs->m_cntOfHWnd ++; 849 cs->m_cntOfHWnd ++;
812 850
813 return TRUE; // continue enumeration (otherwise this would be false) 851 return TRUE; // continue enumeration (otherwise this would be false)
814 } 852 }
815 853
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
816 #ifdef WIN32 870 #ifdef WIN32
817 // This symbol is not defined in older versions of the SDK or Visual C++. 871 // This symbol is not defined in older versions of the SDK or Visual C++.
818 872
819 #ifndef VER_PLATFORM_WIN32_WINDOWS 873 #ifndef VER_PLATFORM_WIN32_WINDOWS
820 # define VER_PLATFORM_WIN32_WINDOWS 1 874 # define VER_PLATFORM_WIN32_WINDOWS 1
891 DragQueryFileW((HDROP)medium.hGlobal, 945 DragQueryFileW((HDROP)medium.hGlobal,
892 i, 946 i,
893 m_szFileUserClickedOn, 947 m_szFileUserClickedOn,
894 sizeof(m_szFileUserClickedOn)); 948 sizeof(m_szFileUserClickedOn));
895 949
896 getGvimNameW(cmdStrW); 950 getGvimInvocationW(cmdStrW);
897 wcscat(cmdStrW, L" \""); 951 wcscat(cmdStrW, L" \"");
898 952
899 if ((wcslen(cmdStrW) + wcslen(m_szFileUserClickedOn) + 2) < BUFSIZE) 953 if ((wcslen(cmdStrW) + wcslen(m_szFileUserClickedOn) + 2) < BUFSIZE)
900 { 954 {
901 wcscat(cmdStrW, m_szFileUserClickedOn); 955 wcscat(cmdStrW, m_szFileUserClickedOn);
959 size_t len; 1013 size_t len;
960 UINT i; 1014 UINT i;
961 1015
962 cmdlen = BUFSIZE; 1016 cmdlen = BUFSIZE;
963 cmdStrW = (wchar_t *) malloc(cmdlen * sizeof(wchar_t)); 1017 cmdStrW = (wchar_t *) malloc(cmdlen * sizeof(wchar_t));
964 getGvimNameW(cmdStrW); 1018 getGvimInvocationW(cmdStrW);
965 1019
966 if (useDiff) 1020 if (useDiff)
967 wcscat(cmdStrW, L" -d"); 1021 wcscat(cmdStrW, L" -d");
968 for (i = 0; i < cbFiles; i++) 1022 for (i = 0; i < cbFiles; i++)
969 { 1023 {