在 Delphi 中调用 winAPI 函数
Calling the winAPI function in Delphi
我正在 Delphi 迈出第一步,我创建了一个使用 GetSystemPowerStatus
函数获取电池状态信息的小程序。
为了加载函数,我使用了 Winapi.Windows
单元。
一切正常,但编译后的EXE文件占用了150kb
据我了解,使用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。
这是最终尺寸,还是可以缩小尺寸?
如果您不想使用 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
单元声明函数的方式相似(但不同)。主要区别是:
- 它将函数的声明和链接拆分到单元的
interface
和 implementation
部分
- 它使用记录类型的别名
- 它使用 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.
我正在 Delphi 迈出第一步,我创建了一个使用 GetSystemPowerStatus
函数获取电池状态信息的小程序。
为了加载函数,我使用了 Winapi.Windows
单元。
一切正常,但编译后的EXE文件占用了150kb
据我了解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。 这是最终尺寸,还是可以缩小尺寸?
如果您不想使用 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
单元声明函数的方式相似(但不同)。主要区别是:
- 它将函数的声明和链接拆分到单元的
interface
和implementation
部分 - 它使用记录类型的别名
- 它使用 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.