Lazarus
Programming => Operating Systems => Windows CE => Topic started by: sin_dragan on September 19, 2013, 08:53:43 am
-
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&PageIndex=125&Language=3 (http://english.tebyan.net/newindex.aspx?pid=31159&BookID=23937&PageIndex=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.
-
Did you read on MSDN ?
RequestPowerNotifications: http://msdn.microsoft.com/en-us/library/aa932427.aspx
(http://msdn.microsoft.com/en-us/library/aa932427.aspx)
CreateMsgQueue : http://msdn.microsoft.com/en-us/library/bb202792.aspx (http://msdn.microsoft.com/en-us/library/bb202792.aspx)
-
@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 :
typedef MSGQUEUEOPTIONS_OS{
DWORD dwSize;
DWORD dwFlags;
DWORD dwMaxMessages;
DWORD cbMaxMessage;
BOOL bReadAccess;
} MSGQUEUEOPTIONS, FAR* LPMSGQUEUEOPTIONS, *PMSGQUEUEOPTIONS;
to Lazarus :
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
-
@swierzbicki,
Did you made it works ?
It seems to me that :
PMSGQUEUEOPTIONS=^MSGQUEUEOPTIONS;
has to be:
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:
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.
-
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.
-
@chrgra: thanks a lot for your code snipped. It helped really a lot these days when I needed WinCE power management notifications. KUDOZ!