Programming Microsoft Windows Ce Net 3Rd [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Programming Microsoft Windows Ce Net 3Rd [Electronic resources] - نسخه متنی

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید






The GAPIShow Example

The following example is a very simple demonstration of GAPI. The game (of sorts) in this case is a star field drawn to appear to the viewer as though it's moving through space. The effect is similar to the Starfield screen saver on desktop versions of Windows with the exception that the objects are simply white dots.

When the game first starts, it displays the information returned by GXGetDisplayProperties, such as the pitch of the pixels and the format of the frame buffer. Selecting Play from the Game menu starts the star field animation. Tapping on the screen stops the animation and brings the user back to the information screen. Contrary to Pocket PC guidelines, GAPIShow has an Exit menu item to ease shutting down the example. Listing 20-1 shows the GAPIShow source code. Since the resources in this example were wizard-generated, the .rc file isn't listed here. Of course, the complete source code is on the companion CD.

Listing 20-1: The GAPIShow source code







GAPIShow.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]))
#define PARSEFLAG(a,b) (a & b) ? TEXT(#b) : TEXT("\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.
};
#define ID_TIMER 1
#define MAX_STARS 40
#define SHFT 3
#define MAX_X 1024*2
#define MAX_Y 1024*2
#define MID_X (MAX_X/2)
#define MID_Y (MAX_Y/2)
typedef struct {
int x;
int y;
int dist;
} STARINFO, *PSTARTINFO;
//----------------------------------------------------------------------
// Function prototypes
//
HWND InitInstance (HINSTANCE, LPWSTR, int);
int TermInstance (HINSTANCE, int);
int InitGame (HWND hWnd);
int EndGame (HWND hWnd);
HWND MyCreateMenuBar (HWND hWnd);
int ClearScreen_16 (PVOID lpBuff, COLORREF rgb);
int DrawScreen_16 (PVOID lpBuff, int dx, int dy, int dv);
int InitScreen_16 (PVOID lpBuff);
#define ClearScreen ClearScreen_16a
#define DrawScreen DrawScreen_16a
// Window procedures
LRESULT CALLBACK MainWndProc (HWND, UINT, WPARAM, LPARAM);
// Dialog procedures
BOOL CALLBACK AboutDlgProc (HWND, UINT, WPARAM, LPARAM);
// Message handlers
LRESULT DoTimerMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoKeyDownMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCreateMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoPaintMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoLButtonDownMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoSetFocusMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoKillFocusMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoCommandMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoSettingChangeMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoActivateMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoHibernateMain (HWND, UINT, WPARAM, LPARAM);
LRESULT DoDestroyMain (HWND, UINT, WPARAM, LPARAM);
// WM_COMMAND message handlers
LPARAM DoMainCommandExit (HWND, WORD, HWND, WORD);
LPARAM DoMainCommandPlay (HWND, WORD, HWND, WORD);
LPARAM DoMainCommandAbout (HWND, WORD, HWND, WORD);


GAPIShow.cpp
//======================================================================
// GAPIShow - A Games API example program for the Pocket PC
//
// Written for the book Programming Windows CE
// Copyright (C) 2003 Douglas Boling
//======================================================================
#include "stdafx.h" // Wizard includes
#include <aygshell.h> // Pocket PC includes
#include <gx.h> // GAPI includes
#include "GapiShow.h"
#include "resource.h" // Tools generated equates
//----------------------------------------------------------------------
// Global data
//
const TCHAR szAppName[] = TEXT("GapiShow");
HINSTANCE hInst; // Program instance handle
// Pocket PC globals
HWND hwndMenuBar = NULL; // Handle of menu bar control
BOOL fHibernated = FALSE; // Indicates hibernated state
BOOL fPlaying = FALSE; // Indicates Gapi access active
BOOL fResuming = FALSE; // Used when regaining focus
SHACTIVATEINFO sai; // Used to adjust window for SIP
RECT rectNorm;
int cyFont = 0;
int nSpeed = 2, ndX = 0, ndY = 0;
int CxScreen, CyScreen;
int nCnt = 0;
STARINFO ptStars[MAX_STARS]; // Star field info
GXDisplayProperties gxdp; // GAPI display info structure
GXKeyList gxkl; // GAPI keyboard info structure
// Message dispatch table for MainWindowProc
const struct decodeUINT MainMessages[] = {
WM_TIMER, DoTimerMain,
WM_KEYDOWN, DoKeyDownMain,
WM_CREATE, DoCreateMain,
WM_PAINT, DoPaintMain,
WM_LBUTTONDOWN, DoLButtonDownMain,
WM_SETFOCUS, DoSetFocusMain,
WM_KILLFOCUS, DoKillFocusMain,
WM_COMMAND, DoCommandMain,
WM_SETTINGCHANGE, DoSettingChangeMain,
WM_ACTIVATE, DoActivateMain,
WM_HIBERNATE, DoHibernateMain,
WM_DESTROY, DoDestroyMain,
};
// Command Message dispatch for MainWindowProc
const struct decodeCMD MainCommandItems[] = {
ID_GAME_EXIT, DoMainCommandExit,
ID_GAME_PLAY, DoMainCommandPlay,
ID_TOOLS_ABOUT, DoMainCommandAbout,
};
//======================================================================
// Program entry point
//
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPWSTR lpCmdLine, int nCmdShow) {
MSG msg;
int rc = 0;
HWND hwndMain;
HACCEL hAccel;
// Initialize application.
hwndMain = InitInstance (hInstance, lpCmdLine, nCmdShow);
if (hwndMain == 0) return 0x10;
hAccel = LoadAccelerators(hInstance,
MAKEINTRESOURCE (IDR_ACCELERATOR1));
// 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;
// Clear GAPI info structures.
memset (&gxdp, 0, sizeof (gxdp));
memset (&gxkl, 0, sizeof (gxkl));
CxScreen = GetSystemMetrics (SM_CXSCREEN);
CyScreen = GetSystemMetrics (SM_CYSCREEN);
// Create main window.
hWnd = CreateWindow (szAppName, // Window class
TEXT("GAPI Show"), // 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.

// Query GAPI parameters.
if (GXOpenDisplay(hWnd, GX_FULLSCREEN)) {
gxdp = GXGetDisplayProperties();
gxkl = GXGetDefaultKeys(GX_NORMALKEYS);
} else
MessageBox (hWnd, TEXT ("GXOpenDisplay failed"),
szAppName, MB_OK);
// Standard show and update calls
ShowWindow (hWnd, nCmdShow);
UpdateWindow (hWnd);
return hWnd;
}
//----------------------------------------------------------------------
// TermInstance - Program cleanup
//
int TermInstance (HINSTANCE hInstance, int nDefRC) {
GXCloseDisplay();
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) {
SIPINFO si;
int cx, cy;
TEXTMETRIC tm;
HDC hdc;
// Query the height of the default font.
hdc = GetDC (hWnd);
GetTextMetrics (hdc, &tm);
cyFont = tm.tmHeight + tm.tmExternalLeading;
ReleaseDC (hWnd, hdc);
// Initialize the shell to activate info structure.
memset (&sai, 0, sizeof (sai));
sai.cbSize = sizeof (sai);
// Create menu bar and check for errors.
hwndMenuBar = MyCreateMenuBar (hWnd);
if (!hwndMenuBar) {
MessageBox (hWnd, TEXT("Couldn\'t create menu bar"),
szAppName, MB_OK);
DestroyWindow (hWnd);
}
// 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 is 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)))
cy -= 26; // Height of menu bar control
SetWindowPos (hWnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
return 0;
}
//----------------------------------------------------------------------
// DoTimerMain - Process WM_TIMER message for window.
//
LRESULT DoTimerMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
PBYTE lpBuff;
lpBuff = (PBYTE) GXBeginDraw();
if (lpBuff) {
DrawScreen_16 (lpBuff, ndX, ndY, nSpeed);
if (fResuming)
ClearScreen_16 (lpBuff, RGB (0, 0, 0));
GXEndDraw();
} else {
KillTimer (hWnd, ID_TIMER);
}
return 0;
}
//----------------------------------------------------------------------
// DoKeyDownMain - Process WM_KEYDOWN message for window.
//
LRESULT DoKeyDownMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
if (fPlaying) {
// Up
if (wParam == (DWORD)gxkl.vkUp) {
if (ndY > -100) ndY -= 10;
// Down
} else if (wParam == (DWORD)gxkl.vkDown) {
if (ndY < 100) ndY += 10;
// Left
} else if (wParam == (DWORD)gxkl.vkLeft) {
if (ndX > -100) ndX -= 10;
// Right
} else if (wParam == (DWORD)gxkl.vkRight) {
if (ndX < 100) ndX += 10;
// Fast
} else if (wParam == (DWORD)gxkl.vkA) {
if (nSpeed < 10) nSpeed += 1;
// Slow
} else if (wParam == (DWORD)gxkl.vkB) {
if (nSpeed > 1) nSpeed -= 1;
else nSpeed = 1;
} else if (wParam == (DWORD)gxkl.vkC) {
ndX = 0;
ndY = 0;
nSpeed = 2;
}
}
return 0;
}
//----------------------------------------------------------------------
// DoLButtonDownMain - Process WM_LBUTTONDOWN message for window.
//
LRESULT DoLButtonDownMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
// If playing, stop the game.
if (fPlaying)
SendMessage (hWnd, WM_COMMAND, MAKELONG (ID_GAME_PLAY, 0), 0);
return 0;
}
//----------------------------------------------------------------------
// DoSetFocusMain - Process WM_SETFOCUS message for window.
//
LRESULT DoSetFocusMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
if (fPlaying) {
GXResume();
fResuming = TRUE;
// Start a very fast timer.
SetTimer (hWnd, ID_TIMER, 10, NULL);
}
return 0;
}
//----------------------------------------------------------------------
// DoKillFocusMain - Process WM_KILLFOCUS message for window.
//
LRESULT DoKillFocusMain (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
if (fPlaying)
SetWindowPos (hWnd, HWND_NOTOPMOST, 0, 0, CxScreen, CyScreen, 0);
KillTimer (hWnd, ID_TIMER);
GXSuspend();
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;
RECT rect;
TCHAR szTxt[128];
HDC hdc;
int i, y = 5;
static hOldPlaying;
hdc = BeginPaint (hWnd, &ps);
GetClientRect (hWnd, &rect);
// If not playing, display the GAPI information about the device.
if (!fPlaying) {
wsprintf (szTxt, TEXT ("Gapi values:"));
ExtTextOut (hdc, 5, y, 0, &rect, szTxt, lstrlen (szTxt), 0);
y += cyFont;
wsprintf (szTxt, TEXT ("cxWidth: %d"), gxdp.cxWidth);
ExtTextOut (hdc, 10, y, 0, &rect, szTxt, lstrlen (szTxt), 0);
y += cyFont;
wsprintf (szTxt, TEXT ("cyHeight: %d"), gxdp.cyHeight);
ExtTextOut (hdc, 10, y, 0, &rect, szTxt, lstrlen (szTxt), 0);
y += cyFont;
wsprintf (szTxt, TEXT ("cbxPitch: %d"), gxdp.cbxPitch);
ExtTextOut (hdc, 10, y, 0, &rect, szTxt, lstrlen (szTxt), 0);
y += cyFont;
wsprintf (szTxt, TEXT ("cbyPitch: %d"), gxdp.cbyPitch);
ExtTextOut (hdc, 10, y, 0, &rect, szTxt, lstrlen (szTxt), 0);
y += cyFont;
wsprintf (szTxt, TEXT ("cBPP: %d"), gxdp.cBPP);
ExtTextOut (hdc, 10, y, 0, &rect, szTxt, lstrlen (szTxt), 0);
y += cyFont;
wsprintf (szTxt, TEXT ("ffFormat: %08x"), gxdp.ffFormat);
ExtTextOut (hdc, 10, y, 0, &rect, szTxt, lstrlen (szTxt), 0);
y += cyFont;
lstrcpy (szTxt, PARSEFLAG(gxdp.ffFormat, kfLandscape));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
lstrcpy (szTxt, PARSEFLAG (gxdp.ffFormat, kfPalette));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
lstrcpy (szTxt, PARSEFLAG (gxdp.ffFormat, kfDirect));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
lstrcpy (szTxt, PARSEFLAG (gxdp.ffFormat, kfDirect555));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
lstrcpy (szTxt, PARSEFLAG (gxdp.ffFormat, kfDirect565));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
lstrcpy (szTxt, PARSEFLAG (gxdp.ffFormat, kfDirect888));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
lstrcpy (szTxt, PARSEFLAG (gxdp.ffFormat, kfDirect444));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
lstrcpy (szTxt, PARSEFLAG (gxdp.ffFormat, kfDirectInverted));
if (i = lstrlen (szTxt)) { //Assignment in if
ExtTextOut (hdc, 20, y, 0, &rect, szTxt, i, 0);
y += cyFont;
}
}
EndPaint (hWnd, &ps);
hOldPlaying = fPlaying;
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) {
if (fPlaying) {
// Clean up if playing game.
KillTimer (hWnd, ID_TIMER);
GXCloseInput();
}
GXCloseDisplay();
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;
}
//----------------------------------------------------------------------
// DoMainCommandPlay - Process Play command.
//
LPARAM DoMainCommandPlay (HWND hWnd, WORD idItem, HWND hwndCtl,
WORD wNotifyCode) {
if (!fPlaying) {
if (!(gxdp.ffFormat & (kfDirect555 | kfDirect565))) {
MessageBox (hWnd,
TEXT ("GAPIShow supports only 16 bpp displays"),
szAppName, MB_OK);
return 0;
}
InitGame (hWnd);
} else {
EndGame (hWnd);
}
return 0;
}
//----------------------------------------------------------------------
// DoMainCommandAbout - Process the Tools | About menu command.
//
LPARAM DoMainCommandAbout(HWND hWnd, WORD idItem, HWND hwndCtl,
WORD wNotifyCode) {
// Use DialogBox to create modal dialog.
DialogBox (hInst, MAKEINTRESOURCE (IDD_ABOUT), hWnd, AboutDlgProc);
return 0;
}
//======================================================================
// About Dialog procedure
//
BOOL CALLBACK AboutDlgProc (HWND hWnd, UINT wMsg, WPARAM wParam,
LPARAM lParam) {
switch (wMsg) {
case WM_INITDIALOG:
{
SHINITDLGINFO idi;
idi.dwMask = SHIDIM_FLAGS;
idi.dwFlags = SHIDIF_DONEBUTTON | SHIDIF_SIZEDLGFULLSCREEN |
SHIDIF_SIPDOWN;
idi.hDlg = hWnd;
SHInitDialog (&idi);
}
break;
case WM_COMMAND:
switch (LOWORD (wParam)) {
case IDOK:
case IDCANCEL:
EndDialog (hWnd, 0);
return TRUE;
}
break;
}
return FALSE;
}
//----------------------------------------------------------------------
// MyCreateMenuBar – Create the menu bar for the program.
//
HWND MyCreateMenuBar (HWND hWnd) {
SHMENUBARINFO mbi;
// Create a menu bar.
memset(&mbi, 0, sizeof(SHMENUBARINFO)); // Zero structure
mbi.cbSize = sizeof(SHMENUBARINFO); // Size field
mbi.hwndParent = hWnd; // Parent window
mbi.nToolBarId = IDR_MENUBAR1; // ID of toolbar resource
mbi.hInstRes = hInst; // Inst handle of app
// Create menu bar and check for errors.
if (!SHCreateMenuBar(&mbi))
return 0;
return mbi.hwndMB;
}
//----------------------------------------------------------------------
// InitGame - Start game by capturing the keyboard, drawing star field,
// and starting timer.
//
int InitGame (HWND hWnd) {
PBYTE pBuff;
// Make our window topmost and cover the entire screen.
GetWindowRect (hWnd, &rectNorm);
SetWindowPos (hWnd, HWND_TOPMOST, 0, 0, CxScreen, CyScreen, 0);
DestroyWindow (hwndMenuBar);
ValidateRect (hWnd, NULL);
// Grab the keyboard.
GXOpenInput();
fPlaying = TRUE;

// Initialize the display.
pBuff = (PBYTE) GXBeginDraw();
if (pBuff) {
ClearScreen_16 (pBuff, RGB (0, 0, 0));
InitScreen_16 (pBuff);
GXEndDraw();
}
// Start a very fast timer.
SetTimer (hWnd, ID_TIMER, 10, NULL);
return 0;
}
//----------------------------------------------------------------------
// EndGame - Clean up by re-creating the main window.
//
int EndGame (HWND hWnd) {
fPlaying = FALSE;
KillTimer (hWnd, ID_TIMER);
GXCloseInput();
// Create menu bar and check for errors.
hwndMenuBar = MyCreateMenuBar (hWnd);
if (!hwndMenuBar) {
MessageBox (hWnd, TEXT("Couldn\'t create menu bar"),
szAppName, MB_OK);
}
// Restore our window to the old position.
SetWindowPos (hWnd, HWND_NOTOPMOST, rectNorm.left, rectNorm.top,
rectNorm.right - rectNorm.left,
rectNorm.bottom - rectNorm.top, 0);
InvalidateRect (hWnd, NULL, TRUE);
return 0;
}
//----------------------------------------------------------------------
// ClearScreen_16 - 16 bpp version of clear screen
//
int ClearScreen_16 (PVOID lpBuff, COLORREF rgb) {
WORD wPixel = 0;
DWORD x, y;
PBYTE pbLine, pbPixel;
// Verify that we have a valid frame buffer.
if (!lpBuff) return 0;
// Format pixel from colorref data.
if (gxdp.ffFormat | kfDirect565) {
wPixel = (WORD) ((GetRValue(rgb) >> 3) << 11 |
(GetGValue(rgb) >> 2) << 5 |
(GetBValue(rgb) >> 3));
} else if (gxdp.ffFormat | kfDirect555) {
wPixel = (WORD) ((GetRValue(rgb) >> 3) << 10 |
(GetGValue(rgb) >> 3) << 5 |
(GetBValue(rgb) >> 3));
}
// Do rows.
pbLine = (PBYTE)lpBuff;
for (y = 0; y < gxdp.cyHeight; y++) {
// Do columns.
pbPixel = pbLine;
for (x = 0; x < gxdp.cxWidth; x++) {
// Cast ptr and write.
*(PWORD)pbPixel = wPixel;
pbPixel += gxdp.cbxPitch; // Move to the next pixel.
}
pbLine += gxdp.cbyPitch; // Move to the next line.
}
return 0;
}
//----------------------------------------------------------------------
// DrawScreen_16 - Compute new position for each star; redraw if it
// has moved.
//
int DrawScreen_16 (PVOID lpBuff, int dx, int dy, int dv) {
int i, nOldDist;
PBYTE pNew = 0;
PBYTE pOld = 0;
static nOldDX, nOldDY;
for (i = 0; i < MAX_STARS; i++) {
// Remove old star.
if (((ptStars[i].x >> SHFT) < CxScreen+2) &&
((ptStars[i].y >> SHFT) < CyScreen+2))
pOld = (PBYTE)lpBuff +
(ptStars[i].x >> SHFT) * gxdp.cbxPitch +
(ptStars[i].y >> SHFT) * gxdp.cbyPitch;
nOldDist = ptStars[i].dist;
// Update pos. New pos is related to its pos from middle of the
// screen. This pushes the stars to the edges.
ptStars[i].x += ((ptStars[i].x-MID_X)/4 * dv + dx)/16+1;
ptStars[i].y += ((ptStars[i].y-MID_Y)/4 * dv + dy)/16+1;
ptStars[i].dist++;
// If new position off screen, regenerate the star.
if ((ptStars[i].x < 0) || (ptStars[i].y < 0) ||
((ptStars[i].x >> SHFT) >= CxScreen) ||
((ptStars[i].y >> SHFT) >= CyScreen)) {

ptStars[i].x = Random() & MAX_X-1;
ptStars[i].y = Random() & MAX_Y-1;
ptStars[i].dist = 0;
}
// Compute pointer to new star.
if (((ptStars[i].x >> SHFT) < CxScreen) &&
((ptStars[i].y >> SHFT) < CyScreen))
pNew = (PBYTE)lpBuff +
(ptStars[i].x >> SHFT) * gxdp.cbxPitch +
(ptStars[i].y >> SHFT) * gxdp.cbyPitch;
// Don't redraw star if in same place.
if (pNew != pOld) {
if (pOld) {
*(PWORD)pOld = 0;
// Stars older than 15 generations get bigger.
if (nOldDist > 15) {
*(PWORD)(pOld + gxdp.cbxPitch) = 0;
*(PWORD)(pOld + gxdp.cbyPitch) = 0;
*(PWORD)(pOld + gxdp.cbxPitch +
gxdp.cbyPitch) = 0;
}
}
if (pNew) {
*(PWORD)pNew = 0xffff;
if (ptStars[i].dist > 15) {
*(PWORD)(pNew + gxdp.cbxPitch) = 0xffff;
*(PWORD)(pNew + gxdp.cbyPitch) = 0xffff;
*(PWORD)(pNew + gxdp.cbxPitch +
gxdp.cbyPitch) = 0xffff;
}
}
}
}
return 0;
}
//----------------------------------------------------------------------
// InitScreen_16 - Initialize each star position and draw it.
//
int InitScreen_16 (PVOID lpBuff) {
int i;
PBYTE pNew = 0;
TCHAR szTxt[128];
for (i = 0; i < MAX_STARS; i++) {
// Initialize star.
ptStars[i].x = Random() & MAX_X-1;
ptStars[i].y = Random() & MAX_Y-1;
ptStars[i].dist = 0;
// If on the screen, draw star.
if (((ptStars[i].x >> SHFT) < CxScreen) &&
((ptStars[i].y >> SHFT) < CyScreen))
pNew = (PBYTE)lpBuff +
(ptStars[i].x >> SHFT) * gxdp.cbxPitch +
(ptStars[i].y >> SHFT) * gxdp.cbyPitch;
__try {
if (pNew)
*(PWORD)pNew = 0xffff;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
wsprintf (szTxt, TEXT("Exception %d %08x (%d,%d)"), i,
pNew, ptStars[i].x, ptStars[i].y);
MessageBox (NULL, szTxt, szAppName, MB_OK);
break;
}
}
return 0;
}











The GAPIShow example has support to access a 16-bpp display, which is the standard format for most Pocket PCs. I'll leave it to you to extend GAPIShow to other screen formats.

The code to draw in the frame buffer is isolated to three routines: InitScreen_16, DrawScreen_16, and ClearScreen_16. The _16 suffix indicates that the routines assume a 16-bpp screen. You can change the code to support 8-bpp displays by simply changing the cast of the writing of each pixel and modifying the pixel formation routine in ClearScreen_16. Although this example supports it, other pixel formats can be supported with very basic changes. You might notice the writing of the pixel in the InitScreen_16 routine is enclosed in a __try block to detect exceptions. This is a helpful technique for catching problems with the code that computes the pixel location in the buffer next chapter, I step back from application programming and look at system programming issues. Chapter 21 explains how the different components of Windows CE work together while presenting a unified Win32-compatible operating system.

/ 169