How to receive WM_POWERBROADCAST inside of a thread?

后端 未结 1 1237
被撕碎了的回忆
被撕碎了的回忆 2021-01-21 00:41

I\'ve been beating my head for over a day now, going through tons of resources trying to figure out how to receive the WM_POWERBROADCAST Windows message from within

相关标签:
1条回答
  • 2021-01-21 01:14

    WM_POWERBROADCAST is not a posted message, so your message loop will never see it. You need a window procedure to receive that message. Your thread code is using DefWindowProc() directly as the window procedure. Change the call to RegisterClass() to register a custom procedure instead, that then calls DefWindowProc() for unhandled messages. GetMessage() will dispatch any sent message directly to the window procedure, and DispatchMessage() will dispatch any posted messages to the same window procedure.

    unit JD.ThreadTest;
    
    interface
    
    uses
      System.Classes, Winapi.Messages, Winapi.Windows;
    
    type
      TDataThread = class(TThread)
      private
        FTitle: String;
        FWnd: HWND;
        FWndClass: WNDCLASS;
        procedure HandleMessage(var Message: TMessage);
      protected
        procedure Execute; override;
        procedure DoTerminate; override;
      public
       constructor Create(const Title: String); reintroduce;
      end;
    
    implementation
    
    function DataThreadWndProc(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
    var
      Thread: TDataThread;
      Message: TMessage;
    begin
      if Msg = WM_NCCREATE then
      begin
        Thread := TDataThread(PCREATESTRUCT(lParam)^.lpCreateParams);
        SetWindowLongPtr(Wnd, GWLP_USERDATA, LONG_PTR(Thread));
      end else
        Thread := TDataThread(GetWindowLongPtr(Wnd, GWLP_USERDATA));
    
      if Thread <> nil then
      begin
        Message.Msg := Msg;
        Message.WParam := wParam;
        Message.LParam := lParam;
        Message.Result := 0;
        Thread.HandleMessage(Message);
        Result := Message.Result;
      end else
        Result := DefWindowProc(Wnd, Msg, wParam, lParam);
    end;
    
    constructor TDataThread.Create(const Title: String);
    begin
      inherited Create(True);
      FTitle := Title;
      with FWndClass do
      begin
        Style := 0;
        lpfnWndProc := @DataThreadWndProc;
        cbClsExtra := 0;
        cbWndExtra := 0;
        hInstance := HInstance;
        hIcon := 0;
        hCursor := LoadCursor(0, IDC_ARROW);
        hbrBackground := COLOR_WINDOW;
        lpszMenuName := nil;
        lpszClassName := 'TDataThread';
      end;
    end;
    
    procedure TDataThread.Execute;
    var
      Msg: TMsg;
    begin
      if Winapi.Windows.RegisterClass(FWndClass) = 0 then Exit;
      FWnd := CreateWindow(FWndClass.lpszClassName, PChar(FTitle), WS_OVERLAPPED, 0, 0, 0, 0, 0, 0, HInstance, Self);
      if FWnd = 0 then Exit;
      while GetMessage(Msg, 0, 0, 0) do
      begin
        if Terminated then Exit;
        TranslateMessage(msg);
        DispatchMessage(msg);
      end;
    end;
    
    procedure TDataThread.DoTerminate;
    begin
      if FWnd <> 0 then DestroyWindow(FWnd);
      Winapi.Windows.UnregisterClass(FWndClass.lpszClassName, HInstance);
      inherited;
    end;
    
    procedure TDataThread.HandleMessage(var Message: TMessage);
    begin
      case Message.Msg of
        WM_POWERBROADCAST:
        begin
          // ...
        end;
      else
        Message.Result := DefWindowProc(FWnd, Message.Msg, Message.WParam, Message.LParam);
      end;
    end;
    
    end.
    
    0 讨论(0)
提交回复
热议问题