So basically I have a plugin dll that is loaded by a GUI-Application. In this dll I need to detect when Windows enters the Hibernate state. I cannot modify the GUI-App. GetMessage only works if the calling thread is the same thread as the UI-Thread, which it is not. Any ideas?
views:
373answers:
2
+1
Q:
How to get the Windows Power State Message (WM_POWERBROADCAST) when not running a Win32 GUI app?
+1
A:
You could create a hidden window in a seperate thread from your DLL code. And process messages as shown below.
You could use this Window class for that.
#pragma once
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;
static const char *g_AppName = "Test";
class CMyWindow
{
HWND _hWnd;
int _width;
int _height;
public:
CMyWindow(const int width,const int height):_hWnd(NULL),_width(width),_height(height)
{
_beginthread( &CMyWindow::thread_entry, 0, this);
}
~CMyWindow(void)
{
SendMessage(_hWnd, WM_CLOSE, NULL, NULL);
}
private:
static void thread_entry(void * p_userdata)
{
CMyWindow * p_win = static_cast<CMyWindow*> (p_userdata);
p_win->create_window();
p_win->message_loop();
}
void create_window()
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = &CMyWindow::WindowProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = GetModuleHandle(NULL);
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = g_AppName;
wcex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wcex);
_hWnd = CreateWindow(g_AppName, g_AppName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, GetModuleHandle(NULL), NULL);
ShowWindow(_hWnd, SW_SHOWDEFAULT);
UpdateWindow(_hWnd);
}
void message_loop()
{
MSG msg = {0};
while (GetMessage(&msg, NULL, 0, 0))
{
if(msg.message == WM_QUIT)
{
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
static LRESULT WINAPI WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_POWERBROADCAST:
{
//power management code here
}
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
};
Also make sure to include an exit condition.
Indeera
2009-07-22 14:33:09
Thanks, that works perfectly!
Simon H.
2009-07-22 15:26:51
+1
A:
You can get the user of your DLL to pass in their HWND . Once you have this handle you can GetWindowLongPtr the window proc (GWL_WNDPROC) and then SetWindowLongPtr your own window proc that will process the WM_POWERBROADCAST and pass all messages on to the old window procedure that you stored from the initial GetWindowLongPtr.
When the DLL exits you can SetWindowLongPtr to its own window proc and even if your DLL is unloaded early thinigs will continue to play nicely.
Goz
2009-07-22 15:03:40
This could work as well but I don't have a direct way to get the HWND handle. I'd have to use something like FindWindow() to get the handle.
Simon H.
2009-07-22 15:28:50