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 a thread. 
Currently, I am using AllocateHWnd(WndMethod) inside of a stand-alone component. When I create an instance of said component in a standard VCL Forms Application, everything works fine, and I receive the WM_POWERBROADCAST message every time, as needed. 
However, when I create an instance of the very same component from within a TThread, I'm no longer receiving this particular Windows message. I'm receiving all kinds of other messages, just not this particular one. 
In my searching for a solution, I've found many resources related to how a Windows Service requires some extra work in order to receive this message. But I'm not using a service, at least not yet. I've also found a couple people mention that a thread needs to have a message loop in order to receive this message, and I've implemented a thread from another answer here, but again, I never receive this particular message.
Below is the complete component how I'm receiving this message, which again works perfectly if this is in a VCL application's main thread. I'm guessing the main thread needs to receive this message and forward it into the thread.
How do I make this receive the WM_POWERBROADCAST message when inside of a TThread? 
unit JD.Power.Monitor;
(*
  JD Power Monitor
  by Jerry Dodge
  Purpose: To monitor the current state of power on the computer, and trigger
  events when different power related changes occur.
  Component: TPowerMonitor
  - Create an instance of TPowerMonitor component
  - Choose desired power settings to get notified of using Settings property
  - Implement event handlers for those events you wish to monitor
  - Component automatically takes care of the rest of the work
*)
interface
uses
  System.Classes, System.SysUtils, System.Generics.Collections,
  Winapi.ActiveX, Winapi.Windows, Winapi.Messages;
type
  TPowerSetting = (psACDCPowerSource, psBatteryPercentage,
    psConsoleDisplayState, psGlobalUserPresence, psIdleBackgroundTask,
    psMonitorPower, psPowerSaving, psPowerSchemePersonality,
    psSessionDisplayStatus, psSessionUserPresence, psSystemAwayMode);
  TPowerSettings = set of TPowerSetting;
  TPowerSource = (poAC, poDC, poHot);
  TPowerDisplayState = (pdOff, pdOn, pdDimmed);
  TPowerUserPresence = (puPresent = 0, puInactive = 2);
  TPowerSavingStatus = (psSaverOff, psSaverOn);
  TPowerAwayMode = (paExiting, paEntering);
  TPowerPersonality = (ppHighPerformance, ppPowerSaver, ppAutomatic);
  TPowerMonitorSettingHandles = array[TPowerSetting] of HPOWERNOTIFY;
  TPowerQueryEndSessionEvent = procedure(Sender: TObject; var EndSession: Boolean) of object;
  TPowerEndSessionEvent = procedure(Sender: TObject) of object;
  TPowerSettingSourceChangeEvent = procedure(Sender: TObject;
    const Src: TPowerSource) of object;
  TPowerSettingBatteryPercentEvent = procedure(Sender: TObject;
    const Perc: Single) of object;
  TPowerSettingDisplayStateEvent = procedure(Sender: TObject;
    const State: TPowerDisplayState) of object;
  TPowerSettingUserPresenceEvent = procedure(Sender: TObject;
    const Presence: TPowerUserPresence) of object;
  TPowerSettingSavingEvent = procedure(Sender: TObject;
    const Status: TPowerSavingStatus) of object;
  TPowerAwayModeEvent = procedure(Sender: TObject;
    const Mode: TPowerAwayMode) of object;
  TPowerPersonalityEvent = procedure(Sender: TObject;
    const Personality: TPowerPersonality) of object;
  TPowerMonitor = class(TComponent)
  private
    FHandle: HWND;
    FSettingHandles: TPowerMonitorSettingHandles;
    FSettings: TPowerSettings;
    FBatteryPresent: Boolean;
    FOnQueryEndSession: TPowerQueryEndSessionEvent;
    FOnEndSession: TPowerEndSessionEvent;
    FOnPowerStatusChange: TNotifyEvent;
    FOnResumeAutomatic: TNotifyEvent;
    FOnResumeSuspend: TNotifyEvent;
    FOnSuspend: TNotifyEvent;
    FOnSourceChange: TPowerSettingSourceChangeEvent;
    FOnBatteryPercent: TPowerSettingBatteryPercentEvent;
    FOnConsoleDisplayState: TPowerSettingDisplayStateEvent;
    FOnGlobalUserPresence: TPowerSettingUserPresenceEvent;
    FOnIdleBackgroundTask: TNotifyEvent;
    FOnMonitorPower: TPowerSettingDisplayStateEvent;
    FOnPowerSavingStatus: TPowerSettingSavingEvent;
    FOnSessionDisplayState: TPowerSettingDisplayStateEvent;
    FOnSessionUserPresence: TPowerSettingUserPresenceEvent;
    FOnAwayMode: TPowerAwayModeEvent;
    FOnPersonality: TPowerPersonalityEvent;
    procedure UnregisterSettings;
    procedure RegisterSettings;
    procedure SetSettings(const Value: TPowerSettings);
  protected
    procedure HandlePowerSetting(const Val: PPowerBroadcastSetting);
    procedure WndMethod(var Msg: TMessage);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Settings: TPowerSettings read FSettings write SetSettings;
    property OnQueryEndSession: TPowerQueryEndSessionEvent
      read FOnQueryEndSession write FOnQueryEndSession;
    property OnEndSession: TPowerEndSessionEvent
      read FOnEndSession write FOnEndSession;
    property OnPowerStatusChange: TNotifyEvent
      read FOnPowerStatusChange write FOnPowerStatusChange;
    property OnResumeAutomatic: TNotifyEvent
      read FOnResumeAutomatic write FOnResumeAutomatic;
    property OnResumeSuspend: TNotifyEvent
      read FOnResumeSuspend write FOnResumeSuspend;
    property OnSuspend: TNotifyEvent
      read FOnSuspend write FOnSuspend;
    property OnSourceChange: TPowerSettingSourceChangeEvent
      read FOnSourceChange write FOnSourceChange;
    property OnBatteryPercent: TPowerSettingBatteryPercentEvent
      read FOnBatteryPercent write FOnBatteryPercent;
    property OnConsoleDisplayState: TPowerSettingDisplayStateEvent
      read FOnConsoleDisplayState write FOnConsoleDisplayState;
    property OnGlobalUserPresence: TPowerSettingUserPresenceEvent
      read FOnGlobalUserPresence write FOnGlobalUserPresence;
    property OnIdleBackgroundTask: TNotifyEvent
      read FOnIdleBackgroundTask write FOnIdleBackgroundTask;
    property OnMonitorPower: TPowerSettingDisplayStateEvent
      read FOnMonitorPower write FOnMonitorPower;
    property OnPowerSavingStatus: TPowerSettingSavingEvent
      read FOnPowerSavingStatus write FOnPowerSavingStatus;
    property OnSessionDisplayState: TPowerSettingDisplayStateEvent
      read FOnSessionDisplayState write FOnSessionDisplayState;
    property OnSessionUserPresence: TPowerSettingUserPresenceEvent
      read FOnSessionUserPresence write FOnSessionUserPresence;
    property OnAwayMode: TPowerAwayModeEvent
      read FOnAwayMode write FOnAwayMode;
    property OnPersonality: TPowerPersonalityEvent
      read FOnPersonality write FOnPersonality;
  end;
implementation
{ TPowerMonitor }
constructor TPowerMonitor.Create(AOwner: TComponent);
begin
  inherited;
  FBatteryPresent:= False;
  FHandle := AllocateHWnd(WndMethod);
end;
destructor TPowerMonitor.Destroy;
begin
  UnregisterSettings;
  DeallocateHWnd(FHandle);
  inherited;
end;
procedure TPowerMonitor.SetSettings(const Value: TPowerSettings);
begin
  UnregisterSettings;
  FSettings := Value;
  RegisterSettings;
end;
procedure TPowerMonitor.WndMethod(var Msg: TMessage);
var
  Handled: Boolean;
begin
  Handled := True;
  case Msg.Msg of
    WM_POWERBROADCAST: begin
      //TODO: Why is this never received when inside of a thread?
      case Msg.WParam of
        PBT_APMPOWERSTATUSCHANGE: begin
          //Power status has changed.
          if Assigned(FOnPowerStatusChange) then
            FOnPowerStatusChange(Self);
        end;
        PBT_APMRESUMEAUTOMATIC: begin
          //Operation is resuming automatically from a low-power state.
          //This message is sent every time the system resumes.
          if Assigned(FOnResumeAutomatic) then
            FOnResumeAutomatic(Self);
        end;
        PBT_APMRESUMESUSPEND: begin
          //Operation is resuming from a low-power state. This message
          //is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered
          //by user input, such as pressing a key.
          if Assigned(FOnResumeSuspend) then
            FOnResumeSuspend(Self);
        end;
        PBT_APMSUSPEND: begin
          //System is suspending operation.
          if Assigned(FOnSuspend) then
            FOnSuspend(Self);
        end;
        PBT_POWERSETTINGCHANGE: begin
          //A power setting change event has been received.
          HandlePowerSetting(PPowerBroadcastSetting(Msg.LParam));
        end;
        else begin
        end;
      end;
    end
    else Handled := False;
  end;
  if Handled then
    Msg.Result := 0
  else
    Msg.Result := DefWindowProc(FHandle, Msg.Msg,
      Msg.WParam, Msg.LParam);
end;
procedure TPowerMonitor.HandlePowerSetting(const Val: PPowerBroadcastSetting);
var
  Pers: TPowerPersonality;
  function ValAsDWORD: DWORD;
  begin
    Result:= DWORD(Val.Data[0]);
  end;
  function ValAsGUID: TGUID;
  begin
    Result:= StringToGUID('{00000000-0000-0000-0000-000000000000}'); //Default
    if SizeOf(TGUID) = Val.DataLength then begin
      Move(Val.Data, Result, Val.DataLength);
    end;
  end;
  function IsVal(G: String): Boolean;
  begin
    Result:= Assigned(Val);
    if Result then
      Result:= IsEqualGUID(StringToGUID(G), Val.PowerSetting);
  end;
  function IsValGuid(G: String): Boolean;
  begin
    Result:= Assigned(Val);
    if Result then
      Result:= IsEqualGUID(StringToGUID(G), ValAsGUID);
  end;
begin
  if IsVal('{5d3e9a59-e9D5-4b00-a6bd-ff34ff516548}') then begin
    //GUID_ACDC_POWER_SOURCE
    if Assigned(FOnSourceChange) then
      FOnSourceChange(Self, TPowerSource(ValAsDWORD));
  end else
  if IsVal('{a7ad8041-b45a-4cae-87a3-eecbb468a9e1}') then begin
    //GUID_BATTERY_PERCENTAGE_REMAINING
    //We assume that if we get this message, that there is a battery connected.
    //Otherwise if this never occurs, then a battery is not present.
    //TODO: How to handle if battery is detached and no longer present?
    FBatteryPresent:= True;
    if Assigned(FOnBatteryPercent) then
      FOnBatteryPercent(Self, ValAsDWORD);
  end else
  if IsVal('{6fe69556-704a-47a0-8f24-c28d936fda47}') then begin
    //GUID_CONSOLE_DISPLAY_STATE
    if Assigned(FOnConsoleDisplayState) then
      FOnConsoleDisplayState(Self, TPowerDisplayState(ValAsDWORD));
  end else
  if IsVal('{786E8A1D-B427-4344-9207-09E70BDCBEA9}') then begin
    //GUID_GLOBAL_USER_PRESENCE
    if Assigned(FOnGlobalUserPresence) then
      FOnGlobalUserPresence(Self, TPowerUserPresence(ValAsDWORD));
  end else
  if IsVal('{515c31d8-f734-163d-a0fd-11a08c91e8f1}') then begin
    //GUID_IDLE_BACKGROUND_TASK
    if Assigned(FOnIdleBackgroundTask) then
      FOnIdleBackgroundTask(Self);
  end else
  if IsVal('{02731015-4510-4526-99e6-e5a17ebd1aea}') then begin
    //GUID_MONITOR_POWER_ON
    if Assigned(FOnMonitorPower) then
      FOnMonitorPower(Self, TPowerDisplayState(ValAsDWORD));
  end else
  if IsVal('{E00958C0-C213-4ACE-AC77-FECCED2EEEA5}') then begin
    //GUID_POWER_SAVING_STATUS
    if Assigned(FOnPowerSavingStatus) then
      FOnPowerSavingStatus(Self, TPowerSavingStatus(ValAsDWORD));
  end else
  if IsVal('{245d8541-3943-4422-b025-13A784F679B7}') then begin
    //GUID_POWERSCHEME_PERSONALITY
    if IsValGuid('{8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}') then begin
      Pers:= TPowerPersonality.ppHighPerformance;
    end else
    if IsValGuid('{a1841308-3541-4fab-bc81-f71556f20b4a}') then begin
      Pers:= TPowerPersonality.ppPowerSaver;
    end else
    if IsValGuid('{381b4222-f694-41f0-9685-ff5bb260df2e}') then begin
      Pers:= TPowerPersonality.ppAutomatic;
    end else begin
      //TODO: Handle unrecognized GUID
      Pers:= TPowerPersonality.ppAutomatic;
    end;
    if Assigned(FOnPersonality) then
      FOnPersonality(Self, Pers);
  end else
  if IsVal('{2B84C20E-AD23-4ddf-93DB-05FFBD7EFCA5}') then begin
    //GUID_SESSION_DISPLAY_STATUS
    if Assigned(FOnSessionDisplayState) then
      FOnSessionDisplayState(Self, TPowerDisplayState(ValAsDWORD));
  end else
  if IsVal('{3C0F4548-C03F-4c4d-B9F2-237EDE686376}') then begin
    //GUID_SESSION_USER_PRESENCE
    if Assigned(FOnSessionUserPresence) then
      FOnSessionUserPresence(Self, TPowerUserPresence(ValAsDWORD));
  end else
  if IsVal('{98a7f580-01f7-48aa-9c0f-44352c29e5C0}') then begin
    //GUID_SYSTEM_AWAYMODE
    if Assigned(FOnAwayMode) then
      FOnAwayMode(Self, TPowerAwayMode(ValAsDWORD));
  end else begin
    //TODO: Handle Unrecognized GUID
  end;
end;
function PowerSettingGUID(const Setting: TPowerSetting): TGUID;
begin
  case Setting of
    psACDCPowerSource: Result:= StringToGUID('{5d3e9a59-e9D5-4b00-a6bd-ff34ff516548}');
    psBatteryPercentage: Result:= StringToGUID('{a7ad8041-b45a-4cae-87a3-eecbb468a9e1}');
    psConsoleDisplayState: Result:= StringToGUID('{6fe69556-704a-47a0-8f24-c28d936fda47}');
    psGlobalUserPresence: Result:= StringToGUID('{786E8A1D-B427-4344-9207-09E70BDCBEA9}');
    psIdleBackgroundTask: Result:= StringToGUID('{515c31d8-f734-163d-a0fd-11a08c91e8f1}');
    psMonitorPower: Result:= StringToGUID('{02731015-4510-4526-99e6-e5a17ebd1aea}');
    psPowerSaving: Result:= StringToGUID('{E00958C0-C213-4ACE-AC77-FECCED2EEEA5}');
    psPowerSchemePersonality: Result:= StringToGUID('{245d8541-3943-4422-b025-13A784F679B7}');
    psSessionDisplayStatus: Result:= StringToGUID('{2B84C20E-AD23-4ddf-93DB-05FFBD7EFCA5}');
    psSessionUserPresence: Result:= StringToGUID('{3C0F4548-C03F-4c4d-B9F2-237EDE686376}');
    psSystemAwayMode: Result:= StringToGUID('{98a7f580-01f7-48aa-9c0f-44352c29e5C0}');
  end;
end;
procedure TPowerMonitor.RegisterSettings;
var
  V: TPowerSetting;
begin
  for V := Low(TPowerSetting) to High(TPowerSetting) do begin
    if V in FSettings then begin
      FSettingHandles[V]:= RegisterPowerSettingNotification(FHandle,
        PowerSettingGUID(V), 0);
    end;
  end;
end;
procedure TPowerMonitor.UnregisterSettings;
var
  V: TPowerSetting;
begin
  for V := Low(TPowerSetting) to High(TPowerSetting) do begin
    if V in FSettings then begin
      UnregisterPowerSettingNotification(FSettingHandles[V]);
    end;
  end;
end;
end.
Further, based on the other answer as mentioned, here's how I'm attempting to capture this message using only a thread, although I'm sure this is not actually what I need since WM_POWERBROADCAST is not a posted message:
unit JD.ThreadTest;
interface
uses
  System.Classes, Winapi.Messages, Winapi.Windows;
type
  TDataThread = class(TThread)
  private
    FTitle: String;
    FWnd: HWND;
    FWndClass: WNDCLASS;
    procedure HandlePower(AMsg: TMsg);
  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 := @DefWindowProc;
    cbClsExtra := 0;
    cbWndExtra := 0;
    hInstance := HInstance;
    hIcon := 0;
    hCursor := LoadCursor(0, IDC_ARROW);
    hbrBackground := COLOR_WINDOW;
    lpszMenuName := nil;
    lpszClassName := PChar(Self.ClassName);
  end;
end;
procedure TDataThread.Execute;
var
  Msg: TMsg;
begin
  if Winapi.Windows.RegisterClass(FWndClass) = 0 then Exit;
  FWnd := CreateWindow(FWndClass.lpszClassName, PChar(FTitle), WS_DLGFRAME,
    0, 0, 698, 517, 0, 0, HInstance, nil);
  if FWnd = 0 then Exit;
  while GetMessage(Msg, FWnd, 0, 0) = True do begin
    if Terminated then Break;
    case Msg.message of
      WM_POWERBROADCAST: begin
        HandlePower(Msg); //Never receives this message
      end;
      else begin
        TranslateMessage(msg);
        DispatchMessage(msg)
      end;
    end;
  end;
end;
procedure TDataThread.HandlePower(AMsg: TMsg);
begin
end;
procedure TDataThread.DoTerminate;
begin
  if FWnd <> 0 then DestroyWindow(FWnd);
  Winapi.Windows.UnregisterClass(PChar(Self.ClassName), FWndClass.hInstance);
  inherited;
end;
end.
PS: The end goal is to make this component re-usable, and to be using it inside of a thread, which will be spawned inside of a service.
EDIT
Just to show some perspective, here's a screenshot of my results, when I put my computer into sleep mode. The form on the left is my 100% working UI application, without any worker thread. It receives many messages through the WM_POWERBROADCAST message. The one on the right is where I attempt to capture this message inside of a thread - updated with the code below in Remy's answer. 
Obviously the "Power Setting" specific messages are not received, because I haven't called RegisterPowerSettingNotification - but there are other cases when I should still receive this message regardless, such as PBT_APMSUSPEND.
unit JD.ThreadTest;
interface
uses
  System.Classes, System.SysUtils, Winapi.Messages, Winapi.Windows;
type
  TMessageEvent = procedure(Sender: TObject; Message: TMessage) of object;
  TDataThread = class(TThread)
  private
    FTitle: String;
    FWnd: HWND;
    FWndClass: WNDCLASS;
    FOnMessage: TMessageEvent;
    FMsg: TMessage;
    procedure HandleMessage(var Message: TMessage);
  protected
    procedure Execute; override;
    procedure DoTerminate; override;
    procedure DoOnMessage;
  public
    constructor Create(const Title: String); reintroduce;
    property OnMessage: TMessageEvent read FOnMessage write FOnMessage;
  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_DLGFRAME, 0, 0, 698, 517, 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.DoOnMessage;
begin
  if Assigned(FOnMessage) then
    FOnMessage(Self, FMsg);
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
  FMsg:= Message;
  Synchronize(DoOnMessage);
  case Message.Msg of
    WM_POWERBROADCAST:
    begin
    end;
  else
    Message.Result := DefWindowProc(FWnd, Message.Msg, Message.WParam, Message.LParam);
  end;
end;
end.
