Introduction
There are various options for program development on Pocket PC, for e.g., embedded VC and Visual Studio. But the drawback of using eVC for Pocket PC development is that eVC currently does not work on Vista and later operating systems. Also device development is not supported on Express Editions of Visual Studio. It requires full version of Visual Studio to develop for Pocket PC. So if you want a free environment for developing Pocket PC applications, you need to look for an alternative.
A good free alternative for Pocket PC development is Pelles C. Pelles C contains compiler, linker and install builders for Pocket PC as well as Windows. It also has an Integrated Development Environment with Project Management, source code editor, debugger and resource editors for various resources like dialogs, menus, icons, cursors, etc.
Background
Pelles C can be downloaded from here.
To demonstrate the use of Pelles C, I have developed a sample application PocketScribble
.
Anyone who knows Windows Programming in C can write Pocket PC programs using Pelles C.
To create a new Pocket PC application in Pelles C IDE, select the File->New->Project menu command. You will get the following screen:
Choose the WinCE Pocket PC Program(EXE) project type.
You can add C source file using the Add files option as follows:
You can generate the executable code of your program by choosing the Build EXE option from the Project menu as follows:
The generated EXE file can be copied to the actual Windows mobile or emulator using either Active Sync (on Windows XP) or Windows Mobile Device Center (on Vista or later O.S).
Using the Code
The execution of a Pocket PC program or a Windows program begins with the WinMain
function whose prototype is as follows:
int PASCAL WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPWSTR lpCmdLine,int nCmdShow)
In the above code, HISNTANCE
is a macro representing an unsigned int
and LPWSTR
is a macro representing a long
pointer to char
.
The parameters of the WinMain
function are as follows:
- The first parameter is
hInst
, which represents the current instance.
- If more than one instance of the program is running concurrently, then the
hPrevInst
parameter contains the hInstance
value for the last copy started.
- The
lpCmdLine
parameter is a pointer to the character string
containing the command line arguments passed to the program.
- The
nCmdShow
parameter is an integer value representing the window state when the program starts (minimized, normal or maximized).
In the WinMain
function, we use the WNDCLASS
structure to define window characteristics as follows:
wc.hInstance=hInst; wc.lpszClassName=L"MYWINDOW"; wc.lpfnWndProc=myWndProc; wc.hbrBackground=GetStockObject(WHITE_BRUSH);
The RegisterClass()
function is used to register the window class as follows:
RegisterClass(&wc);
After registering the window class, a window is created as follows:
hWnd=CreateWindow(L"MYWINDOW",L"Pocket Scribble",
WS_OVERLAPPEDWINDOW,20,20,200,200,0,0,hInst,0);
The parameters of the CreateWindow()
function are as follows:
- The first parameter is the window class name.
- The second parameter is the window title.
- The third parameter is the window style (
WS_OVERLAPPEDWINDOW
).
- The fourth parameter is the x co-ordinate of the window's top left corner.
- The fifth parameter is the y co-ordinate of the window's top left corner.
- The sixth parameter is the window width.
- The seventh parameter is the window height.
- The eighth parameter is the parent window handle. A value of zero for this parameter indicates that the current window has no parent window.
- The ninth parameter is the menu for the window. A value of zero for this parameter indicates that the current window has no menu.
- The tenth parameter is the current program instance.
- The eleventh parameter is the pointer to the window creation data.
The newly created window is displayed by using the following function call:
ShowWindow(hWnd,nCmdShow);
In the ShowWindow()
method, the first parameter is the window handle returned from CreateWindow()
method and the second parameter is the nCmdShow
parameter from the WinMain()
function representing the window state.
The window contents can be updated using the following function call:
UpdateWindow(hWnd);
After this, a message loop is created as follows:
while(GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
The above message loop performs the following tasks:
- It uses the
GetMessage()
method to read messages from the message queue and store it in a MSG
structure.
- It uses the
TranslateMesage()
method to convert keyboard messages in the msg
structure to character messages.
- Then it uses the
DispatchMessage()
method to send the translated message to the window procedure which processes the message.
The following is the window procedure:
LRESULT CALLBACK myWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
HDC hDC;
switch(uMsg)
{
case WM_DESTROY: PostQuitMessage(0); break;
case WM_LBUTTONDOWN: down=1; x1=LOWORD(lParam); y1=HIWORD(lParam); break;
case WM_MOUSEMOVE:
if(down==1) {
x2=LOWORD(lParam); y2=HIWORD(lParam); hDC=GetDC(hWnd); MoveToEx(hDC,x1,y1,0); LineTo(hDC,x2,y2); ReleaseDC(hWnd,hDC); x1=x2;
y1=y2;
}
break;
case WM_LBUTTONUP: down=0;
break;
default:
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
In the above code, the uMsg
parameter contains the messages generated. The WM_DESTROY
is generated when we close the window. We use the PostQuitMessage()
method to post the WM_QUIT
message, which causes the message loop in the WinMain()
function to be terminated and the program stops.
The WM_LBUTTONDOWN
message is generated when the left mouse button is pressed. The down variable is set to 1
to indicate that the left mouse button is pressed. The LOWORD
and HIWORD
macros are used to trap the current x and y co-ordinates respectively.
The WM_LBUTTONUP
message is generated when the left mouse button is released. The down variable is set to 0
to indicate that the left mouse button is released.
The WM_MOUSEMOVE
message is generated when the mouse is moved. We use the LOWORD
and HIWORD
macros to trap the new x and y co-ordinates and draw a line between the old and new co-ordinates. The MoveToEx
and LineTo
functions require the device context which is obtained using the GetDC()
function.
Following is the complete code of the PocketScribble
application:
#include <windows.h>
LRESULT CALLBACK myWndProc(HWND,UINT,WPARAM,LPARAM);
WNDCLASS wc;
int down=0;
int x1,y1,x2,y2;
int PASCAL WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPWSTR lpCmdLine,int nCmdShow)
{
HWND hWnd;
MSG msg;
wc.hInstance=hInst;
wc.lpszClassName=L"MYWINDOW";
wc.lpfnWndProc=myWndProc;
wc.hbrBackground=GetStockObject(WHITE_BRUSH);
RegisterClass(&wc);
hWnd=CreateWindow
(L"MYWINDOW",L"Pocket Scribble",WS_OVERLAPPEDWINDOW,20,20,200,200,0,0,hInst,0);
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
while(GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK myWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
HDC hDC;
switch(uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_LBUTTONDOWN:
down=1;
x1=LOWORD(lParam);
y1=HIWORD(lParam);
break;
case WM_MOUSEMOVE:
if(down==1)
{
x2=LOWORD(lParam);
y2=HIWORD(lParam);
hDC=GetDC(hWnd);
MoveToEx(hDC,x1,y1,0);
LineTo(hDC,x2,y2);
ReleaseDC(hWnd,hDC);
x1=x2;
y1=y2;
}
break;
case WM_LBUTTONUP:
down=0;
break;
default:
break;
}
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
Points of Interest
I was since long searching for an alternative to Visual Studio for Pocket PC Programming and was lucky to find this excellent IDE. I hope this article will be helpful to all Pocket PC enthusiasts who are looking for an alternative IDE for Pocket PC development.
The following figure shows the application being executed on my HTC_P3450 Mobile with Windows Mobile 6 Professional: