1 ///////////////////////////////////////////////////////////////////////////////
2 // LameXP - Audio Encoder Front-End
3 // Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2 of the License, or
8 // (at your option) any later version, but always including the *additional*
9 // restrictions defined in the "License.txt" file.
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 along
17 // with this program; if not, write to the Free Software Foundation, Inc.,
18 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 // http://www.gnu.org/licenses/gpl-2.0.txt
21 ///////////////////////////////////////////////////////////////////////////////
26 #include "Targetver.h"
28 //Visual Leaks Detector
33 #define WIN32_LEAN_AND_MEAN
44 #include <QApplication>
49 #include <QImageReader>
51 #include <QLibraryInfo>
53 #include <QMessageBox>
54 #include <QPlastiqueStyle>
56 #include <QReadWriteLock>
61 #include <QTranslator>
66 #define LAMEXP_INC_CONFIG
71 #include <MUtils/Global.h>
72 #include <MUtils/OSSupport.h>
73 #include <MUtils/Terminal.h>
87 //Initialize static Qt plugins
89 #if QT_VERSION < QT_VERSION_CHECK(5,0,0)
93 Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin
)
94 Q_IMPORT_PLUGIN(QICOPlugin
)
98 ///////////////////////////////////////////////////////////////////////////////
100 ///////////////////////////////////////////////////////////////////////////////
102 #define _LAMEXP_MAKE_STR(STR) #STR
103 #define LAMEXP_MAKE_STR(STR) _LAMEXP_MAKE_STR(STR)
105 ///////////////////////////////////////////////////////////////////////////////
107 ///////////////////////////////////////////////////////////////////////////////
118 //Win32 Theme support
125 g_lamexp_themes_enabled
;
127 //Win32 DWM API functions
131 HRESULT (__stdcall
*dwmIsCompositionEnabled
)(BOOL
*bEnabled
);
132 HRESULT (__stdcall
*dwmExtendFrameIntoClientArea
)(HWND hWnd
, const MARGINS
* pMarInset
);
133 HRESULT (__stdcall
*dwmEnableBlurBehindWindow
)(HWND hWnd
, const DWM_BLURBEHIND
* pBlurBehind
);
134 QLibrary
*dwmapi_dll
;
142 QHash
<const QString
, const unsigned char*> *sound_db
;
148 static const DWORD g_main_thread_id
= GetCurrentThreadId();
151 const char* LAMEXP_DEFAULT_LANGID
= "en";
152 const char* LAMEXP_DEFAULT_TRANSLATION
= "LameXP_EN.qm";
154 ///////////////////////////////////////////////////////////////////////////////
156 ///////////////////////////////////////////////////////////////////////////////
159 * Check if visual themes are enabled (WinXP and later)
161 bool lamexp_themes_enabled(void)
163 typedef int (WINAPI
*IsAppThemedFun
)(void);
165 QReadLocker
readLock(&g_lamexp_themes_enabled
.lock
);
166 if(g_lamexp_themes_enabled
.bInitialized
)
168 return g_lamexp_themes_enabled
.bThemesEnabled
;
172 QWriteLocker
writeLock(&g_lamexp_themes_enabled
.lock
);
174 if(!g_lamexp_themes_enabled
.bInitialized
)
176 g_lamexp_themes_enabled
.bThemesEnabled
= false;
177 const MUtils::OS::Version::os_version_t
&osVersion
= MUtils::OS::os_version();
178 if(osVersion
>= MUtils::OS::Version::WINDOWS_WINXP
)
180 IsAppThemedFun IsAppThemedPtr
= NULL
;
181 QLibrary
uxTheme(QString("%1/UxTheme.dll").arg(MUtils::OS::known_folder(MUtils::OS::FOLDER_SYSTEMFOLDER
)));
184 IsAppThemedPtr
= (IsAppThemedFun
) uxTheme
.resolve("IsAppThemed");
188 g_lamexp_themes_enabled
.bThemesEnabled
= IsAppThemedPtr();
189 if(!g_lamexp_themes_enabled
.bThemesEnabled
)
191 qWarning("Theme support is disabled for this process!");
195 g_lamexp_themes_enabled
.bInitialized
= true;
198 return g_lamexp_themes_enabled
.bThemesEnabled
;
202 * Insert entry to the window's system menu
204 bool lamexp_append_sysmenu(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
208 if(HMENU hMenu
= GetSystemMenu(win
->winId(), FALSE
))
210 ok
= (AppendMenuW(hMenu
, MF_SEPARATOR
, 0, 0) == TRUE
);
211 ok
= (AppendMenuW(hMenu
, MF_STRING
, identifier
, MUTILS_WCHR(text
)) == TRUE
);
218 * Insert entry to the window's system menu
220 bool lamexp_check_sysmenu_msg(void *message
, const unsigned int identifier
)
222 return (((MSG
*)message
)->message
== WM_SYSCOMMAND
) && ((((MSG
*)message
)->wParam
& 0xFFF0) == identifier
);
226 * Update system menu entry
228 bool lamexp_update_sysmenu(const QWidget
*win
, const unsigned int identifier
, const QString
&text
)
232 if(HMENU hMenu
= ::GetSystemMenu(win
->winId(), FALSE
))
234 ok
= (ModifyMenu(hMenu
, identifier
, MF_STRING
| MF_BYCOMMAND
, identifier
, MUTILS_WCHR(text
)) == TRUE
);
240 * Display the window's close button
242 bool lamexp_enable_close_button(const QWidget
*win
, const bool bEnable
)
246 if(HMENU hMenu
= GetSystemMenu(win
->winId(), FALSE
))
248 ok
= (EnableMenuItem(hMenu
, SC_CLOSE
, MF_BYCOMMAND
| (bEnable
? MF_ENABLED
: MF_GRAYED
)) == TRUE
);
255 * Check whether ESC key has been pressed since the previous call to this function
257 bool lamexp_check_escape_state(void)
259 return (GetAsyncKeyState(VK_ESCAPE
) & 0x0001) != 0;
263 * Bring the specifed window to the front
265 bool lamexp_bring_to_front(const QWidget
*window
)
271 for(int i
= 0; (i
< 5) && (!ret
); i
++)
273 ret
= (SetForegroundWindow(window
->winId()) != FALSE
);
274 SwitchToThisWindow(window
->winId(), TRUE
);
276 LockSetForegroundWindow(LSFW_LOCK
);
283 * Bring window of the specifed process to the front (callback)
285 static BOOL CALLBACK
lamexp_bring_process_to_front_helper(HWND hwnd
, LPARAM lParam
)
287 DWORD processId
= *reinterpret_cast<WORD
*>(lParam
);
288 DWORD windowProcessId
= NULL
;
289 GetWindowThreadProcessId(hwnd
, &windowProcessId
);
290 if(windowProcessId
== processId
)
292 SwitchToThisWindow(hwnd
, TRUE
);
293 SetForegroundWindow(hwnd
);
301 * Bring window of the specifed process to the front
303 bool lamexp_bring_process_to_front(const unsigned long pid
)
305 return EnumWindows(lamexp_bring_process_to_front_helper
, reinterpret_cast<LPARAM
>(&pid
)) == TRUE
;
308 static void lamexp_init_dwmapi(void)
310 QReadLocker
writeLock(&g_lamexp_dwmapi
.lock
);
312 //Not initialized yet?
313 if(g_lamexp_dwmapi
.bInitialized
)
318 //Reset function pointers
319 g_lamexp_dwmapi
.dwmIsCompositionEnabled
= NULL
;
320 g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
= NULL
;
321 g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
= NULL
;
323 //Does OS support DWM?
324 const MUtils::OS::Version::os_version_t
&osVersion
= MUtils::OS::os_version();
325 if(osVersion
>= MUtils::OS::Version::WINDOWS_VISTA
)
328 g_lamexp_dwmapi
.dwmapi_dll
= new QLibrary("dwmapi.dll");
329 if(g_lamexp_dwmapi
.dwmapi_dll
->load())
331 //Initialize function pointers
332 g_lamexp_dwmapi
.dwmIsCompositionEnabled
= (HRESULT (__stdcall
*)(BOOL
*)) g_lamexp_dwmapi
.dwmapi_dll
->resolve("DwmIsCompositionEnabled");
333 g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
= (HRESULT (__stdcall
*)(HWND
, const MARGINS
*)) g_lamexp_dwmapi
.dwmapi_dll
->resolve("DwmExtendFrameIntoClientArea");
334 g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
= (HRESULT (__stdcall
*)(HWND
, const DWM_BLURBEHIND
*)) g_lamexp_dwmapi
.dwmapi_dll
->resolve("DwmEnableBlurBehindWindow");
338 MUTILS_DELETE(g_lamexp_dwmapi
.dwmapi_dll
);
339 qWarning("Failed to load DWMAPI.DLL on a DWM-enabled system!");
343 g_lamexp_dwmapi
.bInitialized
= true;
347 * Enable "sheet of glass" effect on the given Window
349 bool lamexp_sheet_of_glass(QWidget
*window
)
351 QReadLocker
readLock(&g_lamexp_dwmapi
.lock
);
353 //Initialize the DWM API
354 while(!g_lamexp_dwmapi
.bInitialized
)
357 lamexp_init_dwmapi();
361 BOOL bCompositionEnabled
= FALSE
;
363 //Required functions available?
364 if((g_lamexp_dwmapi
.dwmIsCompositionEnabled
!= NULL
) && (g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
!= NULL
) && (g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
!= NULL
))
366 //Check if composition is currently enabled
367 if(HRESULT hr
= g_lamexp_dwmapi
.dwmIsCompositionEnabled(&bCompositionEnabled
))
369 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
374 //All functions available *and* composition enabled?
375 if(!bCompositionEnabled
)
380 //Enable the "sheet of glass" effect on this window
381 MARGINS margins
= {-1, -1, -1, -1};
382 if(HRESULT hr
= g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea(window
->winId(), &margins
))
384 qWarning("DwmExtendFrameIntoClientArea function has failed! (error %d)", hr
);
388 //Create and populate the Blur Behind structure
390 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
392 bb
.dwFlags
= DWM_BB_ENABLE
;
393 if(HRESULT hr
= g_lamexp_dwmapi
.dwmEnableBlurBehindWindow(window
->winId(), &bb
))
395 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
400 window
->setAutoFillBackground(false);
401 window
->setAttribute(Qt::WA_TranslucentBackground
);
402 window
->setAttribute(Qt::WA_NoSystemBackground
);
408 * Update "sheet of glass" effect on the given Window
410 bool lamexp_sheet_of_glass_update(QWidget
*window
)
412 QReadLocker
readLock(&g_lamexp_dwmapi
.lock
);
414 //Initialize the DWM API
415 while(!g_lamexp_dwmapi
.bInitialized
)
418 lamexp_init_dwmapi();
422 BOOL bCompositionEnabled
= FALSE
;
424 //Required functions available?
425 if((g_lamexp_dwmapi
.dwmIsCompositionEnabled
!= NULL
) && (g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
!= NULL
))
427 //Check if composition is currently enabled
428 if(HRESULT hr
= g_lamexp_dwmapi
.dwmIsCompositionEnabled(&bCompositionEnabled
))
430 qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr
);
435 //All functions available *and* composition enabled?
436 if(!bCompositionEnabled
)
441 //Create and populate the Blur Behind structure
443 memset(&bb
, 0, sizeof(DWM_BLURBEHIND
));
445 bb
.dwFlags
= DWM_BB_ENABLE
;
446 if(HRESULT hr
= g_lamexp_dwmapi
.dwmEnableBlurBehindWindow(window
->winId(), &bb
))
448 qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr
);
456 * Get system color info
458 QColor
lamexp_system_color(const int color_id
)
464 case lamexp_syscolor_text
:
465 nIndex
= COLOR_WINDOWTEXT
; /*Text in windows*/
467 case lamexp_syscolor_background
:
468 nIndex
= COLOR_WINDOW
; /*Window background*/
470 case lamexp_syscolor_caption
:
471 nIndex
= COLOR_CAPTIONTEXT
; /*Text in caption, size box, and scroll bar arrow box*/
474 qWarning("Unknown system color id (%d) specified!", color_id
);
475 nIndex
= COLOR_WINDOWTEXT
;
478 const DWORD rgb
= GetSysColor(nIndex
);
479 QColor
color(GetRValue(rgb
), GetGValue(rgb
), GetBValue(rgb
));
483 ///////////////////////////////////////////////////////////////////////////////
485 ///////////////////////////////////////////////////////////////////////////////
487 extern "C" void _lamexp_global_init_win32(void)
489 //Zero *before* constructors are called
490 MUTILS_ZERO_MEMORY(g_lamexp_wine
);
491 MUTILS_ZERO_MEMORY(g_lamexp_themes_enabled
);
492 MUTILS_ZERO_MEMORY(g_lamexp_dwmapi
);
493 MUTILS_ZERO_MEMORY(g_lamexp_sounds
);
496 ///////////////////////////////////////////////////////////////////////////////
498 ///////////////////////////////////////////////////////////////////////////////
500 extern "C" void _lamexp_global_free_win32(void)
503 g_lamexp_dwmapi
.dwmIsCompositionEnabled
= NULL
;
504 g_lamexp_dwmapi
.dwmExtendFrameIntoClientArea
= NULL
;
505 g_lamexp_dwmapi
.dwmEnableBlurBehindWindow
= NULL
;
506 MUTILS_DELETE(g_lamexp_dwmapi
.dwmapi_dll
);
509 MUTILS_DELETE(g_lamexp_sounds
.sound_db
);