在 Delphi 中调用winAPI函数

z9smfwbn  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(758)

我在 Delphi 中迈出了第一步,我创建了一个小程序,使用GetSystemPowerStatus函数来获取电池状态信息。
为了加载函数,我使用了Winapi.Windows单元。
一切正常,但编译后的EXE文件占用了150 kb。
从我从this post中了解到的情况来看,使用Winapi.Windows单元是增加的原因,但我还没有找到如何在不使用该单元的情况下访问GetSystemPowerStatus函数。
这可能吗?怎样才能做到?
在雷米勒博的回答之后,我是这样做的:

program GetBatteryData;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

type
  TSystemPowerStatus = record
  ACLineStatus: Byte;
  BatteryFlag: Byte;
  BatteryLifePercent: Byte;
  SystemStatusFlag: Byte;
  BatteryLifeTime: UInt32;
  BatteryFullLifeTime: UInt32;
end;

var
  PowerState: TSystemPowerStatus;
  Param: String;

function GetSystemPowerStatus(var lpSystemPowerStatus: TSystemPowerStatus): LongBool; stdcall; external 'Kernel32';

procedure ShowHelp;
begin
  Writeln('Usage:');
  Writeln(#32#32'GetBatteryData <query>'#10#13);
  Writeln('queries:'#10#13);
  Writeln(#32#32'ACState'#9'Get State of AC power');
  Writeln(#32#32'LeftPercent'#9'Get the left percent on battery');
  Writeln(#32#32'StateFlag'#9'Get the system flag of battery');
end;

function BatteryStateACPower(ACState: Byte): String;
begin
  case ACState of
    0: Result := 'Not Charged';
    1: Result := 'Charged';
    255: Result := 'Unknown battery state';
  end;
end;

function BatteryStatePercent(LeftPercent: Byte): String;
begin
  case LeftPercent of
    0..100: Result := IntToStr(LeftPercent);
    255: Result := 'Unknown battery state';
  end;
end;

function BatteryStateFlags(Flag: Byte): String;
begin
  case Flag of
    1: Result := 'High';
    2: Result := 'Low';
    4: Result := 'Critical';
    8: Result := 'Charged';
    128: Result := 'No battery in system';
    255: Result := 'Unknown battery state';
  end;
end;

begin
  try
    Param := '';
    if ParamCount = 0 then
    begin
      Writeln('No Parameter'#10#13);
      ShowHelp;
    end else
    begin
      Param := Uppercase(ParamStr(1));
      GetSystemPowerStatus(PowerState);
      if Param = 'ACSTATE' then
          Write(BatteryStateACPower(PowerState.ACLineStatus))
          else
            if Param = 'LEFTPERCENT' then Write(BatteryStatePercent(PowerState.BatteryLifePercent))
              else
                if Param = 'STATEFLAG' then Write(BatteryStateFlags(PowerState.BatteryFlag))
                  else
                    begin
                      Writeln('Invalid Parameter'#10#13);
                      ShowHelp;
                    end;
    end;

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

但是,编译后的exe文件仍然占用了超过230kb的空间。这是最终的大小吗?还是可以减少它的大小?

igsr9ssn

igsr9ssn1#

如果你不想使用Winapi.Windows单元,你只需要在你自己的代码中声明这个函数。参见 Delphi 文档中的从库中导入函数。
例如:

type
  SYSTEM_POWER_STATUS = record
    ACLineStatus: Byte;
    BatteryFlag: Byte;
    BatteryLifePercent: Byte;
    SystemStatusFlag: Byte;
    BatteryLifeTime: UInt32;
    BatteryFullLifeTime: UInt32;
  end; 

function GetSystemPowerStatus(var lpSystemPowerStatus: SYSTEM_POWER_STATUS): LongBool; stdcall; external 'Kernel32';

这与Winapi.Windows单元声明函数的方式类似(但不同)。主要区别在于:

  • 它在单元的interfaceimplementation部分之间拆分函数的声明和链接
  • 它使用记录类型的别名
  • 它使用Win32数据类型的别名
unit Winapi.Windows;

...

interface

...

type
  PSystemPowerStatus = ^TSystemPowerStatus;
  _SYSTEM_POWER_STATUS = record
    ACLineStatus : Byte;
    BatteryFlag : Byte;
    BatteryLifePercent : Byte;
    Reserved1 : Byte;
    BatteryLifeTime : DWORD;
    BatteryFullLifeTime : DWORD;
  end;
  {$EXTERNALSYM _SYSTEM_POWER_STATUS}
  TSystemPowerStatus = _SYSTEM_POWER_STATUS;
  SYSTEM_POWER_STATUS = _SYSTEM_POWER_STATUS;
  {$EXTERNALSYM SYSTEM_POWER_STATUS}

function GetSystemPowerStatus(var lpSystemPowerStatus: TSystemPowerStatus): BOOL; stdcall;
{$EXTERNALSYM GetSystemPowerStatus}

...

const
  ...
  kernel32  = 'kernel32.dll';
  ...

...

implementation

...
function GetSystemPowerStatus; external kernel32 name 'GetSystemPowerStatus';
...

end.

相关问题