yonni
yonni

Reputation: 352

Calling the winAPI function in Delphi

I'm taking my first steps in Delphi, I've created a small program that uses the GetSystemPowerStatus function to get battery status information.

To load the function, I used the Winapi.Windows unit.

Everything worked fine, but the EXE file after compilation took up 150 kb.

From what I understand from this post, using the Winapi.Windows unit is the cause of the increase, but I have not found how to access the GetSystemPowerStatus function without using the unit.

Is this possible, and how can it be done?


Well, after Remy Lebeau's answer I did it like this:

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.

But still, after compiling the exe file takes up over 230 kb. Is this the final size, or might it be possible to reduce its size?

Upvotes: 0

Views: 1994

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 598029

If you don't want to use the Winapi.Windows unit, you will just have to declare the function in your own code. See Importing Functions from Libraries in Delphi's documentation.

For example:

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';

This is similar (but different) to how the Winapi.Windows unit declares the function. The main differences being:

  • it splits the declaration and linkage of the function between the interface and implementation sections of the unit
  • it uses an alias for the record type
  • it uses aliases for Win32 data types
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.

Upvotes: 2

Related Questions