Difference between revisions of "Windows CE Development Notes"

From Free Pascal wiki
Jump to navigationJump to search
Line 417: Line 417:
 
!COLSPAN="1" STYLE="background:#ffdead;"|'''Observations'''
 
!COLSPAN="1" STYLE="background:#ffdead;"|'''Observations'''
 
|----
 
|----
|Windows Mobile 5.0 Emulator - PocketPC||5.0||atPDA||Yes||240||268||26||
+
|WM*** 5.0 Emulator - PocketPC||5.0||atPDA||Yes||240||268||26||
 
|----
 
|----
|Windows Mobile 5.0 Emulator - Smartphone||5.0||atSmartphone||No||176||180||0||
+
|WM 5.0 Emulator - Smartphone||5.0||atSmartphone||No||176||180||0||
 
|----
 
|----
|Windows Mobile 5.0 Emulator - Smartphone QVGA||5.0||atSmartphone||No||240||266||0||
+
|WM 5.0 Emulator - Smartphone QVGA||5.0||atSmartphone||No||240||266||0||
 +
|----
 +
|WM 2003 - Pocket PC||?||atPDA||Yes||240||294||0||
 
|}
 
|}
  
 
  * - Values available for a maximized program will all extras activated (start menu, menu correction, PID, etc).
 
  * - Values available for a maximized program will all extras activated (start menu, menu correction, PID, etc).
 
  ** - Adequate value for the WinCEWidgetset.MaximizedWindowHeightCorrection property.
 
  ** - Adequate value for the WinCEWidgetset.MaximizedWindowHeightCorrection property.
 +
*** - WM = Windows Mobile
  
 
==Links==
 
==Links==

Revision as of 16:01, 4 December 2008

WinCE Logo.png

This article applies to WinCE only.

See also: Multiplatform Programming Guide

English (en) 中文(台灣)‎ (zh_TW)

Other Interfaces

Platform specific Tips

Interface Development Articles

Debugging your applications

General info is here Windows_CE_Interface#Debbuging Windows CE software on the Lazarus IDE

  • Sometimes GDB will crash, just reset debugger and start again.
  • If you have an open call stack window it will take lots of time each time you trace or debug your program and it sometimes crashes the debugger, so use it only when needed.
  • Always put breakpoints where needed; you can not-or hardly can- pause your program or even stop/reset it.
  • You can strip your program with --only-keep-debug which save you around 1 mg.There are some issues with strip utility, sometimes it makes your program not executable, So I generally don't recommend using it.
  • Sometimes stepping takes lots of time, just be patient ,I've experienced once a simple assignment took 1 min for debugger to execute that code.

Alignment problems

Using ARM processors, some times you may get a EBusError exception with a message about misaligned data access. The following section explains what this is and how to fix it.


What is misaligned data access?

Suppose a CPU has a 8bit data bus to memory and you want to read a byte. Since you have a 8bit bus, you are able to address all individual bytes, so reading is not a problem. Now imagine a CPU with a 32bit data bus and reading a byte. Data is read in chunks of 32bits (=4 bytes) and it is addressed by multiples of 4. For getting the exact byte, the CPU "shifts" the right byte.


Now we do the same for reading a 32bits integer. On an 8 bit CPU, you have to read 4 times one byte and then you have the integer. On a 32bits CPU it can be read in one go if the address is aligned to 4 bytes. If not, it has to be read in 2 halves and then combined to one integer. The x86 supports reading like this, although it is inefficient. The SPARC and some implementations of the ARM (*) don't support this and raise a bus error if you read data like this.


(*) there are extensions to the ARM core which can handle it, but this Depends on what functionality the manufacturer of a specific core has Implemented.


How to solve this?

Use typecasts of pointers very carefully. 16-bit and 32-bit values need to be 4-byte aligned in memory. Otherwise bus error will occur. Or use newly added "unaligned" keyword before using them. You can use unaligned keyword both in left or right side of your assignments.

Examples:

var
p1:^Longint;
l:longint;
begin
p1^:=20;  //might cause error if p points to an unaligned memory, i.e. not 4-byte aligned.
unaligned(p1^):=20;  //it is ok 
l:=pl^;  //this can also generate error
l:=unaligned(pl^);  //it is ok 
end.

When using Pack records, compiler automatically generates all access to the record members as unaligned access. Currently there are some small issues which sometimes with nested pack records compiler does not generate the required code. You just have to use unaligned keyword. But note that using packed records will influence speed a lot as all of its members are treated as unaligned. So use them only if needed.

Implementation details

ApplicationType

The Windows CE interface will try to automatically detect the kind of device which is being run if nothing is specifyed by the user. The possible devices are:

  • atDefault - The same as atPDA
  • atPDA - A PDA with a touch screen. Forms are usually maximized to ocupy the whole work area, and custom positioning and sizing is ignored. Windows CE devices will almost always (maybe always?) have a Width of 240 pixels, and the Height can very, but 320 pixels is a good guess.
  • atSmartphone - Similar to a PDA, but can be used as a phone. Currently no technical difference to atPDA.
  • atDesktop - A full desktop application, for which the operating system just happens to be WinCE. Should work just like the Win32 Lazarus interface.
  • atHandheld - Bigger then a PDA and with more capability. Currently is the same as atDesktop.

How to specify a fixed device:

<delphi> program MyProgram;

...

begin

 Application.ApplicationType := atSmartphone;
 // On Application.Initialize a default device would be detected if 
 // ApplicationType = atDefault, but now the detection is suppressed.
 Application.Initialize;
 ...

end. </delphi>

Positioning and size of Dialogs and Forms

At run-time the position and size of forms on the WinCE interface is different then designed. Specifically, it's dependent on the kind of device being run and on the border style.


ApplicationType BorderStyle Behavior WindowState Title bar Status
atDesktop, atHandheld Any Not yet defined. Currently it should work just like on win32, althougth maybe the Left/Top position should always be ignored, because a Handheld may have a small screen. It's also necessary to check if all border styles are supported (how could one resize a form on a handhelp?) As on desktops As on desktops Implemented
atPDA, atSmartphone bsDialog Accepts custom sizing. The X, Y position is ignored and always set to be the top-left corner, but taking into account the existence of an eventual Taskbar on the top. Not applicable Separate title bar with a "OK" close button Implemented
atPDA, atSmartphone bsNone Allows full control of the size and position to the user. Not applicable Doesn't exist Implemented
atPDA, atSmartphone bsSizable, bsSingle, bsToolWin, bsSizeToolWin Rejects custom size and position and is always set to fill the entire work area excluding the menu. The definition of Work Area already excludes the Taskbar Not applicable Merged into the taskbar with a "OK" close button Implemented

Obs:

  • Currently atDefault is defined as atPDA.

Links with information

  • Code to position a form on the work area: [1]

The Title "OK" and "X" buttons

A very common problem found in previous LCL for WinCE versions was that under Windows CE, by default, there exists no close button available in the title bar. There is, however, a "X" minimize button, which minimizes the form. Because there is a "X" written on it, and because a very similar button in desktops closes the form, the majority of Lazarus for WinCE users expected that button to close the form. To attend this expectation we have changed the default behavior for our forms and now they will all have a "OK" close button instead of a "X" minimize button.

Predicting that some people will desire to have the X button, it was provided a switch to control the title buttons policy. There are some values possible:

Value Description
tpAlwaysUseOKButton The default one and all forms will have an "OK" close button.
tpOKButtonOnlyOnDialogs Can also be choosen and all forms will have "X" minimize buttons instead of forms with bsDialog borderstyle, which will still have an "OK" close button.
tpControlWithBorderIcons If biMinimize is included in the form's BorderIcons, then a "X" minimize button will be shown. A "OK" button is shown otherwise.

Be very careful using any option which allows the "X" button, because:

  • Clicking in the X in the main form of the application won't quit it. You are responsible for providing code so that when the user starts a new instance of your application it will detect the running instance, show the running instance and then quit, or else you will fill the users memory with instances of your application.

Example code to change the default policy bellow:

<delphi> {$ifdef WinCE} uses

 WinCEInt;

{$endif}

...

begin {$ifdef WinCE}

 WinCEWidgetset.WinCETitlePolicy := tpOKButtonOnlyOnDialogs;

{$endif} end; </delphi>

Screenshots

This is a title with "X" minimize button:

Title with x button.PNG

This is a title with "OK" close button:

Title with ok button.PNG

Implementation details

The "OK" button will send a WM_COMMAND message, which is handled on wincecallback.inc, with wID=IDOK. There we respond by throwing a WM_CLOSE to the form.

Bug Reports

TWinControl.PopupMenu showing

Showing the popup menu of a windowed control is implemented using the native behavior of the Windows CE platform for touch screens. The user holds the pointer in a given control for a certain amount of time and the popup shows. This is implemented on the WM_LBUTTONDOWN message handler by calling SHRecognizeGesture.

For more details see:

TRadioButton and TGroupBox

See Also: Win32/64_Interface#Background_color_of_Standard_Controls

Several different problems with TCustomCheckBox descendents (like TRadioButton) and TGroupBox were found on Lazarus 0.9.25 and are being fixed.

1 - The autosize of TCustomCheckBox descendents under Windows CE produces a too small area, both inside a TRadioGroup and a alone in a form. That indicates that there was a problem with TWSWinCECustomCheckBox.GetPreferedSize. Even with the code exactly equal to the win32 interface the width was still too small, so an extra 10 pixels factor was added arbitrarely to fix that until a better solution is found - Fixed

2 - Aditionally TCustomCheckBox descendents inside a TGroupBox (but not on a form) paint a white background instead of painting the correct background color. The way to handle background color changing on a series of controls is by handling the WM_CTLCOLORSTATIC message. Even with the code exactly the same as the Win32 one that still happens, and for unknown misterious reasons if the control is on a form instead of a GroupBox it works normally.

3 - A third problem found while investigating the other ones is that the difference between the windows client are and the client area that LCL expects was being ignored under Windows CE. This would be seen when one places a control on a TGroupBox or other controls with a border that the position of the places control was wrong - Fixed

TRadioGroup before fixes

Wince radiogroup before.png

(Obs: The captions should be "Item1", "Yet another Item", "Item2", "Item3")

TRadioGroup after fixes

Not yet fixed

Bug Tracker items

TCheckListBox

See also: Win32/64_Interface#TCheckListBox

TCheckListBox presented some color problems under Windows CE which needed to be fixed. Specifically it was found that on several places where system colors were used, the constant SYS_COLOR_INDEX_FLAG wasn't added. LCLIntf.GetSysColor makes sure the constant is added, so it should always be used instead of Windows.GetSysColor. On desktop Windows this constant equals to zero, so it can be ignored.

Possible causes of the problem are a bug on Windows CE or a bug on the emulator.

The colors of the TCheckListBox items under Windows CE are:

Description Code Value before fix Correct value Corrected?
background of the entire item GetSysColor(COLOR_WINDOW) black white Yes
background of unselected text default background color white white Yes
background of selected text SetBkColor(GetSysColor(COLOR_HIGHLIGHT)) black blue Yes
background of selected item GetSysColor(COLOR_HIGHLIGHT) black blue Yes
color of selected text SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)) black white Yes
color of disabled text SetTextColor(GetSysColor(COLOR_GRAYTEXT)) black Gray Yes
color of normal text SetTextColor(GetSysColor(COLOR_WINDOWTEXT)) black black Yes

Acording to the MSDN docs a result of 0 for GetSysColor under Windows CE should identify that it isn't available. Now, 0 is also an RGB value (black), so maybe the WinCE docs are wrong and the Win32 docs should be used.

TChecklistbox before fixes

Wince checklistbox.png

TChecklistbox after fixes

Wince checklistbox after workaround.png

MSDN Docs

Bug tracker items

Tab Controls (TPageControl)

While most controls work just "as-is" from normal Win32 code, Tab Controls present a big amount of "gotchas" which make development of a tab control harder then in Win32.

A small list:

  • Vertical text is not supported, so tab buttons located on the left and right won't show text
  • For whatever reason (a bug in WinCE?) tab controls with tab buttons located on the top won't display text on the tab

Also, Microsoft recomends using tabs with bottom style under Windows CE, so that the user won't cover the touch screen with his hand when changing tabs. Combining all those together made me decide to hard-code page controls into always using bottom style under Windows CE, regardless of the control properties.

The default stype is a bit old. But I found the new style too minimalistic. You can barely see it's a tab control at all. The call to set new style (flat stype) is on the code (TWinCEWSCustomNotebook.CreateHandle), just commented, so it will be easy to change in the future

Some docs are located here:

http://msdn2.microsoft.com/en-us/library/aa921319.aspx

Background and sheet position problems

The background of each page seams not to be painted by default, and because the border around the control is very thin and incomplete (not all edges have borders), you can barely see what is the client area of the sheet

I used a magick change on the sheet position given by WinCE as described here:

http://www.pocketpcdn.com/forum/viewtopic.php?t=499

Here is a TPageControl before the sheet position adjust:

Before tab adjust.png

And after:

After tab adjust.png

Note that you can only clearly see the client area on the bottom page control because I put a TPanel aligned to alClient inside it.

I couldn't decide if fixing a background color was a good idea, or which color would I use for it, so I'm leaving this problem be for now.

Bug tracker items

DataAware controls

For some unknown reason, data-aware controls crash the application.

Bug tracker items

Menus

Menus aren't yet implemented for Smartphones.

Bug tracker items

Brushes

CreateBrushIndirect doesn't exist under Windows CE, so the interface maps it to CreateSolidBrush, CreateDIBPatternBrushPt and GetStockObject.

If special flags are used they are ignored and CreateSolidBrush is used instead.

From CreateBrushIndirect on wincewinapi.inc: <delphi>

 if lb.lbStyle= BS_NULL then
   Result := Windows.GetStockObject(NULL_BRUSH)
 else if lb.lbStyle = BS_DIBPATTERNPT then
   Result := CreateDIBPatternBrushPt(pointer(lb.lbHatch), lb.lbColor)
 else { lb.lbStyle = BS_SOLID }
   Result := Windows.CreateSolidBrush(LB.lbColor);

</delphi>

SetProp - GetProp - RemoveProp APIs

Windows CE does not have SetProp and GetProp API's which is used a lot. So I have created/emulated them. The current implementation is not exactly as win32 API. In win32 you can set multiple properties with different names to each window but here I ignore names so we can only have one kind of property assigned to each control. (It is easy to implement that, but I find it currently of no use). Also removeprop is not called yet! So a memory leak happens each time you exist the program. (I don't know if wince also frees memory itself or not when window handles are destroyed).Should be implemented soon.

Modal Dialogs and the OK and X buttons

Under Windows CE some dialogs will present both the OK and the X button. It is possible to distinguish between them according to the ModalResult that they send. The OK close button will send mrOK, while the X minimize button will close the dialog and send a mrCancel result.

Here is the dialog produced by the following code under Windows CE:

  MessageDlg('Shall I test a very, really, long string?', mtConfirmation, [mbYes, mbNo, mbOk, mbCancel],0);


Messagedlg wince.PNG

Bug reports:

http://bugs.freepascal.org/view.php?id=11439

Overlapping menu bottom

There seams to be a flaw in Windows CE. I haven't yet found a way to effectively maximize a window. The big problem is that the routine Windows.SystemParametersInfo(SPI_GETWORKAREA, 0, @WR, 0); doesn't return what we expect in some systems, and returns on other ones.

To correct this, it is now possible to specify an arbitrary correction called MaximizedWindowHeightCorrection which will be applied to the Height of the window, like in the code bellow:

<delphi> program lazcalendar;

{$mode objfpc}{$H+}

uses

 Interfaces,
 {$ifdef Wince}
 WinCEInt,
 {$endif}
 Forms,
 mainform;

{$IFDEF WINDOWS}{$R lazcalendar.rc}{$ENDIF}

begin

 {$ifdef Wince}
   WinCEWidgetset.MaximizedWindowHeightCorrection := 26;
 {$endif}
 Application.Initialize;
 Application.CreateForm(TformCalendar, formCalendar);
 Application.Run;

end. </delphi>

The good value to use in MaximizedWindowHeightCorrection seems to be 26 and maybe in some rare cases 52.

Here is a screenshot of an application which is overlapping the menu:

Wince overlapping menu.png

Microsoft Newsgroup Links:

Routine to maximize a window in Windows CE. Not very good, because it just uses a lot of ifdefs:

http://groups.google.com/group/microsoft.public.pocketpc.developer/browse_thread/thread/f4bba1733d3f6cfa/342497d1797af97a?lnk=gst&q=unreliable#342497d1797af97a

Workarea problem description:

http://groups.google.com/group/microsoft.public.windowsce.embedded.vc/browse_thread/thread/2f4ecdade7fe48aa?q=menu+SystemParametersInfo+group:microsoft.public.windowsce.*#44941f01c43edbd7

List of devices with information about them

There are differences between devices, so it would be interresting to have a list with information about each of them. Please contribute.


Device Name WinCE Version ApplicationType Touchscreen? Width* Height* MWHC** Observations
WM*** 5.0 Emulator - PocketPC 5.0 atPDA Yes 240 268 26
WM 5.0 Emulator - Smartphone 5.0 atSmartphone No 176 180 0
WM 5.0 Emulator - Smartphone QVGA 5.0 atSmartphone No 240 266 0
WM 2003 - Pocket PC ? atPDA Yes 240 294 0
* - Values available for a maximized program will all extras activated (start menu, menu correction, PID, etc).
** - Adequate value for the WinCEWidgetset.MaximizedWindowHeightCorrection property.
*** - WM = Windows Mobile

Links

Here are some links that might be useful for creating Windows CE interfaces.

How to Port Your Win32 Code to Windows CE

Old but useful article show flags required for creating wince controls

Page with nice descriptions of lots of flags

Adapting Application Menus to the CE User Interface

Differences between normal Win32-API and Windows CE (old wince)

Resource-Definition Statements

GUI Control Styles

Developing Orientation and dpi Aware Applications

Developing Screen Orientation-Aware Applications

Introduction to User Interface Controls in a Windows Mobile-based Smartphone

WinCE port of KOL GUI library