The Road to Delphi – a Blog about programming

Delphi – Lazarus – Delphi Prism


5 Comments

Introducing TSMBIOS

logoA few weeks ago I started a new project called TSMBIOS, this is a library which allows access the SMBIOS using the Object Pascal language (Delphi or Free Pascal).

What is the SMBIOS?

SMBIOS stands for System Management BIOS , this standard is tightly related and developed by the DMTF (Desktop Management Task Force).

The SMBIOS contains a description of the system’s hardware components, the information stored in the SMBIOS typically includes system manufacturer, model name, serial numbers, BIOS version, asset tag, processors, ports, device memory installed and so on.

Note : The amount and accuracy of the SMBIOS information depends on the computer manufacturer.

Which are the advantages of use the SMBIOS?

  • You can retrieve the information without having to probe for the actual hardware. this is a good point in terms of speed and safeness.
  • The SMBIOS information is very well documented.
  • You can avoid the use of undocumented functions to get hardware info (for example the RAM type and manufacturer).
  • Useful for create a Hardware ID (machine fingerprint).

How it works?

The BIOS typically populates the SMBIOS structures at system boot time, and is not in control when the OS is running. Therefore, dynamically changing data is rarely represented in SMBIOS tables.

The SMBIOS Entry Point is located somewhere between the addresses 0xF0000 and 0xFFFFF, in early Windows systems (Win95, Win98) it was possible access this space address directly, but after with the introduction of the NT Systems and the new security changes the BIOS was accessible through section \Device\PhysicalMemory, but this last method was disabled as well in Windows Server 2003 Service Pack 1, and replaced with 2 new WinApi functions the EnumSystemFirmwareTables and GetSystemFirmwareTable, Additionally  the WMI supports reading the entire contents of SMBIOS data i using the MSSMBios_RawSMBiosTables class inside of the root\wmi namespace.

Note : you can find more information about the SMBIOS Support in Windows on this link.

The TSMBIOS can be compiled using a WinApi mode (uses the GetSystemFirmwareTable function) or using the WMI Mode (uses the MSSMBios_RawSMBiosTables class)

If you uses the WinApi Mode you  don’t need use COM and the final size of the Application will be smaller, but the WinAPI functions was introduced in Windows Vista and Windows XP x64 (So in Windows Xp x86 will fail). Otherwise using the WMI mode you will need use COM (CoInitialize and CoUninitialize), but also you will get two additional advantages 1) The WMI will work even in Windows Xp x86 systems, 2) You can read then SMBIOS data of local and remote computers.

In order to use the TSMBIOS in your application only you must add the uSMBIOS unit to your uses clause, then create a instance for the TSMBios class using the proper constructor

// Default constructor, used for populate the TSMBIOS class  using the current mode selected (WMI or WinApi)
constructor Create; overload;
// Use this constructor to load the SMBIOS data from a previously saved file.
constructor Create(const FileName : string); overload;
{$IFDEF USEWMI}
// Use this constructor to read the SMBIOS from a remote machine.
constructor Create(const RemoteMachine, UserName, Password : string); overload;
{$ENDIF}

and finally use the property which expose the SMBIOS info which you need. In this case as is show in the sample code the BatteryInformation property is used to get all the info of the batteries installed on the system.

{$APPTYPE CONSOLE}

uses
  Classes,
  SysUtils,
  uSMBIOS in '..\..\Common\uSMBIOS.pas';

procedure GetBatteryInfo;
Var
  SMBios : TSMBios;
  LBatteryInfo  : TBatteryInformation;
begin
  SMBios:=TSMBios.Create;
  try
      WriteLn('Battery Information');
      WriteLn('-------------------');
      if SMBios.HasBatteryInfo then
      for LBatteryInfo in SMBios.BatteryInformation do
      begin
        WriteLn('Location           '+LBatteryInfo.GetLocationStr);
        WriteLn('Manufacturer       '+LBatteryInfo.GetManufacturerStr);
        WriteLn('Manufacturer Date  '+LBatteryInfo.GetManufacturerDateStr);
        WriteLn('Serial Number      '+LBatteryInfo.GetSerialNumberStr);
        WriteLn('Device Name        '+LBatteryInfo.GetDeviceNameStr);
        WriteLn('Device Chemistry   '+LBatteryInfo.GetDeviceChemistry);
        WriteLn(Format('Design Capacity    %d mWatt/hours',[LBatteryInfo.RAWBatteryInfo.DesignCapacity*LBatteryInfo.RAWBatteryInfo.DesignCapacityMultiplier]));
        WriteLn(Format('Design Voltage     %d mVolts',[LBatteryInfo.RAWBatteryInfo.DesignVoltage]));
        WriteLn('SBDS Version Number  '+LBatteryInfo.GetSBDSVersionNumberStr);
        WriteLn(Format('Maximum Error in Battery Data %d%%',[LBatteryInfo.RAWBatteryInfo.MaximumErrorInBatteryData]));
        WriteLn(Format('SBDS Version Number           %.4x',[LBatteryInfo.RAWBatteryInfo.SBDSSerialNumber]));
        WriteLn('SBDS Manufacture Date  '+LBatteryInfo.GetSBDSManufactureDateStr);
        WriteLn('SBDS Device Chemistry  '+LBatteryInfo.GetSBDSDeviceChemistryStr);
        WriteLn(Format('OEM Specific                  %.8x',[LBatteryInfo.RAWBatteryInfo.OEM_Specific]));
        WriteLn;
      end
      else
      Writeln('No Battery Info was found');
  finally
   SMBios.Free;
  end;
end;

begin
 try
    GetBatteryInfo;
 except
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.

TSMBIOS Features

  • Source Full documented compatible with the help insight feature, available since Delphi 2005.
  • Supports SMBIOS Version from 2.1 to 2.7.1
  • Supports Delphi 5, 6, 7, 2005, BDS/Turbo 2006 and RAD Studio 2007, 2009, 2010, XE, XE2, XE3, XE4.
  • Compatible with FPC 2.6.0 (Windows and Linux)
  • SMBIOS Data can be obtained using WinApi, WMI or loading a saved SMBIOS dump
  • SMBIOS Data can be saved and load to a file
  • SMBIOS Data can be obtained from remote machines

SMBIOS Tables supported

The TSMBIOS is a Open Source project is hosted in the code google site.


1 Comment

How customize the fonts of a TActionMainMenuBar and TPopupActionBar with the Vcl Styles Enabled

This week I received two emails from different Delphi developers asking about : How customize the fonts of a TActionMainMenuBar and TPopupActionBar with the Vcl Styles Enabled? Also a question about the same topic was asked in StackOverflow.

This post shows how this task can be done.

In order to change the font and size of a TActionMainMenuBar and a TPopupActionBar in a VCL application you must use the Screen.MenuFont property like so.

  Screen.MenuFont.Name := 'Impact';
  Screen.MenuFont.Size := 12;

But if the Vcl Styles are enabled these changes are not reflected (This is because the Vcl Styles uses the fonts defined in style file).

Now if you want change the font type or font size of the Vcl Styles elements related to the menus like MenuItemTextNormal, MenuItemTextHot and so on, you will use the Style Designer and set font values which you want.

But unfortunately this will not work either, I mean even if you edit the fonts of the Vcl Style file, the changes are not reflected in the Menus components (or others controls). The reason for this is that the Vcl Styles Engine ignores the fonts types and font size defined in the style file. and just use the font color value to draw the text of the controls.

Note : The font used by the Vcl Styles is Tahoma and the Size is 8.

So what is the solution for customize the font of a TActionMainMenuBar component? A possible workaround is create a new Action Bar Style and also create a new TCustomMenuItem and TCustomMenuButton to override the DrawText method and draw your self the menu text using the Screen.MenuFont values, the good news are which since now, you can find a implementation of a new Action Bar Style in the Vcl.PlatformVclStylesActnCtrls unit (which is part of the Vcl Styles Utils project) which allows you to modify the font of the TActionMainMenuBar and TPopupActionBar components.

So to use this new Action Bar Style, just add the Vcl.PlatformVclStylesActnCtrls unit to your project and then assign the new style to your Action Manager like so :

  ActionManager1.Style:=PlatformVclStylesStyle;

And now when you run your app the TActionMainMenuBar and TPopupActionBar will use the font defined in the Screen.MenuFont property.


5 Comments

Exploring Delphi XE3 – Accesing Windows Sensors from VCL (and Firemonkey)

Delphi XE3 includes support for sensors in OSX and Windows, the classes and types necessaries to access such devices are defined as abstract classes in the System.Sensors unit and implemented in the System.Mac.Sensors unit for OSX and System.Win.Sensors unit for Windows. This article will focus in the Windows side implementation.

Windows 7 introduces the Sensor and Location API, which unifies the access to hardware devices like GPS, Light Sensors, Biometric Sensors and so on. Avoiding the need of use a specific dlls or SDK to control the sensor devices. this API is condensed on these files which are part of the Windows 7 Software Development Kit (SDK).

File name Description
Sensorsapi.h The main header file for the Sensor API. This header file contains the interface definitions.
Sensors.h The header file that contains definitions of platform-defined constants.
Initguid.h The header file that contains definitions for controlling GUID initialization.{
FunctionDiscoveryKeys.h The header file that defines device ID property keys that are required when you connect to logical sensors.
Sensorsapi.lib A static library that contains GUID definitions for the Sensor API.
PortableDeviceGuids.lib A static library that contains GUID definitions for Windows Portable Devices objects.

All these headers was translated by Embarcadero and included as part of the RTL of the Delphi XE3, these are the units which contains such translations Winapi.Portabledevicetypes, Winapi.Sensors, Winapi.Sensorsapi, Winapi.Locationapi. Fortunately an additional set of classes was added to wrap the sensors API, these classes are defined and implemented in the System.Sensors and System.Win.Sensors units. So you don’t need access directly interfaces like ISensor or ISensorManager to gain access to the sensors.

Enumerating Sensors

In order to gain access to the sensors you must get an instance to the TSensorManager class and then call the Activate method, from here you can iterate over the Sensors property or use the GetSensorsByCategory method to get an array of TSensor objects filtered by an TSensorCategory.

var
  LManager : TSensorManager;
  LSensors : TSensorArray;
  LSensor  : TCustomSensor;
begin
  LManager := TSensorManager.Current;
  LManager.Activate;
  try
    LSensors  := LManager.GetSensorsByCategory(TSensorCategory.Location);
    for LSensor in LSensors do
    begin
      //do something
    end;
  finally
    LManager.Deactivate;
  end;
end;

All the sensors share a common set of properties like the Manufacturer, Model, Serial number and so on. So extending the above code you can access such properties on this way :

var
  LManager : TSensorManager;
  LSensors : TSensorArray;
  LSensor  : TCustomSensor;
begin
  LManager := TSensorManager.Current;
  LManager.Activate;
  try
    LSensors  := LManager.GetSensorsByCategory(TSensorCategory.Location);
    for LSensor in LSensors do
    begin
      Writeln(Format('Description  : %s', [LSensor.Description]));
      Writeln(Format('Manufacturer : %s', [LSensor.Manufacturer]));
      Writeln(Format('Model        : %s', [LSensor.Model]));
      Writeln(Format('Serial No    : %s', [LSensor.SerialNo]));
      Writeln(Format('State        : %s', [GetEnumName(TypeInfo(TSensorState),integer(LSensor.State))]));
      Writeln(Format('TimeStamp    : %s', [DatetoStr(LSensor.TimeStamp)]));
      Writeln(Format('Unique ID    : %s', [LSensor.UniqueID]));
    end;
  finally
    LManager.Deactivate;
  end;
end;

Now depending of the sensor category, you must cast the TCustomSensor to the proper specific class, in this case we will use the TCustomLocationSensor class.

var
  LManager : TSensorManager;
  LSensors : TSensorArray;
  LSensor  : TCustomSensor;
  LLocationSensor          : TCustomLocationSensor;
begin
  LManager := TSensorManager.Current;
  LManager.Activate;
  try
    LSensors  := LManager.GetSensorsByCategory(TSensorCategory.Location);
    for LSensor in LSensors do
    begin
      Writeln(Format('Description  : %s', [LSensor.Description]));
      Writeln(Format('Manufacturer : %s', [LSensor.Manufacturer]));
      Writeln(Format('Model        : %s', [LSensor.Model]));
      Writeln(Format('Serial No    : %s', [LSensor.SerialNo]));
      Writeln(Format('State        : %s', [GetEnumName(TypeInfo(TSensorState),integer(LSensor.State))]));
      Writeln(Format('TimeStamp    : %s', [DatetoStr(LSensor.TimeStamp)]));
      Writeln(Format('Unique ID    : %s', [LSensor.UniqueID]));

        LLocationSensor:=LSensor as TCustomLocationSensor;
        LLocationSensor.Start;
        try
          Writeln(Format('Sensor Type       : %s', [GetEnumName(TypeInfo(TLocationSensorType),integer(LLocationSensor.SensorType))]));
          Writeln(Format('Authorized        : %s', [GetEnumName(TypeInfo(TAuthorizationType),integer(LLocationSensor.Authorized))]));
          Writeln(Format('Accuracy          : %n', [LLocationSensor.Accuracy]));
          Writeln(Format('Distance          : %n', [LLocationSensor.Distance]));
          Writeln(Format('Power Consumption : %s', [GetEnumName(TypeInfo(TPowerConsumption),integer(LLocationSensor.PowerConsumption))]));
          Writeln(Format('Location Change   : %s', [GetEnumName(TypeInfo(TLocationChangeType),integer(LLocationSensor.LocationChange))]));
          if TCustomLocationSensor.TProperty.Latitude in  LLocationSensor.AvailableProperties then
          Writeln(Format('Latitude          : %n', [LLocationSensor.Latitude]));
          if TCustomLocationSensor.TProperty.Longitude in  LLocationSensor.AvailableProperties then
          Writeln(Format('Longitude         : %n', [LLocationSensor.Longitude]));
          if TCustomLocationSensor.TProperty.ErrorRadius in  LLocationSensor.AvailableProperties then
          Writeln(Format('Error Radius      : %n', [LLocationSensor.ErrorRadius]));
          if TCustomLocationSensor.TProperty.Altitude in  LLocationSensor.AvailableProperties then
          Writeln(Format('Altitude          : %n', [LLocationSensor.Altitude]));
          if TCustomLocationSensor.TProperty.Speed in  LLocationSensor.AvailableProperties then
          Writeln(Format('Speed             : %n', [LLocationSensor.Speed]));
          if TCustomLocationSensor.TProperty.TrueHeading in  LLocationSensor.AvailableProperties then
          Writeln(Format('True Heading      : %n', [LLocationSensor.TrueHeading]));
          if TCustomLocationSensor.TProperty.MagneticHeading in  LLocationSensor.AvailableProperties then
          Writeln(Format('Magnetic Heading  : %n', [LLocationSensor.MagneticHeading]));
          if TCustomLocationSensor.TProperty.Address1 in  LLocationSensor.AvailableProperties then
          Writeln(Format('Address1          : %s', [LLocationSensor.Address1]));
          if TCustomLocationSensor.TProperty.Address2 in  LLocationSensor.AvailableProperties then
          Writeln(Format('Address2          : %s', [LLocationSensor.Address2]));
          if TCustomLocationSensor.TProperty.City in  LLocationSensor.AvailableProperties then
          Writeln(Format('City              : %s', [LLocationSensor.City]));
          if TCustomLocationSensor.TProperty.StateProvince in  LLocationSensor.AvailableProperties then
          Writeln(Format('State/Province    : %s', [LLocationSensor.StateProvince]));
          if TCustomLocationSensor.TProperty.PostalCode in  LLocationSensor.AvailableProperties then
          Writeln(Format('Postal Code       : %s', [LLocationSensor.PostalCode]));
          if TCustomLocationSensor.TProperty.CountryRegion in  LLocationSensor.AvailableProperties then
          Writeln(Format('Country Region    : %s', [LLocationSensor.CountryRegion]));
        finally
          LLocationSensor.Stop;
        end;
        Writeln;
    end;
  finally
    LManager.Deactivate;
  end;

end;

Not all the properties exposed by the Windows sensors and Location API are mapped directly in the TCustomSensors class, so to access this additional data you can use the HasCustomData and CustomData indexed properties and use one of the values defined in the Winapi.Sensors unit which is the translation of the Sensors.h header file.

  if LLocationSensor.HasCustomData[SENSOR_DATA_TYPE_SATELLITES_USED_COUNT]  then
    Writeln(Format('Satellites used : %d', [ Integer(LLocationSensor.CustomData[SENSOR_DATA_TYPE_SATELLITES_USED_COUNT])]));

Sample Application

Check this sample console application which enumerates all the sensors and properties.

{$APPTYPE CONSOLE}

uses
  System.TypInfo,
  System.Sensors,
  System.SysUtils;

procedure EnumerateSensors;
var
  LManager : TSensorManager;
  LCustomLocationSensor          : TCustomLocationSensor;
  LCustomLightSensor             : TCustomLightSensor;
  LCustomEnvironmentalSensor     : TCustomEnvironmentalSensor;
  LCustomMotionSensor            : TCustomMotionSensor;
  LCustomOrientationSensor       : TCustomOrientationSensor;
  LCustomMechanicalSensor        : TCustomMechanicalSensor;
  LCustomElectricalSensor        : TCustomElectricalSensor;
  LCustomBiometricSensor         : TCustomBiometricSensor;
  LCustomScannerSensor           : TCustomScannerSensor;
  LSensor  : TCustomSensor;
  i        : Integer;
begin
  LManager := TSensorManager.Current;
  LManager.Activate;
  //LSensors  := LManager.GetSensorsByCategory(TSensorCategory.Location);
  if LManager.Count > 0 then
  for i := 0 to LManager.Count-1 do
  begin
    Writeln(Format('Sensor %d',[i+1]));
    Writeln('--------');

    LSensor:= LManager.Sensors[i];
    Writeln(Format('Category     : %s', [GetEnumName(TypeInfo(TSensorCategory),integer(LSensor.Category))]));
    Writeln(Format('Description  : %s', [LSensor.Description]));
    Writeln(Format('Manufacturer : %s', [LSensor.Manufacturer]));
    Writeln(Format('Model        : %s', [LSensor.Model]));
    Writeln(Format('Serial No    : %s', [LSensor.SerialNo]));
    Writeln(Format('State        : %s', [GetEnumName(TypeInfo(TSensorState),integer(LSensor.State))]));
    Writeln(Format('TimeStamp    : %s', [DatetoStr(LSensor.TimeStamp)]));
    Writeln(Format('Unique ID    : %s', [LSensor.UniqueID]));

    case LSensor.Category of

      TSensorCategory.Location :
      begin
        LCustomLocationSensor:=LSensor as TCustomLocationSensor;
        LCustomLocationSensor.Start;
        Writeln(Format('Sensor Type       : %s', [GetEnumName(TypeInfo(TLocationSensorType),integer(LCustomLocationSensor.SensorType))]));
        Writeln(Format('Authorized        : %s', [GetEnumName(TypeInfo(TAuthorizationType),integer(LCustomLocationSensor.Authorized))]));
        Writeln(Format('Accuracy          : %n', [LCustomLocationSensor.Accuracy]));
        Writeln(Format('Distance          : %n', [LCustomLocationSensor.Distance]));
        Writeln(Format('Power Consumption : %s', [GetEnumName(TypeInfo(TPowerConsumption),integer(LCustomLocationSensor.PowerConsumption))]));
        Writeln(Format('Location Change   : %s', [GetEnumName(TypeInfo(TLocationChangeType),integer(LCustomLocationSensor.LocationChange))]));
        Writeln(Format('Latitude          : %n', [LCustomLocationSensor.Latitude]));
        Writeln(Format('Longitude         : %n', [LCustomLocationSensor.Longitude]));
        Writeln(Format('Longitude         : %n', [LCustomLocationSensor.Longitude]));
        Writeln(Format('Error Radius      : %n', [LCustomLocationSensor.ErrorRadius]));
        Writeln(Format('Altitude          : %n', [LCustomLocationSensor.Altitude]));
        Writeln(Format('Speed             : %n', [LCustomLocationSensor.Speed]));
        Writeln(Format('True Heading      : %n', [LCustomLocationSensor.TrueHeading]));
        Writeln(Format('Magnetic Heading  : %n', [LCustomLocationSensor.MagneticHeading]));
        Writeln(Format('Address1          : %s', [LCustomLocationSensor.Address1]));
        Writeln(Format('Address2          : %s', [LCustomLocationSensor.Address2]));
        Writeln(Format('City              : %s', [LCustomLocationSensor.City]));
        Writeln(Format('State/Province    : %s', [LCustomLocationSensor.StateProvince]));
        Writeln(Format('Postal Code       : %s', [LCustomLocationSensor.PostalCode]));
        Writeln(Format('Country Region    : %s', [LCustomLocationSensor.CountryRegion]));
        LCustomLocationSensor.Stop;
      end;

      TSensorCategory.Light :
      begin
        LCustomLightSensor:=LSensor as TCustomLightSensor;
        Writeln(Format('Lux          : %n', [LCustomLightSensor.Lux]));
        Writeln(Format('Temperature  : %n', [LCustomLightSensor.Temperature]));
        Writeln(Format('Chromacity   : %n', [LCustomLightSensor.Chromacity]));
        Writeln(Format('Sensor Type  : %s', [GetEnumName(TypeInfo(TLightSensorType),integer(LCustomLightSensor.SensorType))]));
      end;

      TSensorCategory.Environmental :
      begin
        LCustomEnvironmentalSensor:= LSensor as TCustomEnvironmentalSensor;
        Writeln(Format('Sensor Type    : %s', [GetEnumName(TypeInfo(TEnvironmentalSensorType),integer(LCustomEnvironmentalSensor.SensorType))]));
        Writeln(Format('Temperature    : %n', [LCustomEnvironmentalSensor.Temperature]));
        Writeln(Format('Pressure       : %n', [LCustomEnvironmentalSensor.Pressure]));
        Writeln(Format('Humidity       : %n', [LCustomEnvironmentalSensor.Humidity]));
        Writeln(Format('Wind Direction : %n', [LCustomEnvironmentalSensor.WindDirection]));
        Writeln(Format('Wind Speed     : %n', [LCustomEnvironmentalSensor.WindSpeed]));
      end;

      TSensorCategory.Motion :
      begin
        LCustomMotionSensor:= LSensor as TCustomMotionSensor;
        Writeln(Format('Sensor Type    : %s', [GetEnumName(TypeInfo(TMotionSensorType),integer(LCustomMotionSensor.SensorType))]));
        Writeln(Format('Acceleration X : %n', [LCustomMotionSensor.AccelerationX]));
        Writeln(Format('Acceleration Y : %n', [LCustomMotionSensor.AccelerationY]));
        Writeln(Format('Acceleration Z : %n', [LCustomMotionSensor.AccelerationZ]));
        Writeln(Format('Angle Accel. X : %n', [LCustomMotionSensor.AngleAccelX]));
        Writeln(Format('Angle Accel. Y : %n', [LCustomMotionSensor.AngleAccelY]));
        Writeln(Format('Angle Accel. Z : %n', [LCustomMotionSensor.AngleAccelZ]));
        Writeln(Format('Motion         : %n', [LCustomMotionSensor.Motion]));
        Writeln(Format('Speed          : %n', [LCustomMotionSensor.Speed]));
        Writeln(Format('Update Interval: %n', [LCustomMotionSensor.UpdateInterval]));
      end;

      TSensorCategory.Orientation :
      begin
        LCustomOrientationSensor:= LSensor as TCustomOrientationSensor;
        Writeln(Format('Sensor Type    : %s', [GetEnumName(TypeInfo(TOrientationSensorType),integer(LCustomOrientationSensor.SensorType))]));
        Writeln(Format('Tilt X         : %n', [LCustomOrientationSensor.TiltX]));
        Writeln(Format('Tilt Y         : %n', [LCustomOrientationSensor.TiltY]));
        Writeln(Format('Tilt Z         : %n', [LCustomOrientationSensor.TiltZ]));
        Writeln(Format('Distance X     : %n', [LCustomOrientationSensor.DistanceX]));
        Writeln(Format('Distance Y     : %n', [LCustomOrientationSensor.DistanceY]));
        Writeln(Format('Distance Z     : %n', [LCustomOrientationSensor.DistanceZ]));
        Writeln(Format('Heading X      : %n', [LCustomOrientationSensor.HeadingX]));
        Writeln(Format('Heading Y      : %n', [LCustomOrientationSensor.HeadingY]));
        Writeln(Format('Heading Z      : %n', [LCustomOrientationSensor.HeadingZ]));
        Writeln(Format('Mag. Heading   : %n', [LCustomOrientationSensor.MagHeading]));
        Writeln(Format('True Heading   : %n', [LCustomOrientationSensor.TrueHeading]));
        Writeln(Format('Comp.Heading   : %n', [LCustomOrientationSensor.CompMagHeading]));
        Writeln(Format('Comp True Head : %n', [LCustomOrientationSensor.CompTrueHeading]));
      end;

      TSensorCategory.Mechanical :
      begin
        LCustomMechanicalSensor:= LSensor as TCustomMechanicalSensor;
        Writeln(Format('Sensor Type    : %s', [GetEnumName(TypeInfo(TMechanicalSensorType),integer(LCustomMechanicalSensor.SensorType))]));
        Writeln(Format('Switch State   : %s', [BoolToStr(LCustomMechanicalSensor.SwitchState, True)]));
        Writeln(Format('Switch Array State : %d', [LCustomMechanicalSensor.SwitchArrayState]));
        Writeln(Format('Multi Value State  : %n', [LCustomMechanicalSensor.MultiValueState]));
        Writeln(Format('Force              : %n', [LCustomMechanicalSensor.Force]));
        Writeln(Format('Abs. Pressure      : %n', [LCustomMechanicalSensor.AbsPressure]));
        Writeln(Format('Gauge Pressure     : %n', [LCustomMechanicalSensor.GaugePressure]));
        Writeln(Format('Strain             : %n', [LCustomMechanicalSensor.Strain]));
        Writeln(Format('Weight             : %n', [LCustomMechanicalSensor.Weight]));
      end;

      TSensorCategory.Electrical :
      begin
        LCustomElectricalSensor:= LSensor as TCustomElectricalSensor;
        Writeln(Format('Sensor Type    : %s', [GetEnumName(TypeInfo(TElectricalSensorType),integer(LCustomElectricalSensor.SensorType))]));
        Writeln(Format('Capacitance    : %n', [LCustomElectricalSensor.Capacitance]));
        Writeln(Format('Resistance     : %n', [LCustomElectricalSensor.Resistance]));
        Writeln(Format('Inductance     : %n', [LCustomElectricalSensor.Inductance]));
        Writeln(Format('Current        : %n', [LCustomElectricalSensor.Current]));
        Writeln(Format('Voltage        : %n', [LCustomElectricalSensor.Voltage]));
        Writeln(Format('Power          : %n', [LCustomElectricalSensor.Power]));
      end;

      TSensorCategory.Biometric :
      begin
        LCustomBiometricSensor:= LSensor as TCustomBiometricSensor;
        Writeln(Format('Sensor Type    : %s', [GetEnumName(TypeInfo(TBiometricSensorType),integer(LCustomBiometricSensor.SensorType))]));
        Writeln(Format('Human Proximity: %n', [LCustomBiometricSensor.HumanProximity]));
        Writeln(Format('Human Presense : %s', [BoolToStr(LCustomBiometricSensor.HumanPresense, True)]));
        Writeln(Format('Touch          : %s', [BoolToStr(LCustomBiometricSensor.Touch, True)]));
      end;

      TSensorCategory.Scanner :
      begin
        LCustomScannerSensor:= LSensor as TCustomScannerSensor;
        Writeln(Format('Sensor Type    : %s', [GetEnumName(TypeInfo(TScannerSensorType),integer(LCustomScannerSensor.SensorType))]));
        Writeln(Format('Human Proximity: %d', [LCustomScannerSensor.RFIDTag]));
        Writeln(Format('Barcode Data   : %s', [LCustomScannerSensor.BarcodeData]));
      end;

    end;
    Writeln;
  end
  else
   Writeln('Not sensors was found');
  LManager.Deactivate;
end;

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

Virtual Sensors

If you don’t have sensors in your machine you can play with these virtual sensors.


8 Comments

Delphi IDE Theme Editor – New feature : Help Insight Themed

I just added a new feature to the Delphi IDE Theme Editor which allow you to apply the current select theme to the Help Insight window.

Here is how the Help Insight window typically looks like

And now with the current theme applied.

This new option is enabled by default in the tool, but you can disable anytime using the settings window.

Download the Delphi IDE Theme Editor

Follow

Get every new post delivered to your Inbox.

Join 401 other followers