2009-07-22 60 views

回答

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); 
    } 
}; 

此外请确保包含退出条件。

+0

谢谢,这完美的作品! – 2009-07-22 15:26:51

+0

真的很好的例子..我可以知道如何在应用程序中使用这个DLL吗? – RDX 2016-11-15 06:10:25

1

您可以让您的DLL的用户通过他们的HWND。一旦你有这个句柄,你可以GetWindowLongPtr窗口过程(GWL_WNDPROC),然后SetWindowLongPtr你自己的窗口过程,将处理WM_POWERBROADCAST并将所有消息传递到您从初始GetWindowLongPtr存储的旧窗口过程。

当DLL退出时,您可以将SetWindowLongPtr设置为其自己的窗口过程,即使您的DLL已卸载,thinigs仍会继续良好地播放。

+1

这可以工作,但我没有直接的方式来获得HWND句柄。我不得不使用类似FindWindow()的东西来获取句柄。 – 2009-07-22 15:28:50

1

我遇到了Windows控制台应用程序的类似问题。我写了一篇关于问题是什么的博客文章,隐藏窗口是如何成为唯一的解决方案,以及如何去做。该帖子可用here,源代码可用here。我使用的基本原则与Indeera的答案几乎完全相同。

我不确定您是否必须修改我的解决方案才能在DLL中运行。我相信所有具有消息队列的线程(以及线程在创建窗口时都会执行这些操作)会收到WM_POWERBROADCAST消息,因此即使您由Windows应用程序加载,也可以使用自己的后台消息。

值得注意的是,在系统进入Hibernate之前(例如从关键电池状态)或任何其他睡眠状态,您不能保证收到通知。但是,如果在发生此类事件后系统重新联机,您将收到PBT_APMRESUMEAUTOMATIC事件(或在Vista之前的系统上为PBT_APMRESUMECRITICAL)。

相关问题