1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2019 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
20 //////////////////////////////////////////////////////////////////////////////////
23 #define WIN32_LEAN_AND_MEAN 1
27 #include <MUtils/GUI.h>
28 #include <MUtils/OSSupport.h>
31 #include "Utils_Win32.h"
35 #include <QApplication>
37 #include <QReadWriteLock>
40 ///////////////////////////////////////////////////////////////////////////////
42 ///////////////////////////////////////////////////////////////////////////////
44 static QReadWriteLock g_themes_lock
;
45 static int g_themes_initialized
= 0;
47 typedef int (WINAPI
*IsAppThemedFunction
)(void);
49 bool MUtils::GUI::themes_enabled(void)
51 QReadLocker
readLock(&g_themes_lock
);
53 if(g_themes_initialized
!= 0)
55 return (g_themes_initialized
> 0);
59 QWriteLocker
writeLock(&g_themes_lock
);
61 if(g_themes_initialized
!= 0)
63 return (g_themes_initialized
> 0);
66 const MUtils::OS::Version::os_version_t
&osVersion
= MUtils::OS::os_version();
67 if(osVersion
>= MUtils::OS::Version::WINDOWS_WINXP
)
69 const IsAppThemedFunction isAppThemedPtr
= MUtils::Win32Utils::resolve
<IsAppThemedFunction
>(QLatin1String("UxTheme"), QLatin1String("IsAppThemed"));
72 g_themes_initialized
= isAppThemedPtr() ? 1 : (-1);
73 if(g_themes_initialized
< 0)
75 qWarning("Theme support is disabled for this process!");
80 return (g_themes_initialized
> 0);
83 ///////////////////////////////////////////////////////////////////////////////
85 ///////////////////////////////////////////////////////////////////////////////
87 bool MUtils::GUI::sysmenu_append(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
91 if(HMENU hMenu
= GetSystemMenu(reinterpret_cast<HWND
>(win
->winId()), FALSE
))
93 ok
= (AppendMenuW(hMenu
, MF_SEPARATOR
, 0, 0) == TRUE
);
94 ok
= (AppendMenuW(hMenu
, MF_STRING
, identifier
, MUTILS_WCHR(text
)) == TRUE
);
100 bool MUtils::GUI::sysmenu_update(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
104 if(HMENU hMenu
= ::GetSystemMenu(reinterpret_cast<HWND
>(win
->winId()), FALSE
))
106 ok
= (ModifyMenu(hMenu
, identifier
, MF_STRING
| MF_BYCOMMAND
, identifier
, MUTILS_WCHR(text
)) == TRUE
);
111 bool MUtils::GUI::sysmenu_check_msg(void *const message
, const unsigned int &identifier
)
113 return (((MSG
*)message
)->message
== WM_SYSCOMMAND
) && ((((MSG
*)message
)->wParam
& 0xFFF0) == identifier
);
116 ///////////////////////////////////////////////////////////////////////////////
118 ///////////////////////////////////////////////////////////////////////////////
120 bool MUtils::GUI::enable_close_button(const QWidget
*win
, const bool &bEnable
)
124 if(HMENU hMenu
= GetSystemMenu(reinterpret_cast<HWND
>(win
->winId()), FALSE
))
126 ok
= (EnableMenuItem(hMenu
, SC_CLOSE
, MF_BYCOMMAND
| (bEnable
? MF_ENABLED
: MF_GRAYED
)) == TRUE
);
132 ///////////////////////////////////////////////////////////////////////////////
133 // BRING WINDOW TO FRONT
134 ///////////////////////////////////////////////////////////////////////////////
136 static BOOL CALLBACK
bring_process_to_front_helper(HWND hwnd
, LPARAM lParam
)
138 DWORD processId
= *reinterpret_cast<WORD
*>(lParam
);
139 DWORD windowProcessId
= NULL
;
140 GetWindowThreadProcessId(hwnd
, &windowProcessId
);
141 if(windowProcessId
== processId
)
143 SwitchToThisWindow(hwnd
, TRUE
);
144 SetForegroundWindow(hwnd
);
151 bool MUtils::GUI::bring_to_front(const QWidget
*window
)
157 for(int i
= 0; (i
< 5) && (!ret
); i
++)
159 ret
= (SetForegroundWindow(reinterpret_cast<HWND
>(window
->winId())) != FALSE
);
160 SwitchToThisWindow(reinterpret_cast<HWND
>(window
->winId()), TRUE
);
162 LockSetForegroundWindow(LSFW_LOCK
);
168 bool MUtils::GUI::bring_to_front(const unsigned long pid
)
170 return EnumWindows(bring_process_to_front_helper
, reinterpret_cast<LPARAM
>(&pid
)) == TRUE
;
173 ///////////////////////////////////////////////////////////////////////////////
174 // SHEET OF GLASS EFFECT
175 ///////////////////////////////////////////////////////////////////////////////
177 typedef HRESULT (__stdcall
*DwmIsCompositionEnabledFun
) (BOOL
*bEnabled
);
178 typedef HRESULT (__stdcall
*DwmExtendFrameIntoClientAreaFun
) (HWND hWnd
, const MARGINS
* pMarInset
);
179 typedef HRESULT (__stdcall
*DwmEnableBlurBehindWindowFun
) (HWND hWnd
, const DWM_BLURBEHIND
* pBlurBehind
);
181 bool MUtils::GUI::sheet_of_glass(QWidget
*const window
)
183 const DwmIsCompositionEnabledFun dwmIsCompositionEnabledFun
= MUtils::Win32Utils::resolve
<DwmIsCompositionEnabledFun
> (QLatin1String("dwmapi"), QLatin1String("DwmIsCompositionEnabled") );
184 const DwmExtendFrameIntoClientAreaFun dwmExtendFrameIntoClientAreaFun
= MUtils::Win32Utils::resolve
<DwmExtendFrameIntoClientAreaFun
>(QLatin1String("dwmapi"), QLatin1String("DwmExtendFrameIntoClientArea"));
185 const DwmEnableBlurBehindWindowFun dwmEnableBlurBehindWindowFun
= MUtils::Win32Utils::resolve
<DwmEnableBlurBehindWindowFun
> (QLatin1String("dwmapi"), QLatin1String("DwmEnableBlurBehindWindow") );
187 //Required functions available?
188 BOOL bCompositionEnabled
= FALSE
;
189 if(dwmIsCompositionEnabledFun
&& dwmExtendFrameIntoClientAreaFun
&& dwmEnableBlurBehindWindowFun
)
191 //Check if composition is currently enabled
192 if(HRESULT hr
= dwmIsCompositionEnabledFun(&bCompositionEnabled
))
194 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
199 //All functions available *and* composition enabled?
200 if(!bCompositionEnabled
)
205 //Enable the "sheet of glass" effect on this window
206 MARGINS margins
= {-1, -1, -1, -1};
207 if(HRESULT hr
= dwmExtendFrameIntoClientAreaFun(reinterpret_cast<HWND
>(window
->winId()), &margins
))
209 qWarning("DwmExtendFrameIntoClientArea function has failed! (error %d)", hr
);
213 //Create and populate the Blur Behind structure
215 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
217 bb
.dwFlags
= DWM_BB_ENABLE
;
218 if(HRESULT hr
= dwmEnableBlurBehindWindowFun(reinterpret_cast<HWND
>(window
->winId()), &bb
))
220 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
225 window
->setAutoFillBackground(false);
226 window
->setAttribute(Qt::WA_TranslucentBackground
);
227 window
->setAttribute(Qt::WA_NoSystemBackground
);
232 bool MUtils::GUI::sheet_of_glass_update(QWidget
*const window
)
234 const DwmIsCompositionEnabledFun dwmIsCompositionEnabledFun
= MUtils::Win32Utils::resolve
<DwmIsCompositionEnabledFun
> (QLatin1String("dwmapi"), QLatin1String("DwmIsCompositionEnabled") );
235 const DwmExtendFrameIntoClientAreaFun dwmExtendFrameIntoClientAreaFun
= MUtils::Win32Utils::resolve
<DwmExtendFrameIntoClientAreaFun
>(QLatin1String("dwmapi"), QLatin1String("DwmExtendFrameIntoClientArea"));
236 const DwmEnableBlurBehindWindowFun dwmEnableBlurBehindWindowFun
= MUtils::Win32Utils::resolve
<DwmEnableBlurBehindWindowFun
> (QLatin1String("dwmapi"), QLatin1String("DwmEnableBlurBehindWindow") );
238 //Required functions available?
239 BOOL bCompositionEnabled
= FALSE
;
240 if(dwmIsCompositionEnabledFun
&& dwmExtendFrameIntoClientAreaFun
&& dwmEnableBlurBehindWindowFun
)
242 //Check if composition is currently enabled
243 if(HRESULT hr
= dwmIsCompositionEnabledFun(&bCompositionEnabled
))
245 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
250 //All functions available *and* composition enabled?
251 if(!bCompositionEnabled
)
256 //Create and populate the Blur Behind structure
258 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
260 bb
.dwFlags
= DWM_BB_ENABLE
;
261 if(HRESULT hr
= dwmEnableBlurBehindWindowFun(reinterpret_cast<HWND
>(window
->winId()), &bb
))
263 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
270 ///////////////////////////////////////////////////////////////////////////////
272 ///////////////////////////////////////////////////////////////////////////////
274 QColor
MUtils::GUI::system_color(const int &color_id
)
281 nIndex
= COLOR_WINDOWTEXT
; /*Text in windows*/
283 case SYSCOLOR_BACKGROUND
:
284 nIndex
= COLOR_WINDOW
; /*Window background*/
286 case SYSCOLOR_CAPTION
:
287 nIndex
= COLOR_CAPTIONTEXT
; /*Text in caption, size box, and scroll bar arrow box*/
290 qWarning("Unknown system color id (%d) specified!", color_id
);
291 nIndex
= COLOR_WINDOWTEXT
;
294 const DWORD rgb
= GetSysColor(nIndex
);
295 QColor
color(GetRValue(rgb
), GetGValue(rgb
), GetBValue(rgb
));