【问题标题】:Calling the winAPI function in DelphiDelphi中调用winAPI函数
【发布时间】:2022-07-06 21:16:40
【问题描述】:

我在 Delphi 中迈出了第一步,我创建了一个小程序,它使用 GetSystemPowerStatus 函数来获取电池状态信息。

为了加载函数,我使用了Winapi.Windows 单元。

一切正常,但编译后的EXE文件占用了150 kb。

据我从this post了解到,使用Winapi.Windows单元是增加的原因,但我没有找到如何在不使用单元的情况下访问GetSystemPowerStatus函数。

这可能吗,怎么做?


好吧,在 Remy Lebeau 的回答之后,我这样做了:

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 文件仍然占用超过 230 kb。 这是最终的大小,还是可以减小它的大小?

【问题讨论】:

  • 您已链接到一个问答,该问答解释了如何声明进口,而无需使用为您执行此操作的单元。字面问题的答案是:是的,这是可能的。如果这不是您要问的,请在阅读How to Askedit 提出您的问题。
  • 对,我的意思是问怎么做...我没有注意到我省略了“如何”这个词...固定。
  • 您拥有 Windows 单元的源代码,它准确地向您展示了如何执行此操作。还有关于 external 关键字的文档。如果你有一些自信,你可以自己做。

标签: delphi winapi delphi-11-alexandria


【解决方案1】:

如果您不想使用Winapi.Windows 单元,您只需在自己的代码中声明该函数。请参阅 Delphi 文档中的 Importing Functions from Libraries

例如:

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.

【讨论】:

  • 感谢您的投资!的确,我知道如何设置 SYSTEM_POWER_STATUS 类型,但是我无法从 Windows.pas 单元中弄清楚如何导入该函数。
  • 我已包含来自Winapi.Windows 单元的声明,因此您可以看到它与我建议的比较。
  • 确实,作为一个新手用户,我真的迷失在过多的陈述和指针中......谢谢你的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多