//======================================================================
// HelloPPC - A simple application for the Pocket PC
//
// 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 "helloppc.h"                // Program-specific stuff
//----------------------------------------------------------------------
// Global data
//
const TCHAR szAppName[] = TEXT ("HelloPPC");
HINSTANCE hInst;                      // Program instance handle
// Pocket PC globals
HWND hwndMenuBar = NULL;              // Handle of menu bar control
BOOL fHibernated = FALSE;             // Indicates hibernated state
SHACTIVATEINFO sai;                   // Used to adjust window for SIP
// Message dispatch table for MainWindowProc
const struct decodeUINT MainMessages[] = {
  WM_CREATE, DoCreateMain,
  WM_PAINT, DoPaintMain,
  WM_COMMAND, DoCommandMain,
  WM_SETTINGCHANGE, DoSettingChangeMain,
  WM_ACTIVATE, DoActivateMain,
  WM_HIBERNATE, DoHibernateMain,
  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;
  HACCEL hAccel;
  // Initialize this instance.
  hwndMain = InitInstance (hInstance, lpCmdLine, nCmdShow);
  if (hwndMain == 0) return 0x10;
  hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE (ID_ACCEL));
  // Application message loop
  while (GetMessage (&msg, NULL, 0, 0)) {
    // Translate accelerator keys.
    if (!TranslateAccelerator(hwndMain, hAccel, &msg)) {
      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;
  SIPINFO si;
  int cx, cy;
  // Initialize the shell to activate info structure.
  memset (&sai, 0, sizeof (sai));
  sai.cbSize = sizeof (sai);
  // Create a menu bar.
  memset(&mbi, 0, sizeof(SHMENUBARINFO)); // Zero structure
  mbi.cbSize = sizeof(SHMENUBARINFO);     // Size field
  mbi.hwndParent = hWnd;                  // Parent window
  mbi.dwFlags = SHCMBF_EMPTYBAR;          // Flags like hide SIP btn
  mbi.nToolBarId = 0;                     // ID of toolbar resource
  mbi.hInstRes = 0;                       // Inst handle of app
  mbi.nBmpId = 0;                         // ID of bitmap resource
  mbi.cBmpImages = 0;                     // Num of images in bitmap 
  mbi.hwndMB = 0;                         // Handle of bar returned
  // Create menu bar and check for errors.
  if (!SHCreateMenuBar(&mbi)) {
    MessageBox (hWnd, TEXT ("Couldn\'t create menu bar"), 
      szAppName, MB_OK);
    DestroyWindow (hWnd);
  }
  hwndMenuBar = mbi.hwndMB;               // Save the menu bar handle.
  // Query the sip state and size our window appropriately.
  memset (&si, 0, sizeof (si));
  si.cbSize = sizeof (si);
  SHSipInfo(SPI_GETSIPINFO, 0, (PVOID)&si, FALSE); 
  cx = si.rcVisibleDesktop.right - si.rcVisibleDesktop.left;
  cy = si.rcVisibleDesktop.bottom - si.rcVisibleDesktop.top;
  // If the sip is not shown, or showing but not docked, the
  // desktop rect doesn't include the height of the menu bar.
  if (!(si.fdwFlags & SIPF_ON) ||
      ((si.fdwFlags & SIPF_ON) && !(si.fdwFlags & SIPF_DOCKED))) {
    RECT rectMB;
    GetWindowRect (hwndMenuBar, &rectMB);
    cy -= (rectMB.bottom - rectMB.top);  
  }
    
  SetWindowPos (hWnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
  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 Pocket PC! "), -1, &rect, 
      DT_CENTER | DT_VCENTER | DT_SINGLELINE);
  EndPaint (hWnd, &ps); 
  return 0;
}
//----------------------------------------------------------------------
// DoSettingChangeMain - Process WM_SETTINGCHANGE message for window.
//
LRESULT DoSettingChangeMain (HWND hWnd, UINT wMsg, WPARAM wParam, 
    LPARAM lParam) {
 
  // Notify shell of our WM_SETTINGCHANGE message.
  SHHandleWMSettingChange(hWnd, wParam, lParam, &sai);
  return 0;
}
//----------------------------------------------------------------------
// DoActivateMain - Process WM_ACTIVATE message for window.
//
LRESULT DoActivateMain (HWND hWnd, UINT wMsg, WPARAM wParam, 
    LPARAM lParam) {
  // If activating, restore any hibernated stuff.
  if ((LOWORD (wParam) != WA_INACTIVE) && fHibernated) {
    fHibernated = FALSE;
  }
  // Notify shell of our activate message.
  SHHandleWMActivate(hWnd, wParam, lParam, &sai, 0);
  return 0;
}
//----------------------------------------------------------------------
// DoHibernateMain - Process WM_HIBERNATE message for window.
//
LRESULT DoHibernateMain (HWND hWnd, UINT wMsg, WPARAM wParam, 
    LPARAM lParam) {
 
  // If not the active window, reduce our memory footprint.
  if (GetActiveWindow() != hWnd) {
    fHibernated = TRUE;
  }
  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;
}
       
       |