Fixed issue #2507: Support keyboard shortcuts in yes/no prompts
[TortoiseGit.git] / src / Utils / TaskbarUUID.cpp
blobb5364ce0e8958436d47aecb67fd942f07032ecf7
1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013-2014 - TortoiseGit
4 // Copyright (C) 2011-2012 - TortoiseSVN
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software Foundation,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #pragma once
21 #include "stdafx.h"
22 #include "TaskbarUUID.h"
23 #include "registry.h"
24 #include "CmdLineParser.h"
26 #include <Shobjidl.h>
27 #include "SmartHandle.h"
28 #include <atlbase.h>
29 #include <GdiPlus.h>
31 #define APPID (_T("TGIT.TGIT.1"))
33 void SetTaskIDPerUUID()
35 typedef HRESULT STDAPICALLTYPE SetCurrentProcessExplicitAppUserModelIDFN(PCWSTR AppID);
36 CAutoLibrary hShell = AtlLoadSystemLibraryUsingFullPath(_T("shell32.dll"));
37 if (hShell)
39 SetCurrentProcessExplicitAppUserModelIDFN *pfnSetCurrentProcessExplicitAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDFN*)GetProcAddress(hShell, "SetCurrentProcessExplicitAppUserModelID");
40 if (pfnSetCurrentProcessExplicitAppUserModelID)
42 std::wstring id = GetTaskIDPerUUID();
43 pfnSetCurrentProcessExplicitAppUserModelID(id.c_str());
48 std::wstring GetTaskIDPerUUID(LPCTSTR uuid /*= NULL */)
50 CRegStdDWORD r = CRegStdDWORD(_T("Software\\TortoiseGit\\GroupTaskbarIconsPerRepo"), 3);
51 std::wstring id = APPID;
52 if ((r < 2)||(r == 3))
54 wchar_t buf[MAX_PATH] = {0};
55 GetModuleFileName(NULL, buf, MAX_PATH);
56 std::wstring n = buf;
57 n = n.substr(n.find_last_of('\\'));
58 id += n;
61 if (r >= 3)
63 if (uuid)
65 id += uuid;
67 else
69 CCmdLineParser parser(GetCommandLine());
70 if (parser.HasVal(L"groupuuid"))
72 id += parser.GetVal(L"groupuuid");
76 return id;
79 #ifdef _MFC_VER
80 extern CString g_sGroupingUUID;
81 extern CString g_sGroupingIcon;
82 extern bool g_bGroupingRemoveIcon;
83 #endif
85 void SetUUIDOverlayIcon( HWND hWnd )
87 if (CRegStdDWORD(_T("Software\\TortoiseGit\\GroupTaskbarIconsPerRepo"), 3))
89 if (CRegStdDWORD(_T("Software\\TortoiseGit\\GroupTaskbarIconsPerRepoOverlay"), TRUE))
91 std::wstring uuid;
92 std::wstring sicon;
93 bool bRemoveicon = false;
94 #ifdef _MFC_VER
95 uuid = g_sGroupingUUID;
96 sicon = g_sGroupingIcon;
97 bRemoveicon = g_bGroupingRemoveIcon;
98 #else
99 CCmdLineParser parser(GetCommandLine());
100 if (parser.HasVal(L"groupuuid"))
101 uuid = parser.GetVal(L"groupuuid");
102 #endif
103 if (!uuid.empty())
105 ITaskbarList3 * pTaskbarInterface = NULL;
106 HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, reinterpret_cast<void**> (&(pTaskbarInterface)));
108 if (SUCCEEDED(hr))
110 int foundUUIDIndex = 0;
113 wchar_t buf[MAX_PATH] = {0};
114 swprintf_s(buf, _countof(buf), L"%s%d", L"Software\\TortoiseGit\\LastUsedUUIDsForGrouping\\", foundUUIDIndex);
115 CRegStdString r = CRegStdString(buf);
116 std::wstring sr = r;
117 if (sr.empty())
119 r = uuid + (sicon.empty() ? L"" : (L";" + sicon));
120 break;
122 size_t sep = sr.find(L';');
123 std::wstring olduuid = sep != std::wstring::npos ? sr.substr(0, sep) : sr;
124 if (olduuid.compare(uuid) == 0)
126 if (bRemoveicon)
127 r = uuid; // reset icon path in registry
128 else if (!sicon.empty())
129 r = uuid + (sicon.empty() ? L"" : (L";" + sicon));
130 else
131 sicon = sep != std::wstring::npos ? sr.substr(sep + 1) : L"";
132 break;
134 foundUUIDIndex++;
135 } while (foundUUIDIndex < 20);
136 if (foundUUIDIndex >= 20)
138 CRegStdString r = CRegStdString(L"Software\\TortoiseGit\\LastUsedUUIDsForGrouping\\1");
139 r.removeKey();
142 HICON icon = nullptr;
143 if (!sicon.empty())
145 if (sicon.size() >=4 && !_wcsicmp(sicon.substr(sicon.size() - 4).c_str(), L".ico"))
147 icon = (HICON)::LoadImage(NULL, sicon.c_str(), IMAGE_ICON, 16, 16, LR_LOADFROMFILE | LR_SHARED);
149 else
151 ULONG_PTR gdiplusToken = 0;
152 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
153 GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, nullptr);
154 if (gdiplusToken)
156 Gdiplus::Bitmap *pBitmap = new Gdiplus::Bitmap(sicon.c_str(), FALSE);
157 if (pBitmap->GetLastStatus() == Gdiplus::Status::Ok)
158 pBitmap->GetHICON(&icon);
159 delete pBitmap;
160 Gdiplus::GdiplusShutdown(gdiplusToken);
165 if (!icon)
167 DWORD colors[6] = {0x80FF0000, 0x80FFFF00, 0x8000FF00, 0x800000FF, 0x80000000, 0x8000FFFF};
169 // AND mask - monochrome - determines which pixels get drawn
170 BYTE AND[32];
171 for( int i=0; i<32; i++ )
173 AND[i] = 0xFF;
176 // XOR mask - 32bpp ARGB - determines the pixel values
177 DWORD XOR[256];
178 for( int i=0; i<256; i++ )
180 XOR[i] = colors[foundUUIDIndex % 6];
183 icon = ::CreateIcon(NULL,16,16,1,32,AND,(BYTE*)XOR);
185 pTaskbarInterface->SetOverlayIcon(hWnd, icon, uuid.c_str());
186 pTaskbarInterface->Release();
187 DestroyIcon(icon);