OSDN Git Service

Moved JobObject as well as the remaining GUI functions into the MUtilities library.
authorLoRd_MuldeR <mulder2@gmx.de>
Mon, 8 Dec 2014 21:03:36 +0000 (22:03 +0100)
committerLoRd_MuldeR <mulder2@gmx.de>
Mon, 8 Dec 2014 21:03:36 +0000 (22:03 +0100)
MUtilities_VS2013.vcxproj
MUtilities_VS2013.vcxproj.filters
include/MUtils/GUI.h
include/MUtils/JobObject.h [new file with mode: 0644]
include/MUtils/OSSupport.h
src/GUI.cpp
src/GUI_Win32.cpp [new file with mode: 0644]
src/JobObject_Win32.cpp [new file with mode: 0644]
src/OSSupport_Win32.cpp

index 16a7da4..a1f9d34 100644 (file)
@@ -23,6 +23,8 @@
     <ClCompile Include="src\ErrorHandler_Win32.cpp" />
     <ClCompile Include="src\Global.cpp" />
     <ClCompile Include="src\GUI.cpp" />
+    <ClCompile Include="src\GUI_Win32.cpp" />
+    <ClCompile Include="src\JobObject_Win32.cpp" />
     <ClCompile Include="src\KeccakHash.cpp" />
     <ClCompile Include="src\OSSupport_Win32.cpp" />
     <ClCompile Include="src\Sound_Win32.cpp" />
@@ -37,6 +39,7 @@
     <ClInclude Include="include\MUtils\Exception.h" />
     <ClInclude Include="include\MUtils\Global.h" />
     <ClInclude Include="include\MUtils\GUI.h" />
+    <ClInclude Include="include\MUtils\JobObject.h" />
     <ClInclude Include="include\MUtils\KeccakHash.h" />
     <ClInclude Include="include\MUtils\OSSupport.h" />
     <ClInclude Include="include\MUtils\Sound.h" />
index d4318a0..272fdb4 100644 (file)
     <ClCompile Include="src\Sound_Win32.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="src\JobObject_Win32.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="src\GUI_Win32.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="src\CriticalSection_Win32.h">
     <ClInclude Include="include\MUtils\Sound.h">
       <Filter>Public Headers</Filter>
     </ClInclude>
+    <ClInclude Include="include\MUtils\JobObject.h">
+      <Filter>Public Headers</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="include\Mutils\UpdateChecker.h">
index f11ef60..9140e02 100644 (file)
@@ -24,6 +24,9 @@
 //MUtils
 #include <MUtils/Global.h>
 
+//Qt
+#include <QColor>
+
 //Forward Declaration
 class QIcon;
 class QWidget;
@@ -41,11 +44,45 @@ namespace MUtils
                        USER_EVENT_ENDSESSION      = USER_EVENT + 667
                }
                user_events_t;
+               
+               typedef enum
+               {
+                       SYSCOLOR_TEXT       = 1,
+                       SYSCOLOR_BACKGROUND = 2,
+                       SYSCOLOR_CAPTION    = 3
+               }
+               system_color_t;
 
                //Broadcast message
                MUTILS_API bool broadcast(int eventType, const bool &onlyToVisible);
 
-               MUTILS_API bool set_window_icon(QWidget *window, const QIcon &icon, const bool bIsBigIcon);
+               //Window icon
+               MUTILS_API bool set_window_icon(QWidget *const window, const QIcon &icon, const bool bIsBigIcon);
+
+               //Theme support
+               MUTILS_API bool themes_enabled(void);
+
+               //System menu
+               MUTILS_API bool sysmenu_append(const QWidget *const win, const unsigned int identifier, const QString &text);
+               MUTILS_API bool sysmenu_update(const QWidget *const win, const unsigned int identifier, const QString &text);
+               MUTILS_API bool sysmenu_check_msg(void *const message, const unsigned int &identifier);
+
+               //Close button
+               MUTILS_API bool enable_close_button(const QWidget *const win, const bool &bEnable);
+
+               //Bring to front
+               MUTILS_API bool bring_to_front(const QWidget *const window);
+               MUTILS_API bool bring_to_front(const unsigned long pid);
+
+               //Sheet of glass
+               MUTILS_API bool sheet_of_glass(QWidget *const window);
+               MUTILS_API bool sheet_of_glass_update(QWidget *const window);
+
+               //System colors
+               MUTILS_API QColor system_color(const int &color_id);
+
+               //Blink window
+               MUTILS_API void blink_window(QWidget *const poWindow, const unsigned int &count = 10, const unsigned int &delay = 150);
 
                //Force quit application
                MUTILS_API void force_quit(void);
diff --git a/include/MUtils/JobObject.h b/include/MUtils/JobObject.h
new file mode 100644 (file)
index 0000000..62fb4be
--- /dev/null
@@ -0,0 +1,45 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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
+
+#include <MUtils/Global.h>
+#include <QScopedPointer>
+
+class QProcess;
+
+namespace MUtils
+{
+       class MUTILS_API JobObject_Private;
+
+       class MUTILS_API JobObject
+       {
+       public:
+               JobObject(void);
+               ~JobObject(void);
+
+               bool addProcessToJob(const QProcess *proc);
+               bool terminateJob(unsigned int exitCode);
+
+       private:
+               QScopedPointer<JobObject_Private> p;
+       };
+}
index b21d3c1..7db9988 100644 (file)
@@ -156,6 +156,8 @@ namespace MUtils
                MUTILS_API bool setup_timer_resolution(const quint32 &interval = 1);
                MUTILS_API bool reset_timer_resolution(const quint32 &interval = 1);
 
+               MUTILS_API bool check_key_state_esc(void);
+
                //Check if debugger is present
                MUTILS_API void check_debugger(void);
 
index 9bbf587..39863d4 100644 (file)
@@ -19,7 +19,9 @@
 // http://www.gnu.org/licenses/lgpl-2.1.txt
 //////////////////////////////////////////////////////////////////////////////////
 
+//MUtils
 #include <MUtils/GUI.h>
+#include <MUtils/OSSupport.h>
 
 //Internal
 #include "Utils_Win32.h"
@@ -28,6 +30,7 @@
 #include <QIcon>
 #include <QApplication>
 #include <QWidget>
+#include <QMutex>
 
 ///////////////////////////////////////////////////////////////////////////////
 // BROADCAST
@@ -101,7 +104,7 @@ namespace MUtils
        }
 }
 
-bool MUtils::GUI::set_window_icon(QWidget *window, const QIcon &icon, const bool bIsBigIcon)
+bool MUtils::GUI::set_window_icon(QWidget *const window, const QIcon &icon, const bool bIsBigIcon)
 {
        if((!icon.isNull()) && window->winId())
        {
@@ -118,6 +121,58 @@ bool MUtils::GUI::set_window_icon(QWidget *window, const QIcon &icon, const bool
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// BLINK WINDOW
+///////////////////////////////////////////////////////////////////////////////
+
+static QMutex g_blinkMutex;
+
+void MUtils::GUI::blink_window(QWidget *const poWindow, const unsigned int &count, const unsigned int &delay)
+{
+       const double maxOpac = 1.0;
+       const double minOpac = 0.3;
+       const double delOpac = 0.1;
+
+       if(!g_blinkMutex.tryLock())
+       {
+               qWarning("Blinking is already in progress, skipping!");
+               return;
+       }
+       
+       try
+       {
+               const int steps = static_cast<int>(ceil(maxOpac - minOpac) / delOpac);
+               const int sleep = static_cast<int>(floor(static_cast<double>(delay) / static_cast<double>(steps)));
+               const double opacity = poWindow->windowOpacity();
+       
+               for(unsigned int i = 0; i < count; i++)
+               {
+                       for(double x = maxOpac; x >= minOpac; x -= delOpac)
+                       {
+                               poWindow->setWindowOpacity(x);
+                               QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+                               MUtils::OS::sleep_ms(sleep);
+                       }
+
+                       for(double x = minOpac; x <= maxOpac; x += delOpac)
+                       {
+                               poWindow->setWindowOpacity(x);
+                               QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+                               MUtils::OS::sleep_ms(sleep);
+                       }
+               }
+
+               poWindow->setWindowOpacity(opacity);
+               QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+       }
+       catch(...)
+       {
+               qWarning("Exception error while blinking!");
+       }
+
+       g_blinkMutex.unlock();
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // FORCE QUIT
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/GUI_Win32.cpp b/src/GUI_Win32.cpp
new file mode 100644 (file)
index 0000000..66bf78b
--- /dev/null
@@ -0,0 +1,363 @@
+///////////////////////////////////////////////////////////////////////////////
+// MuldeR's Utilities for Qt
+// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// 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
+//////////////////////////////////////////////////////////////////////////////////
+
+//Win32 API
+#define WIN32_LEAN_AND_MEAN 1
+#include <Windows.h>
+
+//MUtils
+#include <MUtils/GUI.h>
+#include <MUtils/OSSupport.h>
+
+//Internal
+#include "Utils_Win32.h"
+
+//Qt
+#include <QIcon>
+#include <QApplication>
+#include <QWidget>
+#include <QReadWriteLock>
+#include <QLibrary>
+#include <Dwmapi.h>
+
+///////////////////////////////////////////////////////////////////////////////
+// THEME SUPPORT
+///////////////////////////////////////////////////////////////////////////////
+
+static QReadWriteLock g_themes_lock;
+static bool g_themes_initialized = false;
+static bool g_themes_enabled = false;
+
+typedef int (WINAPI *IsAppThemedFunction)(void);
+
+bool MUtils::GUI::themes_enabled(void)
+{
+       QReadLocker readLock(&g_themes_lock);
+
+       if(g_themes_initialized)
+       {
+               return g_themes_enabled;
+       }
+
+       readLock.unlock();
+       QWriteLocker writeLock(&g_themes_lock);
+
+       if(g_themes_initialized)
+       {
+               return g_themes_enabled;
+       }
+
+       const MUtils::OS::Version::os_version_t &osVersion = MUtils::OS::os_version();
+       if(osVersion >= MUtils::OS::Version::WINDOWS_WINXP)
+       {
+               IsAppThemedFunction IsAppThemedPtr = NULL;
+               QLibrary uxTheme("UxTheme.dll");
+               if(uxTheme.load())
+               {
+                       IsAppThemedPtr = (IsAppThemedFunction) uxTheme.resolve("IsAppThemed");
+               }
+               if(IsAppThemedPtr)
+               {
+                       g_themes_enabled = IsAppThemedPtr();
+                       if(!g_themes_enabled)
+                       {
+                               qWarning("Theme support is disabled for this process!");
+                       }
+               }
+       }
+
+       g_themes_initialized = true;
+       return g_themes_enabled;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SYSTEM MENU
+///////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::GUI::sysmenu_append(const QWidget *win, const unsigned int identifier, const QString &text)
+{
+       bool ok = false;
+       
+       if(HMENU hMenu = GetSystemMenu(win->winId(), FALSE))
+       {
+               ok = (AppendMenuW(hMenu, MF_SEPARATOR, 0, 0) == TRUE);
+               ok = (AppendMenuW(hMenu, MF_STRING, identifier, MUTILS_WCHR(text)) == TRUE);
+       }
+
+       return ok;
+}
+
+bool MUtils::GUI::sysmenu_update(const QWidget *win, const unsigned int identifier, const QString &text)
+{
+       bool ok = false;
+       
+       if(HMENU hMenu = ::GetSystemMenu(win->winId(), FALSE))
+       {
+               ok = (ModifyMenu(hMenu, identifier, MF_STRING | MF_BYCOMMAND, identifier, MUTILS_WCHR(text)) == TRUE);
+       }
+       return ok;
+}
+
+bool MUtils::GUI::sysmenu_check_msg(void *const message, const unsigned int &identifier)
+{
+       return (((MSG*)message)->message == WM_SYSCOMMAND) && ((((MSG*)message)->wParam & 0xFFF0) == identifier);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// CLOSE BUTTON
+///////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::GUI::enable_close_button(const QWidget *win, const bool &bEnable)
+{
+       bool ok = false;
+
+       if(HMENU hMenu = GetSystemMenu(win->winId(), FALSE))
+       {
+               ok = (EnableMenuItem(hMenu, SC_CLOSE, MF_BYCOMMAND | (bEnable ? MF_ENABLED : MF_GRAYED)) == TRUE);
+       }
+
+       return ok;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// BRING WINDOW TO FRONT
+///////////////////////////////////////////////////////////////////////////////
+
+static BOOL CALLBACK bring_process_to_front_helper(HWND hwnd, LPARAM lParam)
+{
+       DWORD processId = *reinterpret_cast<WORD*>(lParam);
+       DWORD windowProcessId = NULL;
+       GetWindowThreadProcessId(hwnd, &windowProcessId);
+       if(windowProcessId == processId)
+       {
+               SwitchToThisWindow(hwnd, TRUE);
+               SetForegroundWindow(hwnd);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+bool MUtils::GUI::bring_to_front(const QWidget *window)
+{
+       bool ret = false;
+       
+       if(window)
+       {
+               for(int i = 0; (i < 5) && (!ret); i++)
+               {
+                       ret = (SetForegroundWindow(window->winId()) != FALSE);
+                       SwitchToThisWindow(window->winId(), TRUE);
+               }
+               LockSetForegroundWindow(LSFW_LOCK);
+       }
+
+       return ret;
+}
+
+bool MUtils::GUI::bring_to_front(const unsigned long pid)
+{
+       return EnumWindows(bring_process_to_front_helper, reinterpret_cast<LPARAM>(&pid)) == TRUE;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SHEET OF GLASS EFFECT
+///////////////////////////////////////////////////////////////////////////////
+
+static QReadWriteLock g_dwmapi_lock;
+static QScopedPointer<QLibrary> g_dwmapi_library;
+static bool g_dwmapi_initialized = false;
+
+static struct
+{
+       HRESULT (__stdcall *dwmIsCompositionEnabled)(BOOL *bEnabled);
+       HRESULT (__stdcall *dwmExtendFrameIntoClientArea)(HWND hWnd, const MARGINS* pMarInset);
+       HRESULT (__stdcall *dwmEnableBlurBehindWindow)(HWND hWnd, const DWM_BLURBEHIND* pBlurBehind);
+}
+g_dwmapi_pointers = { NULL, NULL, NULL };
+
+static void initialize_dwmapi(void)
+{
+       QReadLocker writeLock(&g_dwmapi_lock);
+
+       //Not initialized yet?
+       if(g_dwmapi_initialized)
+       {
+               return;
+       }
+       
+       //Reset function pointers
+       g_dwmapi_pointers.dwmIsCompositionEnabled      = NULL;
+       g_dwmapi_pointers.dwmExtendFrameIntoClientArea = NULL;
+       g_dwmapi_pointers.dwmEnableBlurBehindWindow    = NULL;
+                       
+       //Does OS support DWM?
+       const MUtils::OS::Version::os_version_t &osVersion = MUtils::OS::os_version();
+       if(osVersion >= MUtils::OS::Version::WINDOWS_VISTA)
+       {
+               //Load DWMAPI.DLL
+               g_dwmapi_library.reset(new QLibrary("dwmapi.dll"));
+               if(g_dwmapi_library->load())
+               {
+                       //Initialize function pointers
+                       g_dwmapi_pointers.dwmIsCompositionEnabled      = (HRESULT (__stdcall*)(BOOL*))                       g_dwmapi_library->resolve("DwmIsCompositionEnabled");
+                       g_dwmapi_pointers.dwmExtendFrameIntoClientArea = (HRESULT (__stdcall*)(HWND, const MARGINS*))        g_dwmapi_library->resolve("DwmExtendFrameIntoClientArea");
+                       g_dwmapi_pointers.dwmEnableBlurBehindWindow    = (HRESULT (__stdcall*)(HWND, const DWM_BLURBEHIND*)) g_dwmapi_library->resolve("DwmEnableBlurBehindWindow");
+               }
+               else
+               {
+                       g_dwmapi_library.reset(NULL);
+                       qWarning("Failed to load DWMAPI.DLL on a DWM-enabled system!");
+               }
+       }
+
+       g_dwmapi_initialized = true;
+}
+
+bool MUtils::GUI::sheet_of_glass(QWidget *const window)
+{
+       QReadLocker readLock(&g_dwmapi_lock);
+
+       //Initialize the DWM API
+       if(!g_dwmapi_initialized)
+       {
+               readLock.unlock();
+               initialize_dwmapi();
+               readLock.relock();
+       }
+
+       //Required functions available?
+       BOOL bCompositionEnabled = FALSE;
+       if(g_dwmapi_pointers.dwmIsCompositionEnabled && g_dwmapi_pointers.dwmExtendFrameIntoClientArea && g_dwmapi_pointers.dwmEnableBlurBehindWindow)
+       {
+               //Check if composition is currently enabled
+               if(HRESULT hr = g_dwmapi_pointers.dwmIsCompositionEnabled(&bCompositionEnabled))
+               {
+                       qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr);
+                       return false;
+               }
+       }
+       
+       //All functions available *and* composition enabled?
+       if(!bCompositionEnabled)
+       {
+               return false;
+       }
+
+       //Enable the "sheet of glass" effect on this window
+       MARGINS margins = {-1, -1, -1, -1};
+       if(HRESULT hr = g_dwmapi_pointers.dwmExtendFrameIntoClientArea(window->winId(), &margins))
+       {
+               qWarning("DwmExtendFrameIntoClientArea function has failed! (error %d)", hr);
+               return false;
+       }
+
+       //Create and populate the Blur Behind structure
+       DWM_BLURBEHIND bb;
+       memset(&bb, 0, sizeof(DWM_BLURBEHIND));
+       bb.fEnable = TRUE;
+       bb.dwFlags = DWM_BB_ENABLE;
+       if(HRESULT hr = g_dwmapi_pointers.dwmEnableBlurBehindWindow(window->winId(), &bb))
+       {
+               qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr);
+               return false;
+       }
+
+       //Required for Qt
+       window->setAutoFillBackground(false);
+       window->setAttribute(Qt::WA_TranslucentBackground);
+       window->setAttribute(Qt::WA_NoSystemBackground);
+
+       return true;
+}
+
+bool MUtils::GUI::sheet_of_glass_update(QWidget *const window)
+{
+       QReadLocker readLock(&g_dwmapi_lock);
+
+       //Initialize the DWM API
+       if(!g_dwmapi_initialized)
+       {
+               readLock.unlock();
+               initialize_dwmapi();
+               readLock.relock();
+       }
+
+       //Required functions available?
+       BOOL bCompositionEnabled = FALSE;
+       if(g_dwmapi_pointers.dwmIsCompositionEnabled && g_dwmapi_pointers.dwmExtendFrameIntoClientArea && g_dwmapi_pointers.dwmEnableBlurBehindWindow)
+       {
+               //Check if composition is currently enabled
+               if(HRESULT hr = g_dwmapi_pointers.dwmIsCompositionEnabled(&bCompositionEnabled))
+               {
+                       qWarning("DwmIsCompositionEnabled function has failed! (error %d)", hr);
+                       return false;
+               }
+       }
+       
+       //All functions available *and* composition enabled?
+       if(!bCompositionEnabled)
+       {
+               return false;
+       }
+
+       //Create and populate the Blur Behind structure
+       DWM_BLURBEHIND bb;
+       memset(&bb, 0, sizeof(DWM_BLURBEHIND));
+       bb.fEnable = TRUE;
+       bb.dwFlags = DWM_BB_ENABLE;
+       if(HRESULT hr = g_dwmapi_pointers.dwmEnableBlurBehindWindow(window->winId(), &bb))
+       {
+               qWarning("DwmEnableBlurBehindWindow function has failed! (error %d)", hr);
+               return false;
+       }
+
+       return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SYSTEM COLORS
+///////////////////////////////////////////////////////////////////////////////
+
+QColor MUtils::GUI::system_color(const int &color_id)
+{
+       int nIndex = -1;
+
+       switch(color_id)
+       {
+       case SYSCOLOR_TEXT:
+               nIndex = COLOR_WINDOWTEXT;              /*Text in windows*/
+               break;
+       case SYSCOLOR_BACKGROUND:
+               nIndex = COLOR_WINDOW;                  /*Window background*/
+               break;
+       case SYSCOLOR_CAPTION:
+               nIndex = COLOR_CAPTIONTEXT;             /*Text in caption, size box, and scroll bar arrow box*/
+               break;
+       default:
+               qWarning("Unknown system color id (%d) specified!", color_id);
+               nIndex = COLOR_WINDOWTEXT;
+       }
+       
+       const DWORD rgb = GetSysColor(nIndex);
+       QColor color(GetRValue(rgb), GetGValue(rgb), GetBValue(rgb));
+       return color;
+}
diff --git a/src/JobObject_Win32.cpp b/src/JobObject_Win32.cpp
new file mode 100644 (file)
index 0000000..51c1295
--- /dev/null
@@ -0,0 +1,146 @@
+///////////////////////////////////////////////////////////////////////////////
+// LameXP - Audio Encoder Front-End
+// Copyright (C) 2004-2014 LoRd_MuldeR <MuldeR2@GMX.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version, but always including the *additional*
+// restrictions defined in the "License.txt" file.
+//
+// This program 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 General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// http://www.gnu.org/licenses/gpl-2.0.txt
+///////////////////////////////////////////////////////////////////////////////
+
+//Internal
+#include <MUtils/JobObject.h>
+
+//Qt
+#include <QProcess>
+
+//Windows includes
+#define NOMINMAX
+#define WIN32_LEAN_AND_MEAN 1
+#include <Windows.h>
+#include <MMSystem.h>
+#include <ShellAPI.h>
+#include <WinInet.h>
+
+namespace MUtils
+{
+       class JobObject_Private
+       {
+               friend class JobObject;
+
+       protected:
+               JobObject_Private(void)
+               {
+                       m_hJobObject = NULL;
+               }
+
+               HANDLE m_hJobObject;
+       };
+}
+
+MUtils::JobObject::JobObject(void)
+:
+       p(new JobObject_Private())
+{
+       const HANDLE jobObject = CreateJobObject(NULL, NULL);
+       if((jobObject != NULL) && (jobObject != INVALID_HANDLE_VALUE))
+       {
+               JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobExtendedLimitInfo;
+               memset(&jobExtendedLimitInfo, 0, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
+               memset(&jobExtendedLimitInfo.BasicLimitInformation, 0, sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION));
+               jobExtendedLimitInfo.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
+               if(SetInformationJobObject(jobObject, JobObjectExtendedLimitInformation, &jobExtendedLimitInfo, sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)))
+               {
+                       p->m_hJobObject = jobObject;
+               }
+               else
+               {
+                       qWarning("Failed to set job object information!");
+                       CloseHandle(jobObject);
+               }
+       }
+       else
+       {
+               qWarning("Failed to create the job object!");
+       }
+}
+
+MUtils::JobObject::~JobObject(void)
+{
+       if(p->m_hJobObject)
+       {
+               CloseHandle(p->m_hJobObject);
+               p->m_hJobObject = NULL;
+       }
+}
+
+bool MUtils::JobObject::addProcessToJob(const QProcess *proc)
+{
+       if(!p->m_hJobObject)
+       {
+               qWarning("Cannot assign process to job: No job bject available!");
+               return false;
+       }
+
+       if(Q_PID pid = proc->pid())
+       {
+               DWORD exitCode;
+               if(!GetExitCodeProcess(pid->hProcess, &exitCode))
+               {
+                       qWarning("Cannot assign process to job: Failed to query process status!");
+                       return false;
+               }
+
+               if(exitCode != STILL_ACTIVE)
+               {
+                       qWarning("Cannot assign process to job: Process is not running anymore!");
+                       return false;
+               }
+
+               if(!AssignProcessToJobObject(p->m_hJobObject, pid->hProcess))
+               {
+                       qWarning("Failed to assign process to job object!");
+                       return false;
+               }
+
+               return true;
+       }
+       else
+       {
+               qWarning("Cannot assign process to job: Process handle not available!");
+               return false;
+       }
+}
+
+bool MUtils::JobObject::terminateJob(unsigned int exitCode)
+{
+       if(p->m_hJobObject)
+       {
+               if(TerminateJobObject(p->m_hJobObject, exitCode))
+               {
+                       return true;
+               }
+               else
+               {
+                       qWarning("Failed to terminate job object!");
+                       return false;
+               }
+       }
+       else
+       {
+               qWarning("Cannot assign process to job: No job bject available!");
+               return false;
+       }
+}
index 3df1dba..a875e3d 100644 (file)
@@ -949,6 +949,15 @@ bool MUtils::OS::reset_timer_resolution(const quint32 &interval)
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// CHECK KEY STATE
+///////////////////////////////////////////////////////////////////////////////
+
+bool MUtils::OS::check_key_state_esc(void)
+{
+       return (GetAsyncKeyState(VK_ESCAPE) & 0x0001) != 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // DEBUGGER CHECK
 ///////////////////////////////////////////////////////////////////////////////