Windows Mobile-based Smartphone Programming


A Smartphone application is a Windows application with the same entry point, the same message loop, and the same general message handlers. The figure shows HelloSP running on a Smartphone. The text is centered in the client window, which has been sized to fit the area between the navigation bar and the MenuBar control.

The unique parts of the application start with the Pocket PC-like check for whether another instance of the application is running. The example code also queries the height of the MenuBar control and adjusts the size of the main window to fit above it. Unlike Pocket PC applications, there is no need to dynamically respond to the SIP popping up over the window because there's no SIP on the Smartphone. Below shows the source code for HelloSp.

 HelloSP.rc 

//======================================================================
// Resource file
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include "windows.h"                 // Windows stuff
#include "aygshell.h"                // Pocket PC stuff
#include "HelloSP.h"                 // Program-specific stuff

//----------------------------------------------------------------------
// Icons and bitmaps
//
ID_ICON      ICON   "HelloSP.ico"    // Program icon

ID_MENU RCDATA
BEGIN
  0,
  1,
  I_IMAGENONE, IDM_EXIT, TBSTATE_ENABLED, 
      TBSTYLE_BUTTON | TBSTYLE_AUTOSIZE, IDS_OK, 0, NOMENU,
END

STRINGTABLE DISCARDABLE
BEGIN
  IDS_OK        "OK"
END
       

 HelloSP.h 

//======================================================================
// Header file
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//================================================================
// Returns number of elements
#define dim(x) (sizeof(x) / sizeof(x[0])) 

//----------------------------------------------------------------------
// Generic defines and data types
//
struct decodeUINT {                          // Structure associates
  UINT Code;                                 // messages 
                                             // with a function.
  LRESULT (*Fxn)(HWND, UINT, WPARAM, LPARAM);
}; 

struct decodeCMD {                           // Structure associates
  UINT Code;                                 // menu IDs with a 
  LRESULT (*Fxn)(HWND, WORD, HWND, WORD);    // function.
};

//----------------------------------------------------------------------
// Generic defines used by application
#define  ID_MENU           10
#define  IDM_EXIT          100
#define  IDS_OK            1001

//----------------------------------------------------------------------
// Function prototypes
//
HWND InitInstance (HINSTANCE, LPWSTR, int);
int TermInstance (HINSTANCE, int);

// Window procedures
LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);

// Message handlers
LRESULT DoCreateMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoPaintMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDestroyMain (HWND, UINT, WPARAM, LPARAM);

// WM_COMMAND message handlers
PARAM DoMainCommandExit (HWND, WORD, HWND, WORD);
       

 HelloSP.cpp 

//======================================================================
// HelloSP - A simple application for the Smartphone
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include <windows.h>                 // For all that Windows stuff
#include <commctrl.h>                // Command bar includes
#include <aygshell.h>                // Pocket PC includes
#include "hellosp.h"                 // Program-specific stuff

//----------------------------------------------------------------------
// Global data
//
const TCHAR szAppName[] = TEXT("HelloSP");
HINSTANCE hInst;                      // Program instance handle

// Message dispatch table for MainWindowProc
const struct decodeUINT MainMessages[] = {
  WM_CREATE, DoCreateMain,
  WM_PAINT, DoPaintMain,
  WM_COMMAND, DoCommandMain,
  WM_DESTROY, DoDestroyMain,
};

// Command Message dispatch for MainWindowProc
const struct decodeCMD MainCommandItems[] = {
  IDM_EXIT, DoMainCommandExit,
};

//======================================================================
// Program entry point
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPWSTR lpCmdLine, int nCmdShow) {
  MSG msg;
  int rc = 0;
  HWND hwndMain;

  // Initialize this instance.
  hwndMain = InitInstance (hInstance, lpCmdLine, nCmdShow);
  if (hwndMain == 0) return 0x10;

  // Application message loop
  while (GetMessage (&msg, NULL, 0, 0)) {
    TranslateMessage (&msg);
    DispatchMessage (&msg);
  }
  // Instance cleanup
  return TermInstance (hInstance, msg.wParam);
}

//------------------------------------------------------------------
// InitInstance - Instance initialization
//
HWND InitInstance (HINSTANCE hInstance, LPWSTR lpCmdLine, int nCmdShow) {
  WNDCLASS wc;
  HWND hWnd;

  // Save program instance handle in global variable.
  hInst = hInstance;

  // Allow only one instance of the application.
  hWnd = FindWindow (szAppName, NULL);
  if (hWnd) {
    SetForegroundWindow ((HWND)(((DWORD)hWnd) | 0x01));    
    return 0;
  }

  // Register application main window class.
  wc.style = CS_VREDRAW | CS_HREDRAW;       // Window style
  wc.lpfnWndProc = MainWndProc;             // Callback function
  wc.cbClsExtra = 0;                        // Extra class data
  wc.cbWndExtra = 0;                        // Extra window data
  wc.hInstance = hInstance;                 // Owner handle
  wc.hIcon = NULL,                          // Application icon
  wc.hCursor = LoadCursor (NULL, IDC_ARROW); // Default cursor
  wc.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH);
  wc.lpszMenuName =  NULL;                  // Menu name
  wc.lpszClassName = szAppName;             // Window class name

  if (RegisterClass (&wc) == 0) return 0;

  // Create main window.
  hWnd = CreateWindow (szAppName,           // Window class
                       TEXT("Hello"),       // Window title
                       WS_VISIBLE,          // Style flags
                       CW_USEDEFAULT,       // x position
                       CW_USEDEFAULT,       // y position
                       CW_USEDEFAULT,       // Initial width
                       CW_USEDEFAULT,       // Initial height
                       NULL,                // Parent
                       NULL,                // Menu, must be null
                       hInstance,           // Application instance
                       NULL);               // Pointer to create
                                               // parameters
  if (!IsWindow (hWnd)) return 0;           // Fail if not created.

  // Standard show and update calls
  ShowWindow (hWnd, nCmdShow);
  UpdateWindow (hWnd);
  return hWnd;
}

//----------------------------------------------------------------------
// TermInstance - Program cleanup
//
int TermInstance (HINSTANCE hInstance, int nDefRC) {
  return nDefRC;
}

//======================================================================
// Message handling procedures for main window
//
//----------------------------------------------------------------------
// MainWndProc - Callback function for application window
//
LRESULT CALLBACK MainWndProc (HWND hWnd, UINT wMsg, WPARAM wParam, 
    LPARAM lParam) {
  INT i;
 
  //
  // Search message list to see if we need to handle this
  // message.  If in list, call procedure.
  //
  for (i = 0; i < dim(MainMessages); i++) {
    if (wMsg == MainMessages[i].Code)
      return (*MainMessages[i].Fxn)(hWnd, wMsg, wParam, lParam);
  }
  return DefWindowProc (hWnd, wMsg, wParam, lParam);
}

//----------------------------------------------------------------------
// DoCreateMain - Process WM_CREATE message for window.
//
LRESULT DoCreateMain (HWND hWnd, UINT wMsg, WPARAM wParam, 
    LPARAM lParam) {
  SHMENUBARINFO mbi;

  // Create a MenuBar.
  memset(&mbi, 0, sizeof(SHMENUBARINFO)); // Zero structure
  mbi.cbSize = sizeof(SHMENUBARINFO);     // Size field
  mbi.hwndParent = hWnd;                  // Parent window
  mbi.nToolBarId = ID_MENU;               // ID of toolbar resource
  mbi.hInstRes = hInst;                   // Inst handle of app

  // Create bar and check for errors.
  if (!SHCreateMenuBar(&mbi)) {
    MessageBox (hWnd, TEXT("Couldn\'t create menu bar"), 
        szAppName, MB_OK);
    DestroyWindow (hWnd);
  }

  // Size the window to fit above the MenuBar
  RECT rect, rectDesk;
  int cx, cy;
  GetWindowRect (mbi.hwndMB, &rect);
  GetWindowRect (GetDesktopWindow (), &rectDesk);
  cx = rectDesk.right-rectDesk.left;
  cy = (rectDesk.bottom - rectDesk.top) - (rect.bottom - rect.top);
  SetWindowPos (hWnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);

  SHSetNavBarText (hWnd, TEXT("Hello"));
  return 0;
}

//----------------------------------------------------------------------
// DoCommandMain - Process WM_COMMAND message for window.
//
LRESULT DoCommandMain (HWND hWnd, UINT wMsg, WPARAM wParam,
    LPARAM lParam) {
  WORD idItem, wNotifyCode;
  HWND hwndCtl;
  INT  i;

  // Parse the parameters.
  idItem = (WORD) LOWORD (wParam);
  wNotifyCode = (WORD) HIWORD (wParam);
  hwndCtl = (HWND) lParam;

  // Call routine to handle control message.
  for (i = 0; i < dim(MainCommandItems); i++) {
    if (idItem == MainCommandItems[i].Code)
      return (*MainCommandItems[i].Fxn)(hWnd, idItem, hwndCtl,
          wNotifyCode);
  }
  return 0;
}

//----------------------------------------------------------------------
// DoPaintMain - Process WM_PAINT message for window.
//
LRESULT DoPaintMain (HWND hWnd, UINT wMsg, WPARAM wParam, 
    LPARAM lParam) {
  PAINTSTRUCT ps;
  HPEN hPen, hOld;
  RECT rect;
  HDC hdc;

  hdc = BeginPaint (hWnd, &ps); 
  GetClientRect (hWnd, &rect);

  // Draw a red rectangle around the window.
  hPen = CreatePen (PS_SOLID, 1, RGB (255, 0, 0));
  hOld = (HPEN)SelectObject (hdc, hPen);
  Rectangle (hdc, rect.left, rect.top, rect.right, rect.bottom);
  SelectObject (hdc, hOld);
  DeleteObject (hPen);

  // Draw the standard hello text centered in the window.
  DrawText (hdc, TEXT ("Hello Smartphone!"), -1, &rect, 
      DT_CENTER | DT_VCENTER | DT_SINGLELINE);

  EndPaint (hWnd, &ps); 
  return 0;
}

//----------------------------------------------------------------------
// DoDestroyMain - Process WM_DESTROY message for window.
//
LRESULT DoDestroyMain (HWND hWnd, UINT wMsg, WPARAM wParam, 
    LPARAM lParam) {
  PostQuitMessage (0);
  return 0;
}

//======================================================================
// Command handler routines
//----------------------------------------------------------------------
// DoMainCommandExit - Process Program Exit command.
//
LPARAM DoMainCommandExit (HWND hWnd, WORD idItem, HWND hwndCtl,
    WORD wNotifyCode) {
  SendMessage (hWnd, WM_CLOSE, 0, 0);
  return 0;
}