From 52b230f2db271ea2b8c495b3382a605dca59492d Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Sat, 29 Nov 2014 01:22:46 +0100 Subject: [PATCH] Moved more functions into MUtils library, especially all the Qt initialization code and some more OS-specific stuff. --- MUtilities_VS2013.vcxproj | 3 + MUtilities_VS2013.vcxproj.filters | 9 +++ include/MUtils/GUI.h | 49 +++++++++++ include/MUtils/OSSupport.h | 7 ++ include/MUtils/Startup.h | 3 + include/MUtils/Terminal.h | 6 +- src/ErrorHandler_Win32.cpp | 2 + src/GUI.cpp | 74 +++++++++++++++++ src/OSSupport_Win32.cpp | 147 +++++++++++++++++++++++++++++++-- src/Startup.cpp | 165 +++++++++++++++++++++++++++++++++++++- src/Terminal_Win32.cpp | 61 ++++++++++---- src/Utils_Win32.h | 45 +++++++++++ 12 files changed, 547 insertions(+), 24 deletions(-) create mode 100644 include/MUtils/GUI.h create mode 100644 src/GUI.cpp create mode 100644 src/Utils_Win32.h diff --git a/MUtilities_VS2013.vcxproj b/MUtilities_VS2013.vcxproj index ef947ea..77f48a3 100644 --- a/MUtilities_VS2013.vcxproj +++ b/MUtilities_VS2013.vcxproj @@ -19,6 +19,7 @@ + @@ -32,11 +33,13 @@ + + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)" MOC "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" diff --git a/MUtilities_VS2013.vcxproj.filters b/MUtilities_VS2013.vcxproj.filters index a031eeb..2c07910 100644 --- a/MUtilities_VS2013.vcxproj.filters +++ b/MUtilities_VS2013.vcxproj.filters @@ -54,6 +54,9 @@ Source Files + + Source Files + @@ -89,6 +92,12 @@ Public Headers + + Public Headers + + + Header Files + diff --git a/include/MUtils/GUI.h b/include/MUtils/GUI.h new file mode 100644 index 0000000..a5e9cf5 --- /dev/null +++ b/include/MUtils/GUI.h @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//MUtils +#include + +/////////////////////////////////////////////////////////////////////////////// + +namespace MUtils +{ + namespace GUI + { + typedef enum + { + USER_EVENT = 1000, /*QEvent::User*/ + USER_EVENT_QUERYENDSESSION = USER_EVENT + 666, + USER_EVENT_ENDSESSION = USER_EVENT + 667 + } + user_events_t; + + //Broadcast message + MUTILS_API bool broadcast(int eventType, const bool &onlyToVisible); + + //Force quit application + MUTILS_API void force_quit(void); + } +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/include/MUtils/OSSupport.h b/include/MUtils/OSSupport.h index 3c4cea5..1cd5498 100644 --- a/include/MUtils/OSSupport.h +++ b/include/MUtils/OSSupport.h @@ -106,6 +106,7 @@ namespace MUtils //Get the OS version MUTILS_API const Version::os_version_t &os_version(void); MUTILS_API const char *os_friendly_name(const MUtils::OS::Version::os_version_t &os_version); + MUTILS_API const bool &running_on_wine(void); //Get known Folder MUTILS_API const QString &known_folder(known_folder_t folder_id); @@ -113,9 +114,15 @@ namespace MUtils //Current Date MUTILS_API QDate current_date(void); + //Check for process elevation + MUTILS_API bool is_elevated(bool *bIsUacEnabled = NULL); + //Network Status MUTILS_API int network_status(void); + //Message handler + MUTILS_API bool handle_os_message(const void *const message, long *result); + //Error handling MUTILS_API void fatal_exit(const wchar_t* const errorMessage); } diff --git a/include/MUtils/Startup.h b/include/MUtils/Startup.h index 17239c7..6017d83 100644 --- a/include/MUtils/Startup.h +++ b/include/MUtils/Startup.h @@ -35,6 +35,9 @@ namespace MUtils //Startup Application MUTILS_API int startup(int &argc, char **argv, main_function_t *const entry_point); + + //Initialize Qt + MUTILS_API bool init_qt(int &argc, char **argv, const QString &appName); } } diff --git a/include/MUtils/Terminal.h b/include/MUtils/Terminal.h index 41b2ac7..e5039be 100644 --- a/include/MUtils/Terminal.h +++ b/include/MUtils/Terminal.h @@ -25,8 +25,7 @@ #include //Qt -#include -#include +#include /////////////////////////////////////////////////////////////////////////////// @@ -39,6 +38,9 @@ namespace MUtils //Terminal output MUTILS_API void write(const int &type, const char *const message); + + //Terminal icon + MUTILS_API void set_icon(const QIcon &icon); } } diff --git a/src/ErrorHandler_Win32.cpp b/src/ErrorHandler_Win32.cpp index 7a4222e..cdbb2e4 100644 --- a/src/ErrorHandler_Win32.cpp +++ b/src/ErrorHandler_Win32.cpp @@ -66,6 +66,7 @@ void MUtils::ErrorHandler::initialize(void) SetUnhandledExceptionFilter(my_exception_handler); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); _set_invalid_parameter_handler(my_invalid_param_handler); + SetDllDirectoryW(L""); /*don'tload DLL from "current" directory*/ static const int signal_num[6] = { SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM }; @@ -73,6 +74,7 @@ void MUtils::ErrorHandler::initialize(void) { signal(signal_num[i], my_signal_handler); } + } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/GUI.cpp b/src/GUI.cpp new file mode 100644 index 0000000..7453c6f --- /dev/null +++ b/src/GUI.cpp @@ -0,0 +1,74 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#include + +//Qt +#include +#include + +/////////////////////////////////////////////////////////////////////////////// +// BROADCAST +/////////////////////////////////////////////////////////////////////////////// + +bool MUtils::GUI::broadcast(int eventType, const bool &onlyToVisible) +{ + if(QApplication *app = dynamic_cast(QApplication::instance())) + { + qDebug("Broadcasting %d", eventType); + + bool allOk = true; + QEvent poEvent(static_cast(eventType)); + QWidgetList list = app->topLevelWidgets(); + + while(!list.isEmpty()) + { + QWidget *widget = list.takeFirst(); + if(!onlyToVisible || widget->isVisible()) + { + if(!app->sendEvent(widget, &poEvent)) + { + allOk = false; + } + } + } + + qDebug("Broadcast %d done (%s)", eventType, (allOk ? "OK" : "Stopped")); + return allOk; + } + else + { + qWarning("Broadcast failed, could not get QApplication instance!"); + return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// +// BROADCAST +/////////////////////////////////////////////////////////////////////////////// + +void MUtils::GUI::force_quit(void) +{ + qApp->closeAllWindows(); + qApp->quit(); +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/OSSupport_Win32.cpp b/src/OSSupport_Win32.cpp index e03eae7..46dd086 100644 --- a/src/OSSupport_Win32.cpp +++ b/src/OSSupport_Win32.cpp @@ -21,11 +21,6 @@ #pragma once -//Internal -#include -#include -#include "CriticalSection_Win32.h" - //Win32 API #define WIN32_LEAN_AND_MEAN 1 #include @@ -34,6 +29,12 @@ #include #include +//Internal +#include +#include +#include +#include "CriticalSection_Win32.h" + //Qt #include #include @@ -261,6 +262,7 @@ const MUtils::OS::Version::os_version_t &MUtils::OS::os_version(void) qWarning("Failed to determin the operating system version!"); } + //Completed g_os_version_initialized = true; return g_os_version_info; } @@ -279,6 +281,55 @@ const char *MUtils::OS::os_friendly_name(const MUtils::OS::Version::os_version_t } /////////////////////////////////////////////////////////////////////////////// +// WINE DETECTION +/////////////////////////////////////////////////////////////////////////////// + +static bool g_wine_deteced = false; +static bool g_wine_initialized = false; +static QReadWriteLock g_wine_lock; + +static const bool detect_wine(void) +{ + bool is_wine = false; + + QLibrary ntdll("ntdll.dll"); + if(ntdll.load()) + { + if(ntdll.resolve("wine_nt_to_unix_file_name") != NULL) is_wine = true; + if(ntdll.resolve("wine_get_version") != NULL) is_wine = true; + ntdll.unload(); + } + + return is_wine; +} + +const bool &MUtils::OS::running_on_wine(void) +{ + QReadLocker readLock(&g_wine_lock); + + //Already initialized? + if(g_wine_initialized) + { + return g_wine_deteced; + } + + readLock.unlock(); + QWriteLocker writeLock(&g_wine_lock); + + //Initialized now? + if(g_wine_initialized) + { + return g_wine_deteced; + } + + //Try to detect Wine + g_wine_deteced = detect_wine(); + g_wine_initialized = true; + + return g_wine_deteced; +} + +/////////////////////////////////////////////////////////////////////////////// // KNWON FOLDERS /////////////////////////////////////////////////////////////////////////////// @@ -458,6 +509,62 @@ QDate MUtils::OS::current_date(void) } /////////////////////////////////////////////////////////////////////////////// +// PROCESS ELEVATION +/////////////////////////////////////////////////////////////////////////////// + +bool MUtils::OS::is_elevated(bool *bIsUacEnabled) +{ + if(bIsUacEnabled) + { + *bIsUacEnabled = false; + } + + bool bIsProcessElevated = false; + HANDLE hToken = NULL; + + if(OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) + { + TOKEN_ELEVATION_TYPE tokenElevationType; + DWORD returnLength; + if(GetTokenInformation(hToken, TokenElevationType, &tokenElevationType, sizeof(TOKEN_ELEVATION_TYPE), &returnLength)) + { + if(returnLength == sizeof(TOKEN_ELEVATION_TYPE)) + { + switch(tokenElevationType) + { + case TokenElevationTypeDefault: + qDebug("Process token elevation type: Default -> UAC is disabled.\n"); + break; + case TokenElevationTypeFull: + qWarning("Process token elevation type: Full -> potential security risk!\n"); + bIsProcessElevated = true; + if(bIsUacEnabled) *bIsUacEnabled = true; + break; + case TokenElevationTypeLimited: + qDebug("Process token elevation type: Limited -> not elevated.\n"); + if(bIsUacEnabled) *bIsUacEnabled = true; + break; + default: + qWarning("Unknown tokenElevationType value: %d", tokenElevationType); + break; + } + } + else + { + qWarning("GetTokenInformation() return an unexpected size!"); + } + } + CloseHandle(hToken); + } + else + { + qWarning("Failed to open process token!"); + } + + return bIsProcessElevated; +} + +/////////////////////////////////////////////////////////////////////////////// // NETWORK STATE /////////////////////////////////////////////////////////////////////////////// @@ -473,6 +580,36 @@ int MUtils::OS::network_status(void) } /////////////////////////////////////////////////////////////////////////////// +// MESSAGE HANDLER +/////////////////////////////////////////////////////////////////////////////// + +bool MUtils::OS::handle_os_message(const void *const message, long *result) +{ + const MSG *const msg = reinterpret_cast(message); + + switch(msg->message) + { + case WM_QUERYENDSESSION: + qWarning("WM_QUERYENDSESSION message received!"); + *result = MUtils::GUI::broadcast(MUtils::GUI::USER_EVENT_QUERYENDSESSION, false) ? TRUE : FALSE; + return true; + case WM_ENDSESSION: + qWarning("WM_ENDSESSION message received!"); + if(msg->wParam == TRUE) + { + MUtils::GUI::broadcast(MUtils::GUI::USER_EVENT_ENDSESSION, false); + MUtils::GUI::force_quit(); + exit(1); + } + *result = 0; + return true; + default: + /*ignore this message and let Qt handle it*/ + return false; + } +} + +/////////////////////////////////////////////////////////////////////////////// // FATAL EXIT /////////////////////////////////////////////////////////////////////////////// diff --git a/src/Startup.cpp b/src/Startup.cpp index 32c80bd..de8d6b3 100644 --- a/src/Startup.cpp +++ b/src/Startup.cpp @@ -27,7 +27,14 @@ #include //Qt -#include +#include +#include +#include +#include +#include +#include +#include +#include /////////////////////////////////////////////////////////////////////////////// // MESSAGE HANDLER @@ -48,6 +55,11 @@ static void qt_message_handler(QtMsgType type, const char *msg) } } +static bool qt_event_filter(void *message, long *result) +{ + return MUtils::OS::handle_os_message(message, result); +} + /////////////////////////////////////////////////////////////////////////////// // STARTUP FUNCTION /////////////////////////////////////////////////////////////////////////////// @@ -105,3 +117,154 @@ int MUtils::Startup::startup(int &argc, char **argv, main_function_t *const entr } /////////////////////////////////////////////////////////////////////////////// +// QT INITIALIZATION +/////////////////////////////////////////////////////////////////////////////// + +static QMutex g_qt_lock; +static QScopedPointer g_application; + +static const char *const g_imageformats[] = {"bmp", "png", "jpg", "gif", "ico", "xpm", "svg", NULL}; + +bool MUtils::Startup::init_qt(int &argc, char **argv, const QString &appName) +{ + QMutexLocker lock(&g_qt_lock); + const QStringList &arguments = MUtils::OS::arguments(); + + //Don't initialized again, if done already + if(!g_application.isNull()) + { + return true; + } + + //Extract executable name from argv[] array + QString executableName = QLatin1String("LameXP.exe"); + if(arguments.count() > 0) + { + static const char *delimiters = "\\/:?"; + executableName = arguments[0].trimmed(); + for(int i = 0; delimiters[i]; i++) + { + int temp = executableName.lastIndexOf(QChar(delimiters[i])); + if(temp >= 0) executableName = executableName.mid(temp + 1); + } + executableName = executableName.trimmed(); + if(executableName.isEmpty()) + { + executableName = QLatin1String("LameXP.exe"); + } + } + + //Check Qt version +#ifdef QT_BUILD_KEY + qDebug("Using Qt v%s [%s], %s, %s", qVersion(), QLibraryInfo::buildDate().toString(Qt::ISODate).toLatin1().constData(), (qSharedBuild() ? "DLL" : "Static"), QLibraryInfo::buildKey().toLatin1().constData()); + qDebug("Compiled with Qt v%s [%s], %s\n", QT_VERSION_STR, QT_PACKAGEDATE_STR, QT_BUILD_KEY); + if(_stricmp(qVersion(), QT_VERSION_STR)) + { + qFatal("%s", QApplication::tr("Executable '%1' requires Qt v%2, but found Qt v%3.").arg(executableName, QString::fromLatin1(QT_VERSION_STR), QString::fromLatin1(qVersion())).toLatin1().constData()); + return false; + } + if(QLibraryInfo::buildKey().compare(QString::fromLatin1(QT_BUILD_KEY), Qt::CaseInsensitive)) + { + qFatal("%s", QApplication::tr("Executable '%1' was built for Qt '%2', but found Qt '%3'.").arg(executableName, QString::fromLatin1(QT_BUILD_KEY), QLibraryInfo::buildKey()).toLatin1().constData()); + return false; + } +#else + qDebug("Using Qt v%s [%s], %s", qVersion(), QLibraryInfo::buildDate().toString(Qt::ISODate).toLatin1().constData(), (qSharedBuild() ? "DLL" : "Static")); + qDebug("Compiled with Qt v%s [%s]\n", QT_VERSION_STR, QT_PACKAGEDATE_STR); +#endif + + //Check the Windows version + + const MUtils::OS::Version::os_version_t &osVersion = MUtils::OS::os_version(); + if((osVersion.type != MUtils::OS::Version::OS_WINDOWS) || (osVersion < MUtils::OS::Version::WINDOWS_WINXP)) + { + qFatal("%s", QApplication::tr("Executable '%1' requires Windows XP or later.").arg(executableName).toLatin1().constData()); + } + + //Check whether we are running on a supported Windows version + if(const char *const friendlyName = MUtils::OS::os_friendly_name(osVersion)) + { + qDebug("Running on %s (NT v%u.%u).\n", friendlyName, osVersion.versionMajor, osVersion.versionMinor); + } + else + { + const QString message = QString().sprintf("Running on an unknown WindowsNT-based system (v%u.%u).", osVersion.versionMajor, osVersion.versionMinor); + qWarning("%s\n", MUTILS_UTF8(message)); + MUtils::OS::system_message_wrn(MUTILS_WCHR(message), L"LameXP"); + } + + //Check for compat mode + if(osVersion.overrideFlag && (osVersion <= MUtils::OS::Version::WINDOWS_WN100)) + { + qWarning("Windows compatibility mode detected!"); + if(!arguments.contains("--ignore-compat-mode", Qt::CaseInsensitive)) + { + qFatal("%s", QApplication::tr("Executable '%1' doesn't support Windows compatibility mode.").arg(executableName).toLatin1().constData()); + return false; + } + } + + //Check for Wine + if(MUtils::OS::running_on_wine()) + { + qWarning("It appears we are running under Wine, unexpected things might happen!\n"); + } + + //Set text Codec for locale + QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); + + //Create Qt application instance + g_application.reset(new QApplication(argc, argv)); + + //Load plugins from application directory + QCoreApplication::setLibraryPaths(QStringList() << QApplication::applicationDirPath()); + qDebug("Library Path:\n%s\n", MUTILS_UTF8(QApplication::libraryPaths().first())); + + //Set application properties + g_application->setApplicationName(appName); + g_application->setOrganizationName("LoRd_MuldeR"); + g_application->setOrganizationDomain("mulder.at.gg"); + g_application->setEventFilter(qt_event_filter); + + //Check for supported image formats + QList supportedFormats = QImageReader::supportedImageFormats(); + for(int i = 0; g_imageformats[i]; i++) + { + if(!supportedFormats.contains(g_imageformats[i])) + { + qFatal("Qt initialization error: QImageIOHandler for '%s' missing!", g_imageformats[i]); + return false; + } + } + + //Enable larger/smaller font size + double fontScaleFactor = 1.0; + if(arguments.contains("--huge-font", Qt::CaseInsensitive)) fontScaleFactor = 1.500; + if(arguments.contains("--big-font", Qt::CaseInsensitive)) fontScaleFactor = 1.250; + if(arguments.contains("--small-font", Qt::CaseInsensitive)) fontScaleFactor = 0.875; + if(arguments.contains("--tiny-font", Qt::CaseInsensitive)) fontScaleFactor = 0.750; + if(!qFuzzyCompare(fontScaleFactor, 1.0)) + { + qWarning("Application font scale factor set to: %.3f\n", fontScaleFactor); + QFont appFont = g_application->font(); + appFont.setPointSizeF(appFont.pointSizeF() * fontScaleFactor); + g_application->setFont(appFont); + } + + //Check for process elevation + if(MUtils::OS::is_elevated() && (!MUtils::OS::running_on_wine())) + { + QMessageBox messageBox(QMessageBox::Warning, "LameXP", "LameXP was started with 'elevated' rights, altough LameXP does not need these rights.
Running an applications with unnecessary rights is a potential security risk!
", QMessageBox::NoButton, NULL, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint | Qt::WindowStaysOnTopHint); + messageBox.addButton("Quit Program (Recommended)", QMessageBox::NoRole); + messageBox.addButton("Ignore", QMessageBox::NoRole); + if(messageBox.exec() == 0) + { + return NULL; + } + } + + //Successful + return g_application.data(); +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/src/Terminal_Win32.cpp b/src/Terminal_Win32.cpp index eff8630..b3ba9d9 100644 --- a/src/Terminal_Win32.cpp +++ b/src/Terminal_Win32.cpp @@ -20,21 +20,24 @@ // http://www.gnu.org/licenses/gpl-2.0.txt /////////////////////////////////////////////////////////////////////////////// -#include +//Windows includes +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN 1 +#include + //Internal +#include #include #include +#include "Utils_Win32.h" #include "CriticalSection_Win32.h" -//Windows includes -#define NOMINMAX -#define WIN32_LEAN_AND_MEAN 1 -#include - //Qt #include #include +#include +#include //CRT #include @@ -182,18 +185,18 @@ void MUtils::Terminal::setup(int &argc, char **argv, const bool forceEnabled) g_filebufStdErr.reset(new std::filebuf(hfStdErr)); std::cerr.rdbuf(g_filebufStdErr.data()); } - } - HWND hwndConsole = GetConsoleWindow(); - if((hwndConsole != NULL) && (hwndConsole != INVALID_HANDLE_VALUE)) - { - HMENU hMenu = GetSystemMenu(hwndConsole, 0); - EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); - RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND); + const HWND hwndConsole = GetConsoleWindow(); + if((hwndConsole != NULL) && (hwndConsole != INVALID_HANDLE_VALUE)) + { + HMENU hMenu = GetSystemMenu(hwndConsole, 0); + EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | MF_GRAYED); + RemoveMenu(hMenu, SC_CLOSE, MF_BYCOMMAND); - SetWindowPos (hwndConsole, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); - SetWindowLong(hwndConsole, GWL_STYLE, GetWindowLong(hwndConsole, GWL_STYLE) & (~WS_MAXIMIZEBOX) & (~WS_MINIMIZEBOX)); - SetWindowPos (hwndConsole, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); + SetWindowPos (hwndConsole, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); + SetWindowLong(hwndConsole, GWL_STYLE, GetWindowLong(hwndConsole, GWL_STYLE) & (~WS_MAXIMIZEBOX) & (~WS_MINIMIZEBOX)); + SetWindowPos (hwndConsole, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER|SWP_FRAMECHANGED); + } } } } @@ -327,3 +330,29 @@ void MUtils::Terminal::write(const int &type, const char *const message) write_logfile_helper(g_log_file.data(), type, message); } } + +/////////////////////////////////////////////////////////////////////////////// +// TERMINAL ICON +/////////////////////////////////////////////////////////////////////////////// + +void MUtils::Terminal::set_icon(const QIcon &icon) +{ + MUtils::Internal::CSLocker lock(g_terminal_lock); + + if(!(icon.isNull() || MUtils::OS::running_on_wine())) + { + QLibrary kernel32("kernel32.dll"); + if(kernel32.load()) + { + typedef DWORD (__stdcall *SetConsoleIconFun)(HICON); + if(SetConsoleIconFun SetConsoleIconPtr = (SetConsoleIconFun) kernel32.resolve("SetConsoleIcon")) + { + if(HICON hIcon = qicon_to_hicon(icon, 16, 16)) + { + SetConsoleIconPtr(hIcon); + DestroyIcon(hIcon); + } + } + } + } +} diff --git a/src/Utils_Win32.h b/src/Utils_Win32.h new file mode 100644 index 0000000..f074410 --- /dev/null +++ b/src/Utils_Win32.h @@ -0,0 +1,45 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +#pragma once + +//Win32 API +#ifndef _INC_WINDOWS +#define WIN32_LEAN_AND_MEAN 1 +#include +#endif //_INC_WINDOWS + +/////////////////////////////////////////////////////////////////////////////// +// QICON TO HICON +/////////////////////////////////////////////////////////////////////////////// + +static HICON qicon_to_hicon(const QIcon &icon, const int w, const int h) +{ + if(!icon.isNull()) + { + QPixmap pixmap = icon.pixmap(w, h); + if(!pixmap.isNull()) + { + return pixmap.toWinHICON(); + } + } + return NULL; +} -- 2.11.0