{WinCE API call sample : sysinfo show how to : - handle messages with loop using TObject.Dispatch - create form, - load resources (accelators/menubar) - show system informations using HDC sysinfo.rc file require .inc file for consts, if needed update #include path in this file changes : 10-05-2005 : orinaudo@gmail.com first release win32(xp) cross compiled with fpc 2.1.x from today, tested on PPC arm-wince 4.21 Tested on WM5 } Program sysinfo; {$APPTYPE GUI} {$MODE DELPHI} {$PACKRECORDS C} Uses Strings, Windows, SysUtils, strutils, aygshell; {$include appconst.inc} {$R sysinfo.rc} //***************************************************************************** // Base Object (dispatch messages using FPC/TObject capabilities) //***************************************************************************** Function SysInfoMainWndProc (pMainHWnd:HWnd; piMessage : UINT; pWParam : WParam; pLParam:LParam): LResult; stdcall; forward; type TMainSysInfo = Class(TObject) FPWClassName, FPWTitleName : PWideChar; FAccelTable : HACCEL; FMainHWnd : HWND; FMenuBarHWnd : HWND; FShellActivateInfo : SHACTIVATEINFO; constructor Create; function WInit: boolean; function FWndProc( pMainHWnd:HWnd; piMessage : UINT; pWParam : WParam; pLParam:LParam): LResult; procedure DefaultHandler(var message); override; procedure DoCommand( var vAMessage : TMessage); message WM_COMMAND; virtual; procedure DoCreate( var vAMessage : TMessage); message WM_CREATE; virtual; procedure DoPaint( var vAMessage : TMessage); message WM_PAINT; virtual; procedure DoDestroy( var vAMessage : TMessage); message WM_DESTROY; virtual; procedure DoActivate( var vAMessage : TMessage); message WM_ACTIVATE; virtual; procedure DoSettingChange( var vAMessage : TMessage); message WM_SETTINGCHANGE; virtual; end; //***************************************************************************** // Global variables //***************************************************************************** var GMainSysInfo : TMainSysInfo; GMsg: MSG; //***************************************************************************** constructor TMainSysInfo.Create; Begin inherited Create; FPWClassName:='TFormSysInfo'; FPWTitleName:='SysInfo'; FMainHWnd:=0; FMenuBarHWnd:=0; FAccelTable:=0; end; function TMainSysInfo.WInit : boolean; var rc : RECT; wc : WNDCLASS; begin //requirements of the Pocket PC shell, only one instance //If it is already running, then focus on the window FMainHWnd:=FindWindow( FPWClassName, FPWTitleName); if (FMainHWnd=0) then begin //register windows class With wc do begin Style := cs_hRedraw or cs_vRedraw; lpfnWndProc := WndProc(@SysInfoMainWndProc); cbClsExtra := 0; cbWndExtra := 0; hInstance := system.MainInstance; hIcon := LoadIcon(system.MainInstance,IDI_SYSINFO); hCursor := 0; hbrBackground := GetStockObject(WHITE_BRUSH); lpszMenuName := 0; lpszClassName := FPWClassName; End; RegisterClass(@wc); //create window FMainHWnd := CreateWindow ( FPWClassName, FPWTitleName, WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, system.MainInstance, 0); GetWindowRect(FMainHWnd, @rc); rc.bottom:= rc.bottom - 26; //26 is the menubar height if (FMenuBarHWnd>0) then MoveWindow(FMainHWnd, rc.left, rc.top, rc.right, rc.bottom, FALSE); ShowWindow(FMainHWnd, SW_SHOW); UpdateWindow(FMainHWnd); FAccelTable:= LoadAccelerators(System.MainInstance , MAKEINTRESOURCE(IDC_SYSINFO)); Result:=True; end else begin SetForegroundWindow(FMainHWnd); Result:=False; end; //MessageBox(0,PWideChar(WideFormat('hMainInst/hMainWindow/hAccel = %d/%d/%d/ler: %d',[system.MainInstance,FMainHWnd, FAccelTable,GetLastError])),'Info', MB_OK); end; function TMainSysInfo.FWndProc( pMainHWnd:HWnd; piMessage : UINT; pWParam : WParam; pLParam:LParam): LResult; var AMessage: TMessage; begin //small hack, wm_create occur during creation -> createwindows function is not returned //so FMainHWnd still 0 and menubar need a parent ! if (FMainHWnd=0) and (piMessage=WM_CREATE) then FMainHWnd:=pMainHWnd; with AMessage do begin msg := piMessage; wParam := pWParam; lParam := pLParam; end; Dispatch(AMessage); Result:=AMessage.Result; end; procedure TMainSysInfo.DefaultHandler(var message); var PAMessage : PMessage; begin with TMessage(message) do Result:=DefWindowProc(FMainHWnd, msg, wParam, lParam); end; procedure TMainSysInfo.DoCommand( var vAMessage : TMessage); begin vAMessage.Result:=0; // Parse the menu selections: Case vAMessage.wParamlo of IDM_HELP_ABOUT: begin MessageBox(0,'SysInfo v1','About', MB_OK); end; IDOK: begin SendMessage(FMainHWnd, WM_ACTIVATE, MAKEWPARAM(WA_INACTIVE, 0), FMainHWnd); SendMessage (FMainHWnd, WM_CLOSE, 0, 0); end; IDM_QUIT: begin DestroyWindow(FMainHWnd); end; else vAMessage.Result:=DefWindowProc(FMainHWnd, vAMessage.msg, vAMessage.WParam, vAMessage.LParam); end; end; procedure TMainSysInfo.DoCreate( var vAMessage : TMessage); var AMenuBarInfo : SHMENUBARINFO; begin vAMessage.Result:=0; //create MenuBar FillByte(AMenuBarInfo,sizeof(SHMENUBARINFO),0); with AMenuBarInfo do begin cbSize := sizeof(SHMENUBARINFO); dwFlags:= 0; //SHCMBF_EMPTYBAR; hwndParent:= FMainHWnd; nToolBarId:= IDR_MENUBAR; hInstRes:= System.MainInstance; nBmpId:= 0; cBmpImages:= 0; hwndMB:= 0; clrBk :=0; end; if SHCreateMenuBar(@AMenuBarInfo) then FMenuBarHWnd:=AMenuBarInfo.hwndMB else FMenuBarHWnd:=0; //MessageBox(0,PWideChar(WideFormat('menu bar hwnd = %d / %d',[FMenuBarHWnd, GetLastError])),'Info', MB_OK); //Initialize the shell activate info structure FillByte(FShellActivateInfo,sizeof(SHACTIVATEINFO),0); FShellActivateInfo.cbSize := sizeof(SHACTIVATEINFO); end; procedure TMainSysInfo.DoPaint( var vAMessage : TMessage); var rt : RECT; ps : PAINTSTRUCT; AHDC : HDC; wzData : WideString; begin vAMessage.Result:=0; AHDC:= BeginPaint(FMainHWnd, @ps); try GetClientRect(FMainHWnd, @rt); wzData:=WideFormat('Build : %d, WinCE v : %d.%d'#13+ 'Plateform : %d'#13+ 'CDS Version : %s', [Sysutils.WinCEBuildNumber, Sysutils.WinCEMajorVersion, Sysutils.WinCEMinorVersion, SysUtils.WinCEPlatform, Sysutils.WinCECSDVersion]); DrawText(Ahdc, PWideChar(wzData), -1, @rt, DT_LEFT); finally EndPaint(FMainHWnd, @ps); end; end; procedure TMainSysInfo.DoDestroy( var vAMessage : TMessage); begin vAMessage.Result:=0; DestroyWindow(FMenuBarHWnd); //MenuBar Destroy FMenuBarHWnd:=0; PostQuitMessage(0); end; procedure TMainSysInfo.DoActivate( var vAMessage : TMessage); begin with vAMessage do begin Result:=0; // Notify shell of our activate message SHHandleWMActivate(FMainHWnd, wParam, lParam, @FShellActivateInfo, 0); //SHA_INPUTDIALOG end; end; procedure TMainSysInfo.DoSettingChange( var vAMessage : TMessage); begin with vAMessage do begin Result:=0; SHHandleWMSettingChange(FMainHWnd, wParam, lParam, @FShellActivateInfo); end; end; //***************************************************************************** // SysInfoMainWndProc // Process messages for the main window //***************************************************************************** // registerclass accept only static proc not objects methods // lpfnWndProc := WndProc(@SysInfoMainWndProc) -> redirection to object method Function SysInfoMainWndProc (pMainHWnd:HWnd; piMessage : UINT; pWParam : WParam; pLParam:LParam): LResult; stdcall; begin Result:=GMainSysInfo.FWndProc( pMainHWnd,piMessage,pWParam,pLParam); end; //***************************************************************************** // Main entry point //***************************************************************************** Begin try GMainSysInfo:=TMainSysInfo.Create; try if GMainSysInfo.WInit then While GetMessage(@GMsg,0,0,0) do if TranslateAccelerator(GMsg.hwnd, GMainSysInfo.FAccelTable, @GMsg)=0 then begin Windows.TranslateMessage(@GMsg); Windows.DispatchMessage(@GMsg); end; finally GMainSysInfo.Free; end; except On E:Exception do MessageBox(0,PWideChar(WideFormat('message = %s',[E.message])),'Error', MB_OK); end; End.