📄 apm.pas
字号:
(*
Advanced Power Management (APM) Component 1.0 by Jerry Ryle
This component will intercept the APM messages received by its
parent on run-time. It encapsulates the APM API and allows the
programmer to write APM event handlers easily. The
OnOverrideableSuspendQuery event even allows you to block a
suspend request from the system. For documentation, please read
the accompanying APMHelp.txt
This is of course, absolutely free; however, I will take no
responsiblity for any damage. If you find this component
incredibly useful, I'd be happy to accept donations. ;)
Enjoy, learn, & modify freely. Let me know of any major
improvements.
-- gryle@calpoly.edu
*)
unit APM;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
const
PBT_APMQUERYSUSPEND = 0; {Request for permission to suspend.}
PBT_APMQUERYSUSPENDFAILED = 2; {Suspension request denied.}
PBT_APMSUSPEND = 4; {System is suspending operation.}
PBT_APMRESUMECRITICAL = 6; {Operation resuming after critical suspension.}
PBT_APMRESUMESUSPEND = 7; {Operation resuming after suspension.}
PBT_APMBATTERYLOW = 9; {Battery power is low.}
PBT_APMPOWERSTATUSCHANGE = 10; {Power status has changed.}
PBT_APMOEMEVENT = 11; {OEM-defined event occurred.}
type
TBatteryLowEvent = procedure(Sender: TObject) of object;
TOEMEvent = procedure(Sender: TObject; EventCode : Integer) of object;
TSuspendRequestEvent = procedure(Sender: TObject) of object;
TSuspendEvent = procedure(Sender: TObject) of object;
TOverrideSuspendRequestEvent = procedure(Sender: TObject; var CanSuspend : Boolean) of object;
TSuspendRequestDeniedEvent = procedure(Sender: TObject) of object;
TResumeAfterCriticalEvent = procedure(Sender: TObject) of object;
TResumeAfterSuspendEvent = procedure(Sender: TObject) of object;
TPowerStatusChangeEvent = procedure(Sender: TObject) of object;
TAPM = class(TComponent)
private
APACPowerStatus : String;
APACPowerStatusFlag : Byte;
APBatteryChargeStatus : String;
APBatteryChargeStatusFlag : Byte;
APBatteryLifePercent : Byte;
APBatteryLifeTime : Cardinal;
APBatteryLifeFullTime : Cardinal;
APEnabled : Boolean;
FOnBatteryLow : TBatteryLowEvent;
FOnOEMEvent : TOEMEvent;
FOnSuspend : TSuspendEvent;
FOnSuspendQuery : TSuspendRequestEvent;
FOnOverrideableSuspendQuery : TOverrideSuspendRequestEvent;
FOnSuspendDenied : TSuspendRequestDeniedEvent;
FOnResumeAfterCritical : TResumeAfterCriticalEvent;
FOnResumeAfterSuspend : TResumeAfterSuspendEvent;
FOnPowerStatusChange : TPowerStatusChangeEvent;
OldWndProc : TFarProc;
NewWndProc : Pointer;
procedure HookParent;
procedure UnhookParent;
procedure HookWndProc(var Msg: TMessage);
procedure SetEnabled(value : Boolean);
protected
public
constructor create(AOwner : TComponent); override;
destructor destroy; override;
Function Suspend(Force : Boolean) : Boolean;
Function Hibernate(Force : Boolean) : Boolean;
procedure RefreshAPMStats;
published
{events}
property OnBatteryLow : TBatteryLowEvent read FOnBatteryLow write FOnBatteryLow;
property OnOEMEvent : TOEMEvent read FOnOEMEvent write FOnOEMEvent;
property OnSuspend : TSuspendEvent read FOnSuspend write FOnSuspend;
property OnSuspendQuery : TSuspendRequestEvent read FOnSuspendQuery write FOnSuspendQuery;
property OnOverrideableSuspendQuery : TOverrideSuspendRequestEvent read FOnOverrideableSuspendQuery write FOnOverrideableSuspendQuery;
property OnSuspendDenied : TSuspendRequestDeniedEvent read FOnSuspendDenied write FOnSuspendDenied;
property OnResumeAfterCritical : TResumeAfterCriticalEvent read FOnResumeAfterCritical write FOnResumeAfterCritical;
property OnResumeAfterSuspend : TResumeAfterSuspendEvent read FOnResumeAfterSuspend write FOnResumeAfterSuspend;
property OnPowerStatusChange : TPowerStatusChangeEvent read FOnPowerStatusChange write FOnPowerStatusChange;
{properties}
property ACPowerStatus : String read APACPowerStatus write APACPowerStatus;
property ACPowerStatusFlag : byte read APACPowerStatusFlag write APACPowerStatusFlag;
property BatteryChargeStatus : String read APBatteryChargeStatus write APBatteryChargeStatus;
property BatteryChargeStatusFlag : byte read APBatteryChargeStatusFlag write APBatteryChargeStatusFlag;
property BatteryLifePercent : byte read APBatteryLifePercent write APBatteryLifePercent;
property BatteryLifeTime : Cardinal read APBatteryLifeTime write APBatteryLifeTime;
property BatteryLifeFullTime : Cardinal read APBatteryLifeFullTime write APBatteryLifeFullTime;
property Enabled : Boolean read APEnabled write SetEnabled;
end;
procedure Register;
implementation
constructor TAPM.create(AOwner : TComponent);
begin
inherited;
NewWndProc := Nil;
OldWndProc := Nil;
APEnabled := True;
RefreshAPMStats; {Refresh the Component's properties}
If ComponentState<>[csDesigning] Then HookParent; {Hook the parent's messages}
end;
destructor TAPM.destroy;
begin
UnhookParent; {Unhook the parent's messages}
inherited;
end;
procedure TAPM.SetEnabled(value : Boolean);
begin
APEnabled := value;
end;
procedure TAPM.HookParent;
begin
{Make sure the owner is a windowed control}
if (Owner As TWinControl) = NIL then exit;
{Store the old window procedure}
OldWndProc := TFarProc(GetWindowLong((Owner As TWinControl).Handle, GWL_WNDPROC));
{Create the new window procedure}
NewWndProc := MakeObjectInstance(HookWndProc);
{Hook this procedure onto the parent's}
SetWindowLong((Owner As TWinControl).Handle, GWL_WNDPROC, LongInt(NewWndProc));
end;
procedure TAPM.UnhookParent;
begin
if ( (Owner As TWinControl)<> NIL) And (Assigned(OldWndProc) ) then
{Restore the old procedure}
SetWindowLong((Owner As TWinControl).Handle, GWL_WNDPROC, LongInt(OldWndProc));
if assigned(NewWndProc) then
{free allocated memory}
FreeObjectInstance(NewWndProc);
NewWndProc := NIL;
OldWndProc := NIL;
end;
procedure TAPM.RefreshAPMStats;
var MyPowerStatus : _SYSTEM_POWER_STATUS;
begin
{API call to get APM stats. Look this up in the win32.hlp file}
GetSystemPowerStatus(MyPowerStatus);
APACPowerStatusFlag := MyPowerStatus.ACLineStatus;
Case MyPowerStatus.ACLineStatus Of
0 : APACPowerStatus := 'OffLine';
1 : APACPowerStatus := 'OnLine';
else APACPowerStatus := 'Unknown';
end;
APBatteryChargeStatusFlag := MyPowerStatus.BatteryFlag;
{Convert to a string....I like frills.}
If (MyPowerStatus.BatteryFlag or 1) = 1 Then APBatteryChargeStatus := 'High'
Else If (MyPowerStatus.BatteryFlag or 2) = 2 Then APBatteryChargeStatus := 'Low'
Else If (MyPowerStatus.BatteryFlag or 4) = 4 Then APBatteryChargeStatus := 'Critical'
Else If (MyPowerStatus.BatteryFlag or 8) = 8 Then APBatteryChargeStatus := 'Charging'
Else If (MyPowerStatus.BatteryFlag or 128) = 128 Then APBatteryChargeStatus := 'No Battery'
Else APBatteryChargeStatus := 'Unknown';
APBatteryLifePercent := MyPowerStatus.BatteryLifePercent;
APBatteryLifeTime := MyPowerStatus.BatteryLifeTime;
APBatteryLifeFullTime := MyPowerStatus.BatteryFullLifeTime;
end;
Function TAPM.Suspend(Force : Boolean) : Boolean;
begin
{API Call to suspend the system. Look it up.}
Result := SetSystemPowerState(True,Force);
end;
Function TAPM.Hibernate(Force : Boolean) : Boolean;
begin
{API Call to suspend the system. Look it up.}
Result := SetSystemPowerState(False,Force);
end;
procedure TAPM.HookWndProc(var Msg: TMessage);
{This is the new window message handler}
var CanStandby : Boolean;
begin
CanStandby := True;
if (Owner As TWinControl) = NIL then
Exit;
{First call the parent's handler to make sure we don't mess up someone else's work}
Msg.Result := CallWindowProc(OldWndProc, (Owner As TWinControl).Handle, Msg.Msg, Msg.wParam, Msg.lParam);
{Then handle only one message: WM_POWERBROADCAST (look it up)
We'll be looking at the wparam for specifics}
If (Msg.Msg = WM_POWERBROADCAST) and (APEnabled) Then
Begin
Case Msg.WParam Of
PBT_APMBATTERYLOW : begin
if Assigned(FOnBatteryLow) Then
FOnBatteryLow(self);
end;
PBT_APMOEMEVENT : begin
if Assigned(FOnOEMEvent) Then
FOnOEMEvent(self,Msg.LParam);
end;
PBT_APMPOWERSTATUSCHANGE : begin
if Assigned(FOnPowerStatusChange) Then
FOnPowerStatusChange(self);
end;
PBT_APMQUERYSUSPEND : begin
{check to see if we can possibly override}
If Msg.LParamLo = 1 Then
begin
{if we can, trigger that event}
if Assigned(FOnOverrideableSuspendQuery) then
FOnOverrideableSuspendQuery(self,CanStandby);
If CanStandby = True then Msg.Result := 0
Else Msg.Result := BROADCAST_QUERY_DENY;
end
else if Assigned(FOnSuspendQuery) then
FOnSuspendQuery(self);
end;
PBT_APMQUERYSUSPENDFAILED : begin
if Assigned(FOnSuspendDenied) Then
FOnSuspendDenied(self);
end;
PBT_APMRESUMECRITICAL : begin
if Assigned(FOnResumeAfterCritical) Then
FOnResumeAfterCritical(self);
end;
PBT_APMRESUMESUSPEND : begin
if Assigned(FOnResumeAfterSuspend) Then
FOnResumeAfterSuspend(self);
end;
PBT_APMSUSPEND : begin
if Assigned(FOnSuspend) Then
FOnSuspend(self);
end;
end;
End;
end;
procedure Register; {duh}
begin
RegisterComponents('System', [TAPM]);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -