Battery status notification lazarus / 35-Windows CE ---------------------------------------------------------------------- sin_dragan · 2013-09-19 06:53 Hi, I'm writing a application for WinCE 5 and 6 platform. I ve included battery meter, and using device DLL function to get battery status (function GetSystemPowerStatusEx is also performing good) and I m using Timer to call the function. To avoid this I want to intercept a system message or receive a notification from system that the battery info changed and then update the meter on application. Below is the text I found, but it's related to .NET platform. I found this text regarding this problem: http://english.tebyan.net/newindex.aspx?pid=31159&BookID=23937&PageInd ex=125&Language=3 Can you tell me which message I should intercept so that I can get notified of system power change? I see that the coredll.dll has some notification functions, but I'm not sure it's the right direction. Thank you Power Notifications One of the more welcome features of the Power Manager is its ability to notify an application when the power state of the system changes. This ability frees the application from polling the battery state manually to monitor the power. An application can request that the Power Manager send a notification to the application when the power state of the system changes by calling RequestPowerNotifications. The Power Manager then sends the notifications through a message queue that has been previously created by the application. RequestPowerNotifications is prototyped as HANDLE RequestPowerNotifications (HANDLE hMsgQ, DWORD Flags); The first parameter is the handle to a message queue that the application has previously created. The second parameter is a series of flags indicating which notifications the application wants to receive. The flags, which can be ORed together, are as follows: PBT_TRANSITION Receive notifications when the power state changes—for example, when the system goes from On to Suspend. PBT_RESUME Receive notifications when the system resumes. PBT_POWERSTATUSCHANGEReceive notifications when the system transitions between AC and battery power. PBT_POWERINFOCHANGE Receive notifications when the power information, such as the battery level, changes. POWER_NOTIFY_ALL Receive all power notifications. ---------------------------------------------------------------------- bambamns · 2013-09-27 19:48 Did you read on MSDN ? RequestPowerNotifications: http://msdn.microsoft.com/en- us/library/aa932427.aspx CreateMsgQueue : http://msdn.microsoft.com/en-us/library/bb202792.aspx ---------------------------------------------------------------------- swierzbicki · 2013-10-02 09:37 @Bambams, I'm jumping into this topic (I want to detect when my device come out of suspend mode.) I'm trying to convert this structure  : Code: [Select]  typedef MSGQUEUEOPTIONS_OS{     DWORD dwSize;     DWORD dwFlags;     DWORD dwMaxMessages;     DWORD cbMaxMessage;     BOOL bReadAccess;   } MSGQUEUEOPTIONS, FAR* LPMSGQUEUEOPTIONS, *PMSGQUEUEOPTIONS;      to Lazarus :   Code: [Select]MSGQUEUEOPTIONS = record     dwSize : DWORD;     dwFlags : DWORD ;     dwMaxMessages : DWORD ;     cbMaxMessage : DWORD;     bReadAccess : BOOL;   end;   PMSGQUEUEOPTIONS=^MSGQUEUEOPTIONS;  Is this correct ? The next step will be the notification queue creation (guess it will be harder for a noob like me) Thanx ---------------------------------------------------------------------- bambamns · 2013-10-13 03:53 @swierzbicki, Did you made it works ? It seems to me that : Code: [Select]PMSGQUEUEOPTIONS=^MSGQUEUEOPTIONS; has to be: Code: [Select]PMSGQUEUEOPTIONS=@MSGQUEUEOPTIONS; My experience with WinCE is not to let them to go sleep. I use two procedures to keep them in a suspend but not sleep mode: Code: [Select]procedure SystemIdleTimerReset; stdcall; external 'coredll.dll'; procedure SHIdleTimerReset; stdcall; external 'aygshell.dll' name 'SHIdleTimerReset';         Just call them every 15 sec and it will be ok. ---------------------------------------------------------------------- chrgra · 2014-06-01 01:56 I think this will do the trick..... unit Unit1; {$mode objfpc}{$H+} interface uses   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,   Windows, msgqueue, pm; type TMyThread = class(TThread) private   fStatusText: string;   mHandle : Handle;   pHandle : Handle;   mOptions : MSGQUEUEOPTIONS;   mBroadcast : POWER_BROADCAST;   nBytesRead : dword;   dwFlags    : dWord;   counter : integer;   procedure ShowStatus; protected   procedure Execute; override; public   constructor Create(CreateSuspended: boolean); end;   { TForm1 }   TForm1 = class(TForm)     Memo1: TMemo;     procedure FormCreate(Sender: TObject);   private     { private declarations }   public     { public declarations }   end; var   Form1: TForm1; implementation {$R *.lfm} function RequestPowerNotifications(hMsgQ : HANDLE; flags : DWORD) : HANDLE; external kerneldll name 'RequestPowerNotifications'; function StoppowerNotifications(hMsgQ : HANDLE) : HANDLE; external kerneldll name 'StopPowerNotifications'; { TForm1 } procedure TForm1.FormCreate(Sender: TObject); var   MyThread : TMyThread; begin   MyThread := TMyThread.Create(True); // With the True parameter it doesn't start automatically   if Assigned(MyThread.FatalException) then     raise MyThread.FatalException;   memo1.Clear;   // Here the code initialises anything required before the threads starts executing   MyThread.Start; end; procedure TMyThread.ShowStatus; // this method is only called by Synchronize(@ShowStatus) and therefore // executed by the main thread // The main thread can access GUI elements, for example Form1.Caption. begin   form1.Memo1.Append(inttostr(counter) + ' ' + fstatustext); end; procedure TMyThread.Execute; var   newStatus : string; begin   fStatusText := 'TMyThread Starting ...';   Synchronize(@Showstatus);   fStatusText := 'TMyThread Running ...';   while (not Terminated) and (true {any condition required}) do   begin      inc(counter);      Synchronize(@Showstatus);      fstatustext := '';      //sleep(500);  {    function ReadMsgQueue(hMsgQ:HANDLE;                       lpBuffer:LPVOID;                       cbBufferSize:DWORD;                       lpNumberOfBytesRead:LPDWORD;                       dwTimeout:DWORD;                       pdwFlags:LPDWORD):BOOL; external KernelDLL name 'ReadMsgQueue'; // index 112  }      if (not ReadMsgQueue(mHandle,@mBroadcast, sizeof(mBroadcast),  @nBytesRead,50000,@dwFlags) ) then      begin         fstatustext := inttostr(nbytesread) + ' '+ syserrormessage(GetLastError);        // Synchronize(@Showstatus);      end;      case mBroadcast._Message of        PBT_RESUME : fstatustext := 'PBT_RESUME';        PBT_POWERSTATUSCHANGE : fstatustext := 'PBT_POWERSTATUSCHANGE';        PBT_POWERINFOCHANGE: fstatustext := 'PBT_POWERINFOCHANGE';        PBT_TRANSITION: fstatustext := 'PBT_TRANSITION';      end;                                                {    RETAILMSG(1, (TEXT("PBT_TRANSITION")));                                                                               switch( POWER_STATE(pwrStatus.Flags) )                                                                               {                                                                                               case POWER_STATE_ON:                                                                                                               RETAILMSG(1, (TEXT(" POWER_STATE_ON\n")));                                                                                                               break;                                                                                               case POWER_STATE_OFF:                                                                                                               RETAILMSG(1, (TEXT(" POWER_STATE_OFF\n")));                                                                                                               break;                                                                                               case POWER_STATE_CRITICAL:                                                                                                               RETAILMSG(1, (TEXT(" POWER_STATE_CRITICAL\n")));                                                                                                               break;                                                                                               case POWER_STATE_BOOT:                                                                                                               RETAILMSG(1, (TEXT(" POWER_STATE_BOOT\n")));                                                                                                               break;                                                                                               case POWER_STATE_IDLE:                                                                                                               RETAILMSG(1, (TEXT(" POWER_STATE_IDLE\n")));                                                                                                               break;                                                                                               case POWER_STATE_SUSPEND:                                                                                                               RETAILMSG(1, (TEXT(" POWER_STATE_SUSPEND\n")));                                                                                                               break;                                                                                               case POWER_STATE_RESET:                                                                                                               RETAILMSG(1, (TEXT(" POWER_STATE_RESET\n")));                                                                                                               break;                                                                                               default:                                                                                                               break;                                                                               }                                                                               break;                                                                 default:                                                                               break;    }    end;    StopPowerNotifications(mHandle);    CloseMsgQueue(mHandle); end; constructor TMyThread.Create(CreateSuspended: boolean); begin    counter := 0;    mHandle := 0;    pHandle := 0;    mOptions.bReadAccess:=true;    mOptions.cbMaxMessage:=sizeof(mBroadcast);    mOptions.dwSize:=5*sizeof(mBroadcast);    mOptions.dwMaxMessages:=5;    mOptions.dwFlags:=  MSGQUEUE_ALLOW_BROKEN;    FreeOnTerminate := True;    mHandle := CreateMsgQueue('powernotify',@mOptions);   // showmessage('na createmsgqueue '+syserrormessage(getlasterror));    if mHandle = 0 then    begin       showmessage('newmsgqueue failed');      // terminated := true;    end;    pHandle := requestpowernotifications(mHandle,POWER_NOTIFY_ALL);   // showmessage('na requestpowernotifications '+syserrormessage(getlasterror));    if (pHandle = 0) then    begin       showmessage('powernotification failed');      // terminated := true;    end;    inherited Create(CreateSuspended); end; end. ---------------------------------------------------------------------- vincococka · 2015-02-14 16:34 @chrgra: thanks a lot for your code snipped. It helped really a lot these days when I needed WinCE power management notifications. KUDOZ!