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?
3 Answers
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.

- 8,651
- 2
- 32
- 37
-
Really good example..May i know how to use this DLL with Application? – RDX Nov 15 '16 at 06:10
I ran into a similar problem with a Windows console application. I wrote up a blog post on what the issues are, how the hidden window seems like the only solution, and how to do it. The post is available here and the source code is available here. The basic principle I used is almost identical to Indeera's answer.
I'm not sure if you would have to modify my solution at all to run in a DLL. I believe that ALL threads which have a message queue (and a thread does when it creates a window) receive WM_POWERBROADCAST messages, so spooling up one of your own even if you are loaded by a Windows application might work.
It's worth noting by the way, that you aren't guaranteed to receive a notification prior to the system going into Hibernate (such as from a critical battery state) or any other sleep state for that matter. You will however receive a PBT_APMRESUMEAUTOMATIC event (or PBT_APMRESUMECRITICAL on systems prior to Vista) when the system comes back online after such an event has occurred.

- 13,476
- 14
- 56
- 65
-
-
Cf [CodeFinder's answer below for source code](https://stackoverflow.com/a/62439093/6069586): https://bitbucket.org/zachburlingame/windowspowerevents/src/default/ – JWCS Jun 17 '20 at 22:47
-
-
I forgot there were cross links here when that repo went stale. I’ll see if can put it up on GitHub later and update the link. – Zach Burlingame Jun 12 '21 at 15:47
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.

- 61,365
- 24
- 124
- 204
-
1This 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. Jul 22 '09 at 15:28
-
Subclassing (changing the wndproc) a hwnd that you don't own should be considered a last resort; it can be particularly fragile if you have two pieces of code trying to do it. Worse case is that you end up with another piece of code 'restoring' the wndproc to your DLL's wndproc after your DLL has been unloaded, leading to a crash. Check out this article on Raymond Chen's blog: http://blogs.msdn.com/b/oldnewthing/archive/2003/11/11/55653.aspx . At a bare minimum, you'd want to make it absolutely clear in the API doc that the hwnd passed in was going to be subclassed in this way. – BrendanMcK Apr 02 '11 at 06:04