1 ///////////////////////////////////////////////////////////////////////////////
2 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2014 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>
41 ///////////////////////////////////////////////////////////////////////////////
43 ///////////////////////////////////////////////////////////////////////////////
45 static QReadWriteLock g_themes_lock
;
46 static bool g_themes_initialized
= false;
47 static bool g_themes_enabled
= false;
49 typedef int (WINAPI IsAppThemedFunction
)(void);
51 bool MUtils::GUI::themes_enabled(void)
53 QReadLocker
readLock(&g_themes_lock
);
55 if(g_themes_initialized
)
57 return g_themes_enabled
;
61 QWriteLocker
writeLock(&g_themes_lock
);
63 if(g_themes_initialized
)
65 return g_themes_enabled
;
68 const MUtils::OS::Version::os_version_t
&osVersion
= MUtils::OS::os_version();
69 if(osVersion
>= MUtils::OS::Version::WINDOWS_WINXP
)
71 QLibrary
uxTheme("UxTheme.dll");
74 if(IsAppThemedFunction
*const IsAppThemedPtr
= (IsAppThemedFunction
*) uxTheme
.resolve("IsAppThemed"))
76 g_themes_enabled
= IsAppThemedPtr();
79 qWarning("Theme support is disabled for this process!");
85 g_themes_initialized
= true;
86 return g_themes_enabled
;
89 ///////////////////////////////////////////////////////////////////////////////
91 ///////////////////////////////////////////////////////////////////////////////
93 bool MUtils::GUI::sysmenu_append(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
97 if(HMENU hMenu
= GetSystemMenu(win
->winId(), FALSE
))
99 ok
= (AppendMenuW(hMenu
, MF_SEPARATOR
, 0, 0) == TRUE
);
100 ok
= (AppendMenuW(hMenu
, MF_STRING
, identifier
, MUTILS_WCHR(text
)) == TRUE
);
106 bool MUtils::GUI::sysmenu_update(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
110 if(HMENU hMenu
= ::GetSystemMenu(win
->winId(), FALSE
))
112 ok
= (ModifyMenu(hMenu
, identifier
, MF_STRING
| MF_BYCOMMAND
, identifier
, MUTILS_WCHR(text
)) == TRUE
);
117 bool MUtils::GUI::sysmenu_check_msg(void *const message
, const unsigned int &identifier
)
119 return (((MSG
*)message
)->message
== WM_SYSCOMMAND
) && ((((MSG
*)message
)->wParam
& 0xFFF0) == identifier
);
122 ///////////////////////////////////////////////////////////////////////////////
124 ///////////////////////////////////////////////////////////////////////////////
126 bool MUtils::GUI::enable_close_button(const QWidget
*win
, const bool &bEnable
)
130 if(HMENU hMenu
= GetSystemMenu(win
->winId(), FALSE
))
132 ok
= (EnableMenuItem(hMenu
, SC_CLOSE
, MF_BYCOMMAND
| (bEnable
? MF_ENABLED
: MF_GRAYED
)) == TRUE
);
138 ///////////////////////////////////////////////////////////////////////////////
139 // BRING WINDOW TO FRONT
140 ///////////////////////////////////////////////////////////////////////////////
142 static BOOL CALLBACK
bring_process_to_front_helper(HWND hwnd
, LPARAM lParam
)
144 DWORD processId
= *reinterpret_cast<WORD
*>(lParam
);
145 DWORD windowProcessId
= NULL
;
146 GetWindowThreadProcessId(hwnd
, &windowProcessId
);
147 if(windowProcessId
== processId
)
149 SwitchToThisWindow(hwnd
, TRUE
);
150 SetForegroundWindow(hwnd
);
157 bool MUtils::GUI::bring_to_front(const QWidget
*window
)
163 for(int i
= 0; (i
< 5) && (!ret
); i
++)
165 ret
= (SetForegroundWindow(window
->winId()) != FALSE
);
166 SwitchToThisWindow(window
->winId(), TRUE
);
168 LockSetForegroundWindow(LSFW_LOCK
);
174 bool MUtils::GUI::bring_to_front(const unsigned long pid
)
176 return EnumWindows(bring_process_to_front_helper
, reinterpret_cast<LPARAM
>(&pid
)) == TRUE
;
179 ///////////////////////////////////////////////////////////////////////////////
180 // SHEET OF GLASS EFFECT
181 ///////////////////////////////////////////////////////////////////////////////
183 static QReadWriteLock g_dwmapi_lock
;
184 static QScopedPointer
<QLibrary
> g_dwmapi_library
;
185 static bool g_dwmapi_initialized
= false;
189 HRESULT (__stdcall
*dwmIsCompositionEnabled
)(BOOL
*bEnabled
);
190 HRESULT (__stdcall
*dwmExtendFrameIntoClientArea
)(HWND hWnd
, const MARGINS
* pMarInset
);
191 HRESULT (__stdcall
*dwmEnableBlurBehindWindow
)(HWND hWnd
, const DWM_BLURBEHIND
* pBlurBehind
);
193 g_dwmapi_pointers
= { NULL
, NULL
, NULL
};
195 static void initialize_dwmapi(void)
197 QReadLocker
writeLock(&g_dwmapi_lock
);
199 //Not initialized yet?
200 if(g_dwmapi_initialized
)
205 //Reset function pointers
206 g_dwmapi_pointers
.dwmIsCompositionEnabled
= NULL
;
207 g_dwmapi_pointers
.dwmExtendFrameIntoClientArea
= NULL
;
208 g_dwmapi_pointers
.dwmEnableBlurBehindWindow
= NULL
;
210 //Does OS support DWM?
211 const MUtils::OS::Version::os_version_t
&osVersion
= MUtils::OS::os_version();
212 if(osVersion
>= MUtils::OS::Version::WINDOWS_VISTA
)
215 g_dwmapi_library
.reset(new QLibrary("dwmapi.dll"));
216 if(g_dwmapi_library
->load())
218 //Initialize function pointers
219 g_dwmapi_pointers
.dwmIsCompositionEnabled
= (HRESULT (__stdcall
*)(BOOL
*)) g_dwmapi_library
->resolve("DwmIsCompositionEnabled");
220 g_dwmapi_pointers
.dwmExtendFrameIntoClientArea
= (HRESULT (__stdcall
*)(HWND
, const MARGINS
*)) g_dwmapi_library
->resolve("DwmExtendFrameIntoClientArea");
221 g_dwmapi_pointers
.dwmEnableBlurBehindWindow
= (HRESULT (__stdcall
*)(HWND
, const DWM_BLURBEHIND
*)) g_dwmapi_library
->resolve("DwmEnableBlurBehindWindow");
225 g_dwmapi_library
.reset(NULL
);
226 qWarning("Failed to load DWMAPI.DLL on a DWM-enabled system!");
230 g_dwmapi_initialized
= true;
233 bool MUtils::GUI::sheet_of_glass(QWidget
*const window
)
235 QReadLocker
readLock(&g_dwmapi_lock
);
237 //Initialize the DWM API
238 if(!g_dwmapi_initialized
)
245 //Required functions available?
246 BOOL bCompositionEnabled
= FALSE
;
247 if(g_dwmapi_pointers
.dwmIsCompositionEnabled
&& g_dwmapi_pointers
.dwmExtendFrameIntoClientArea
&& g_dwmapi_pointers
.dwmEnableBlurBehindWindow
)
249 //Check if composition is currently enabled
250 if(HRESULT hr
= g_dwmapi_pointers
.dwmIsCompositionEnabled(&bCompositionEnabled
))
252 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
257 //All functions available *and* composition enabled?
258 if(!bCompositionEnabled
)
263 //Enable the "sheet of glass" effect on this window
264 MARGINS margins
= {-1, -1, -1, -1};
265 if(HRESULT hr
= g_dwmapi_pointers
.dwmExtendFrameIntoClientArea(window
->winId(), &margins
))
267 qWarning("DwmExtendFrameIntoClientArea function has failed! (error %d)", hr
);
271 //Create and populate the Blur Behind structure
273 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
275 bb
.dwFlags
= DWM_BB_ENABLE
;
276 if(HRESULT hr
= g_dwmapi_pointers
.dwmEnableBlurBehindWindow(window
->winId(), &bb
))
278 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
283 window
->setAutoFillBackground(false);
284 window
->setAttribute(Qt::WA_TranslucentBackground
);
285 window
->setAttribute(Qt::WA_NoSystemBackground
);
290 bool MUtils::GUI::sheet_of_glass_update(QWidget
*const window
)
292 QReadLocker
readLock(&g_dwmapi_lock
);
294 //Initialize the DWM API
295 if(!g_dwmapi_initialized
)
302 //Required functions available?
303 BOOL bCompositionEnabled
= FALSE
;
304 if(g_dwmapi_pointers
.dwmIsCompositionEnabled
&& g_dwmapi_pointers
.dwmExtendFrameIntoClientArea
&& g_dwmapi_pointers
.dwmEnableBlurBehindWindow
)
306 //Check if composition is currently enabled
307 if(HRESULT hr
= g_dwmapi_pointers
.dwmIsCompositionEnabled(&bCompositionEnabled
))
309 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
314 //All functions available *and* composition enabled?
315 if(!bCompositionEnabled
)
320 //Create and populate the Blur Behind structure
322 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
324 bb
.dwFlags
= DWM_BB_ENABLE
;
325 if(HRESULT hr
= g_dwmapi_pointers
.dwmEnableBlurBehindWindow(window
->winId(), &bb
))
327 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
334 ///////////////////////////////////////////////////////////////////////////////
336 ///////////////////////////////////////////////////////////////////////////////
338 QColor
MUtils::GUI::system_color(const int &color_id
)
345 nIndex
= COLOR_WINDOWTEXT
; /*Text in windows*/
347 case SYSCOLOR_BACKGROUND
:
348 nIndex
= COLOR_WINDOW
; /*Window background*/
350 case SYSCOLOR_CAPTION
:
351 nIndex
= COLOR_CAPTIONTEXT
; /*Text in caption, size box, and scroll bar arrow box*/
354 qWarning("Unknown system color id (%d) specified!", color_id
);
355 nIndex
= COLOR_WINDOWTEXT
;
358 const DWORD rgb
= GetSysColor(nIndex
);
359 QColor
color(GetRValue(rgb
), GetGValue(rgb
), GetBValue(rgb
));