WinCE Programming Tips

From Lazarus-ccr

Jump to: navigation, search

This page is a under construction reference to help in the development for the Windows CE platform, covering common programming topics specific to it.

Contents

[edit] Other Interfaces

[edit] Platform specific Tips

  • OS X Programming Tips - Lazarus installation, useful tools, Unix commands, and more...
  • WinCE Programming Tips - Using the telephone API, sending SMSes, and more...
  • Windows Programming Tips - Desktop Windows programming tips.

[edit] Interfaces Development Articles

[edit] TIPS / FAQ

[edit] Application runs on Windows Device Emulator, but not on physical device

When running a compiled application on the Windows Device emulator, it works fine, but running it on the physical device you get the error:

Cannot find 'project1' (or one of its components).

This is usually indicative of missing DLLs on the target device, especially if you have a very simple "Hello World" type of application. In many instances, it is related to the aygshell.dll file, which is not present on many industrial-type devices running a bare Windows CE version - normally devices running "Windows Mobile" versions of Windows CE will not have this problem.

This problem has been reported on Motorolla/Symbol MC9000 and MC1000 barcode scanners running both Windows CE 4.2 and 5.

To resolve, do a search for "aygshells.zip" in a search engine - there are some "Dummy" aygshell.dll files available that can be copied to the device to overcome this problem.

[edit] Get Device ID

Get and ID of your device useful for protect your application. This work only on Windows Mobile 5.0 and Windows CE 5.1

 
 
function GetDeviceUniqueID(AppData:LPCWSTR; cbApplictionData:Integer; dwDeviceIDVersion:Integer;
 var deviceIDOuput; var pcbDeviceIDOutput:DWORD):Integer; external 'coredll.dll' name 'GetDeviceUniqueID';
 
function GetDeviceID: string;
var
  AppData: array[0..19] of WideChar;
  DeviceID : array[0..19] of Byte;
  Count: DWORD;
  s: string;
  Res, i:Integer;
begin
  //not sure about Unicode
  AppData := Utf8Decode('MY_SIG');//any string you like
  Count := SizeOf(DeviceID);
  FillChar(DeviceID, Count, #0);
  Res := GetDeviceUniqueID(AppData, SizeOF(AppData), 1, DeviceID, Count);
  if Res = 0 then
  begin
    Result := '';
    for i := 0 to Count -1 do
    begin
      if (i > 0) and ((i mod 2) = 0) then
        Result := Result + '-'; //add space make the string wrap in label
      Result := Result + IntToHex(DeviceID[i], 2);
    end;
  end
  else
    Result := '';//error accord
//  you can MD5 it with your string
//  Result := MD5Print(MD5Buffer(DeviceID, Count));
end;
 

Reference pages: http://msdn2.microsoft.com/en-us/library/ms893522.aspx http://peterfoot.net/RetrieveIMEIThroughTAPI.aspx http://blogs.msdn.com/jehance/archive/2004/07/12/181067.aspx

[edit] Get Device Name

Easy to get it from registry

 
function GetDeviceName: string;
var
  aReg:TRegistry;
begin
  aReg := TRegistry.Create(KEY_READ);
  try
    aReg.RootKey := HKEY_LOCAL_MACHINE;
    aReg.OpenKey('Ident', False);
    if aReg.ValueExists('Name') then
      Result := aReg.ReadString('Name')
    else
      Result := 'GUEST';
  finally
    aReg.Free;
  end;
end;
 

[edit] Show/Hide SIP Panel

SIP: Software Input Panel button, it is a keyboard come with WinCE for touch screen devices.

 
const
  //some of consts already found in Windows
  SIPF_OFF    =	$00000000;
  SIPF_ON     =	$00000001;
  SIPF_DOCKED =	$00000002;
  SIPF_LOCKED =	$00000004;
 
function SipShowIM(IPStatus:DWORD):Integer; stdcall; external 'coredll.dll' name 'SipShowIM';
 
begin
  SipShowIM(SIPF_ON)
end;
 
 


[edit] Wakeup Device/ Power On

If you like to make alarm application this function make your device power on, you need also make some sounds with it.

 
function SetSystemPowerState(psState: PWideChar; StateFlags: DWORD; Options : DWORD):DWORD;
 stdcall; external 'coredll.dll' name 'SetSystemPowerState';
 
 
  SetSystemPowerState(nil, POWER_STATE_ON, 0);
  Application.BringToFront;
  ShowWindow(Handle, SW_SHOW);
 

[edit] LED / Vibrator

You can turn on/off then LED/vibrator in, your device, it worked for me but not as like as i want, may be it need some improvements.

 
const
  NLED_COUNT_INFO_ID	= 0;
  NLED_SUPPORTS_INFO_ID	= 1;
  NLED_SETTINGS_INFO_ID	= 2;
 
type
  TNLED_COUNT_INFO = record
    cLeds: DWORD;
  end;
 
  TNLED_SETTINGS_INFO = record
    LedNum: DWORD;                 // LED number, 0 is first LED
    OffOnBlink: Integer;           // 0 = off, 1 = on, 2 = blink
    TotalCycleTime: DWORD;         // total cycle time of a blink in microseconds
    OnTime: DWORD;                 // on time of a cycle in microseconds
    OffTime: DWORD;                // off time of a cycle in microseconds
    MetaCycleOn: Integer;          // number of on blink cycles
    MetaCycleOff: Integer;         // number of off blink cycles
   end;
 
  function NLedGetDeviceInfo(nID:Integer; var pOutput): WordBool;
   stdcall; external 'coredll.dll' name 'NLedGetDeviceInfo';
  function NLedSetDevice(nID: Integer; var pOutput): WordBool;
   stdcall; external 'coredll.dll' name 'NLedSetDevice';
 

Examples

 
function TForm1.MakeLEDOn;
var
  Countnfo: TNLED_COUNT_INFO;
  Info:TNLED_SETTINGS_INFO;
begin
  NLedGetDeviceInfo(NLED_COUNT_INFO_ID, Countnfo);
  //with Countnfo.cLeds you can check if your device support LEDs;
  Info.LedNum := 0; //<--- First LED
  Info.OffOnBlink := 1;
  Info.OffTime := 0;
  Info.MetaCycleOff:= 50;
  Info.MetaCycleOn:= 50;
  Info.TotalCycleTime := 100;
  NLedSetDevice(NLED_SETTINGS_INFO_ID, Info);
end;
 
procedure TForm1.MakeLedOff;
var
  Info:TNLED_SETTINGS_INFO;
begin
  Info.LedNum := 0;
  Info.OffOnBlink := 0;
  NLedSetDevice(NLED_SETTINGS_INFO_ID, Info);
end;  
 
 


Vibrator it is the last LED in your device, if you can write some music you can now make your phone dance.

 
function TForm1.MakeVibratorOn;
var
  Countnfo: TNLED_COUNT_INFO;
  Info:TNLED_SETTINGS_INFO;
begin
  NLedGetDeviceInfo(NLED_COUNT_INFO_ID, Countnfo);
  Info.LedNum := Countnfo.cLeds -1;
  Info.OffOnBlink := 1;
  NLedSetDevice(NLED_SETTINGS_INFO_ID, Info);
end;  
 
function TForm1.MakeVibratorOff;
var
  Countnfo: TNLED_COUNT_INFO;
  Info:TNLED_SETTINGS_INFO;
begin
  NLedGetDeviceInfo(NLED_COUNT_INFO_ID, Countnfo);
  Info.LedNum := Countnfo.cLeds -1;
  Info.OffOnBlink := 0;
  NLedSetDevice(NLED_SETTINGS_INFO_ID, Info);
end;  
 

[edit] Getting Battery Status

For more information : MSDN GetSystemPowerStatusEx

 
//by Philip Heinisch
 type
  TBAT_INFO = record
  ACLineStatus:byte; //0=Offline, 1=Online, 2=Backup Power,3= Unknown status 
  BatteryFlag:byte; //0=High, 1=Low, 2=Critical, 3=Charging, 4=No Battery, 5=Unknown
  BatteryLifePercent:byte; //0..100 Battery Life in Percent
  Reserved1:byte; //always 0
  BatteryLifeTime: DWORD; //remaining time in seconds
  BatteryFullLifeTime: DWORD; //max usage time in seconds
  Reserved2:byte; //always 0
  BackupBatteryFlag:byte; //0=High, 1=Low, 2=Critical, 3=Charging, 4=No Battery, 5=Unknown
  BackupBatteryLifePercent:byte; //0..100 Backup Battery Life in Percent
  Reserved3:byte; //always 0
  BackupBatteryLifeTime: DWORD; //remaining time in seconds
  BackupBatteryFullLifeTime: DWORD; //max usage time in seconds
 end;        
 
  function GetSystemPowerStatusEx(var pOutput;fUpdate:boolean ): WordBool;
   stdcall; external 'coredll.dll' name 'GetSystemPowerStatusEx'; 
 
//Usage Example:
 
function getbat :  byte;
var
  batinfo: TBAT_INFO;
begin
if GetSystemPowerStatusEx(batinfo,True) then getbat:=batinfo.BatteryLifePercent
else getbat:=255; //255=Function Call Failed 
end;