WinCE Programming Tips
From Lazarus-ccr
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
- Lazarus known issues (things that will never be fixed) - A list of interface compatibility issues
- Win32/64 Interface - The winapi interface for Windows 95/98/Me/2K/XP/Vista, but not CE
- GTK1 Interface - The gtk1 for Unixes, Mac OS X, Windows
- GTK2 Interface - The gtk2 for Unixes, Mac OS X, Windows
- Carbon Interface - The Carbon Interface for Mac OS X
- Qt Interface - The Qt 4 Interface for Unixes, Mac OS X and linux-based PDAs
- Windows CE Interface - For Pocket PC and Smartphones
- fpGUI Interface - A widgetset completely written in Object Pascal
- Cocoa Interface - The Cocoa Interface for Mac OS X
[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
- Carbon interface internals - If you want to help improving the Carbon interface
- Windows CE Development Notes - For Pocket PC and Smartphones
- Adding a new interface - How to add a new widget set interface
- LCL Defines - Choosing the right options to recompile LCL
[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;
