所以基本上我有一个由GUI-Application加载的插件dll。在这个DLL中我需要检测Windows何时进入休眠状态。我无法修改GUI-App。 GetMessage仅在调用线程与UI-Thread相同的线程时才有效,而不是。有什么想法吗?
答案 0 :(得分:8)
您可以在DLL代码的单独线程中创建隐藏窗口。并处理如下所示的消息。
您可以使用此Window类。
#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);
}
};
还要确保包含退出条件。
答案 1 :(得分:1)
您可以让DLL的用户传入他们的HWND。一旦你有了这个句柄,你可以GetWindowLongPtr窗口proc(GWL_WNDPROC),然后SetWindowLongPtr你自己的窗口proc将处理WM_POWERBROADCAST并将所有消息传递给你从初始GetWindowLongPtr存储的旧窗口过程。
当DLL退出时,你可以将SetWindowLongPtr设置为它自己的窗口proc,即使你的DLL被卸载,早期的thinigs也会继续很好地运行。
答案 2 :(得分:1)
我遇到了与Windows控制台应用程序类似的问题。我写了一篇关于问题是什么的博客文章,隐藏窗口如何成为唯一的解决方案,以及如何做到这一点。该帖子可用here,源代码可用here。我使用的基本原理几乎与Indeera的答案相同。
我不确定你是否必须修改我的解决方案才能在DLL中运行。我相信所有具有消息队列的线程(以及线程在创建窗口时都会这样做)都会收到WM_POWERBROADCAST消息,因此即使您被Windows应用程序加载,也可以使用自己的一个线程。
值得注意的是,您不能保证在系统进入休眠状态之前(例如从关键电池状态)或任何其他睡眠状态接收通知。但是,当系统在发生此类事件后重新联机时,您将在Vista之前的系统上收到PBT_APMRESUMEAUTOMATIC事件(或PBT_APMRESUMECRITICAL)。