1
// TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (C) 2013-2014, 2016-2018 - TortoiseGit
4 // Copyright (C) 2011-2012, 2016 - 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.
22 #include "TaskbarUUID.h"
24 #include "CmdLineParser.h"
25 #include "LoadIconEx.h"
27 #include "SmartHandle.h"
30 #pragma warning(disable: 4458)
33 #pragma comment(lib, "gdiplus.lib")
35 #define APPID (L"TGIT.TGIT.1")
37 void SetTaskIDPerUUID()
39 typedef HRESULT STDAPICALLTYPE
SetCurrentProcessExplicitAppUserModelIDFN(PCWSTR AppID
);
40 CAutoLibrary hShell
= AtlLoadSystemLibraryUsingFullPath(L
"shell32.dll");
43 SetCurrentProcessExplicitAppUserModelIDFN
*pfnSetCurrentProcessExplicitAppUserModelID
= (SetCurrentProcessExplicitAppUserModelIDFN
*)GetProcAddress(hShell
, "SetCurrentProcessExplicitAppUserModelID");
44 if (pfnSetCurrentProcessExplicitAppUserModelID
)
46 std::wstring id
= GetTaskIDPerUUID();
47 pfnSetCurrentProcessExplicitAppUserModelID(id
.c_str());
52 std::wstring
GetTaskIDPerUUID(LPCTSTR uuid
/*= nullptr */)
54 CRegStdDWORD r
= CRegStdDWORD(L
"Software\\TortoiseGit\\GroupTaskbarIconsPerRepo", 3);
55 std::wstring id
= APPID
;
56 if ((r
< 2)||(r
== 3))
58 wchar_t buf
[MAX_PATH
] = {0};
59 GetModuleFileName(nullptr, buf
, _countof(buf
));
61 n
= n
.substr(n
.find_last_of('\\'));
73 CCmdLineParser
parser(GetCommandLine());
74 if (parser
.HasVal(L
"groupuuid"))
76 id
+= parser
.GetVal(L
"groupuuid");
84 extern CString g_sGroupingUUID
;
85 extern CString g_sGroupingIcon
;
86 extern bool g_bGroupingRemoveIcon
;
89 void SetUUIDOverlayIcon( HWND hWnd
)
91 if (!CRegStdDWORD(L
"Software\\TortoiseGit\\GroupTaskbarIconsPerRepo", 3))
94 if (!CRegStdDWORD(L
"Software\\TortoiseGit\\GroupTaskbarIconsPerRepoOverlay", TRUE
))
99 bool bRemoveicon
= false;
101 uuid
= g_sGroupingUUID
;
102 sicon
= g_sGroupingIcon
;
103 bRemoveicon
= g_bGroupingRemoveIcon
;
105 CCmdLineParser
parser(GetCommandLine());
106 if (parser
.HasVal(L
"groupuuid"))
107 uuid
= parser
.GetVal(L
"groupuuid");
112 CComPtr
<ITaskbarList3
> pTaskbarInterface
;
113 if (FAILED(pTaskbarInterface
.CoCreateInstance(CLSID_TaskbarList
, nullptr, CLSCTX_INPROC_SERVER
)))
116 int foundUUIDIndex
= 0;
119 wchar_t buf
[MAX_PATH
] = { 0 };
120 swprintf_s(buf
, L
"%s%d", L
"Software\\TortoiseGit\\LastUsedUUIDsForGrouping\\", foundUUIDIndex
);
121 CRegStdString r
= CRegStdString(buf
);
125 r
= uuid
+ (sicon
.empty() ? L
"" : (L
";" + sicon
));
128 size_t sep
= sr
.find(L
';');
129 std::wstring olduuid
= sep
!= std::wstring::npos
? sr
.substr(0, sep
) : sr
;
130 if (olduuid
.compare(uuid
) == 0)
133 r
= uuid
; // reset icon path in registry
134 else if (!sicon
.empty())
135 r
= uuid
+ (sicon
.empty() ? L
"" : (L
";" + sicon
));
137 sicon
= sep
!= std::wstring::npos
? sr
.substr(sep
+ 1) : L
"";
141 } while (foundUUIDIndex
< 20);
142 if (foundUUIDIndex
>= 20)
144 CRegStdString r
= CRegStdString(L
"Software\\TortoiseGit\\LastUsedUUIDsForGrouping\\1");
148 int iconWidth
= GetSystemMetrics(SM_CXSMICON
);
149 int iconHeight
= GetSystemMetrics(SM_CYSMICON
);
151 HICON icon
= nullptr;
154 if (sicon
.size() >= 4 && !_wcsicmp(sicon
.substr(sicon
.size() - 4).c_str(), L
".ico"))
155 icon
= LoadIconEx(nullptr, sicon
.c_str(), iconWidth
, iconHeight
);
158 ULONG_PTR gdiplusToken
= 0;
159 Gdiplus::GdiplusStartupInput gdiplusStartupInput
;
160 GdiplusStartup(&gdiplusToken
, &gdiplusStartupInput
, nullptr);
164 auto pBitmap
= std::make_unique
<Gdiplus::Bitmap
>(sicon
.c_str(), FALSE
);
165 if (pBitmap
->GetLastStatus() == Gdiplus::Status::Ok
)
166 pBitmap
->GetHICON(&icon
);
168 Gdiplus::GdiplusShutdown(gdiplusToken
);
175 DWORD colors
[6] = { 0x80FF0000, 0x80FFFF00, 0x8000FF00, 0x800000FF, 0x80000000, 0x8000FFFF };
177 // AND mask - monochrome - determines which pixels get drawn
178 auto AND
= std::make_unique
<BYTE
[]>(iconWidth
* iconWidth
);
179 for (int i
= 0; i
< iconWidth
* iconWidth
; ++i
)
182 // XOR mask - 32bpp ARGB - determines the pixel values
183 auto XOR
= std::make_unique
<DWORD
[]>(iconWidth
* iconWidth
);
184 for (int i
= 0; i
< iconWidth
* iconWidth
; ++i
)
185 XOR
[i
] = colors
[foundUUIDIndex
% 6];
187 icon
= ::CreateIcon(nullptr, iconWidth
, iconHeight
, 1, 32, AND
.get(), (BYTE
*)XOR
.get());
189 pTaskbarInterface
->SetOverlayIcon(hWnd
, icon
, uuid
.c_str());