How to receive WM_POWERBROADCAST inside of a thread?
Описание проблемы
Пользователь сталкивает с трудностями в получении уведомления WM_POWERBROACAST от Windows внутри созданного потока. В стандартном приложении VCL Forms, работающем в главном потоке, уведомление получается корректно. Однако, когда компонент, обрабатывающий это сообщение, создается внутри потока, WM_POWERBROACAST не доставляется.
Контекст запроса
Предоставлен исходный код компонента TPowerMonitor, который обрабатывает WM_POWERBROACAST и связанные настройки питания. В коде используется AllocateHWnd для создания окна, в оконной процедуре которого обрабатывается сообщение. В потоке TDataThread также пытается обработать это сообщение, но безуспешно.
Подтвержденный ответ
Для получения WM_POWERBROACAST в потоке необходимо создать окно с оконной процедурой, которая будет обрабатывать это сообщение. В Windows, WM_POWERBROACAST не является посланным сообщением, его необходимо обрабатывать через оконную процедуру. Важно, чтобы поток имел цикл обработки сообщений, например, с помощью функций GetMessage, TranslateMessage, DispatchMessage.
Альтернативный ответ
Код, предоставленный в вопросе, пытается обработать WM_POWERBROACAST внутри потока, но использует DefWindowProc для необработанных сообщений, что неверно. Вместо этого, следует зарегистрировать собственную оконную процедуру с помощью RegisterClass и затем обработать WM_POWERBROACAST внутри этой процедуры.
Шаги для решения проблемы:
Создать оконную процедуру для обработки WM_POWERBROACAST.
В конструкторе потока TDataThread зарегистрировать эту оконную процедуру с помощью RegisterClass.
В оконной процедуре обработать WM_POWERBROACAST.
В цикле обработки сообщений потока Execute использовать GetMessage, TranslateMessage, DispatchMessage для обработки сообщений.
unit TDataThread;
interface
uses
System.Classes, Winapi.Windows, Winapi.Messages;
type
TDataThread = class(TThread)
private
FTitle: string;
FWndClass: TWndClass;
FWndProc: TWndProc;
FWnd: HWND;
procedure HandlePowerMessage(var Msg: TMessage);
protected
procedure Execute; override;
procedure DoTerminate; override;
public
constructor Create(const Title: string); reintroduce;
end;
implementation
constructor TDataThread.Create(const Title: string);
begin
inherited Create(True);
FTitle := Title;
with FWndClass do
begin
Style := 0;
lpfnWndProc := @HandlePowerMessage;
cbWndExtra := 0;
cbClsExtra := 0;
hbrBackground := COLOR_WINDOW;
hIcon := LoadIcon(NULL, IDI_INFORMATION);
hCursor := LoadCursor(NULL, IDC_ARROW);
hInstance := HInstance;
lpszClassName := PChar(Self.ClassName);
end;
end;
function TDataThread.HandlePowerMessage(var Msg: TMessage): LRESULT; stdcall;
begin
if Msg.Msg = WM_POWERBROACAST then
begin
// Обработка сообщения WM_POWERBROACAST
Result := 0;
end
else
Result := DefWindowProc(Msg.HWnd, Msg.Msg, Msg.WParam, Msg.LParam);
end;
procedure TDataThread.Execute;
var
Msg: TMsg;
begin
if RegisterClass(FWndClass) = 0 then
Exit;
FWnd := CreateWindow(FWndClass.lpszClassName, PChar(FTitle), WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, 0, 0, HInstance, nil);
if FWnd = 0 then
Exit;
while GetMessage(Msg, FWnd, 0, 0) > 0 do
begin
if Terminated then
Break;
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end;
procedure TDataThread.DoTerminate;
begin
if FWnd > 0 then
DestroyWindow(FWnd);
UnregisterClass(FWndClass.lpszClassName, HInstance);
end;
end;
Заключение
Следует заметить, что для корректной работы WM_POWERBROACAST необходимо, чтобы поток имел цикл обработки сообщений, и что AllocateHWnd не является подходящим способом для создания окна в потоке, предназначенном для приема этого сообщения.
Пользователь пытается получить уведомление `WM_POWERBROADCAST` от Windows внутри созданного потока в среде разработки VCL Forms.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.