⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apm.pas

📁 封装了电源管理的控件
💻 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 + -