www.pudn.com > BaseSample.rar > CrosswordSample.cpp
// CrosswordSample.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "CrosswordSample.h"
const int MAX_LOADSTRING = 100;
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: WinMain
//
// PURPOSE: Entry point of our application.
//
int WINAPI WinMain( HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HACCEL hAccelTable;
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_CROSSWORDSAMPLE);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return msg.wParam;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: MyRegisterClass
//
// PURPOSE: Registers the window class for the main window.
//
// ON ENTRY:
// HINSTANCE hInstance: the application instance.
// LPTSTR szWindowClass: the window class name to register.
//
// ON EXIT:
// The window class is registered and the return value
// from RegisterClass is returned.
//
ATOM MyRegisterClass(HINSTANCE hInstance, LPTSTR szWindowClass)
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CROSSWORDSAMPLE));
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = szWindowClass;
return RegisterClass(&wc);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: CreateRpCommandBar
//
// PURPOSE: Creates the command bar at the bottom of the window.
//
// ON ENTRY:
// HWND hwnd: the window which will recieve the command bar.
// g_hInst: the application instance.
//
// ON EXIT:
// The HWND of the command bar.
//
HWND CreateRpCommandBar(HWND hwnd)
{
SHMENUBARINFO mbi;
memset(&mbi, 0, sizeof(SHMENUBARINFO));
mbi.cbSize = sizeof(SHMENUBARINFO);
mbi.hwndParent = hwnd;
mbi.nToolBarId = IDM_MENU;
mbi.hInstRes = g_hInst;
mbi.nBmpId = 0;
mbi.cBmpImages = 0;
if (!SHCreateMenuBar(&mbi))
return NULL;
CommandBar_AddBitmap (mbi.hwndMB, g_hInst, IDR_TOOLBAR1, 4, 16, 15);
return mbi.hwndMB;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: InitInstance
//
// PURPOSE: Saves instance handle to g_hInst and creates the main window.
//
// ON ENTRY:
// HINSTANCE hInstance: the application instance.
// int nCmdShow: the hide/show parameter from WinMain.
//
// ON EXIT:
// g_hInst is initialized.
// Returns TRUE if all initialization completed successfully.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd = NULL;
TCHAR szTitle[MAX_LOADSTRING];
TCHAR szWindowClass[MAX_LOADSTRING];
g_hInst = hInstance;
LoadString(hInstance, IDC_CROSSWORDSAMPLE, szWindowClass, MAX_LOADSTRING);
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
//
// If the app is already running, find it and bring it to the foreground.
// (the "| 0x01" is used to bring any owned windows to the foreground).
//
hWnd = FindWindow(szWindowClass, szTitle);
if (hWnd)
{
SetForegroundWindow((HWND)((ULONG) hWnd | 0x00000001));
return 0;
}
//
// Create the main window.
//
MyRegisterClass(hInstance, szWindowClass);
hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
//
// Initialize the crossword data structures.
//
CreateCrossword();
//
// Create all child windows.
//
CreateWindow(_T("Edit"), NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER | ES_AUTOHSCROLL,
8, 4, 170, 20,
hWnd, (HMENU)IDC_MAIN_EDIT_BOX, g_hInst, 0);
CreateWindow(_T("Button"), _T(""),
WS_VISIBLE | WS_CHILD | BS_OWNERDRAW,
183, 4, 50, 20,
hWnd, (HMENU)IDC_MAIN_ENTER_BUTTON, g_hInst, 0);
//
// This magic control automatically brings up the SIP when focus
// is transferred to an editable control.
//
SHInitExtraControls();
CreateWindow(WC_SIPPREF, NULL,
WS_CHILD,
0,0,0,0,
hWnd, NULL, g_hInst, 0);
//
// Create the default font.
//
LOGFONT lf;
memset(&lf, 0, sizeof(lf));
lf.lfHeight = -12;
_tcscpy(lf.lfFaceName, _T("Courier New"));
lf.lfWeight = FW_NORMAL;
g_hFont = CreateFontIndirect(&lf);
//
// Load the images for the ENTER button.
//
g_hImageList = ImageList_LoadImage(
g_hInst,
MAKEINTRESOURCE(IDB_ENTERBTN),
46,
0,
CLR_NONE,
IMAGE_BITMAP,
0);
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: CreateCrossword
//
// PURPOSE: Creates the crossword bitmaps and does all initial drawing.
//
// ON EXIT: g_hMemDC, g_hMemBitmap, g_selectedClue, g_crossword
// are initialized.
//
void CreateCrossword()
{
HDC hScreenDC = GetWindowDC(NULL);
g_hMemDC = CreateCompatibleDC(hScreenDC);
g_hMemBitmap = CreateCompatibleBitmap(hScreenDC, 240, 320);
ReleaseDC(NULL, hScreenDC);
SelectObject(g_hMemDC, g_hMemBitmap);
int iHint = 0;
//
// Fill in each g_hints structure from left to right (for ACROSS hints).
//
for (int y = 0; y < CROSSWORD_Y - 1; y++)
{
int cLetters = 0;
for (int x = 0; x < CROSSWORD_X; x++)
{
if (g_crosswordSolution[y][x] == '*')
{
SelectObject(g_hMemDC, GetStockObject(BLACK_BRUSH));
if (cLetters > 1)
{
g_hints[iHint].x = x - cLetters;
g_hints[iHint].y = y;
g_hints[iHint].cLetters = cLetters;
g_hints[iHint].fDown = false;
iHint++;
}
cLetters = 0;
}
else
{
SelectObject(g_hMemDC, GetStockObject(WHITE_BRUSH));
cLetters++;
}
//
// Also draw the offscreen crossword bitmap during this pass.
//
RECT r;
r.left = 16 * x;
r.top = 16 * y;
r.right = r.left + 17;
r.bottom = r.top + 17;
Rectangle(g_hMemDC, r.left, r.top, r.right, r.bottom);
g_crossword[y][x] = ' ';
}
}
//
// Fill in each g_hints structure from top to bottom (for DOWN hints).
//
for (int x = 0; x < CROSSWORD_X - 1; x++)
{
int cLetters = 0;
for (int y = 0; y < CROSSWORD_Y; y++)
{
if (g_crosswordSolution[y][x] == '*')
{
if (cLetters > 1)
{
g_hints[iHint].x = x;
g_hints[iHint].y = y - cLetters;
g_hints[iHint].cLetters = cLetters;
g_hints[iHint].fDown = true;
iHint++;
}
cLetters = 0;
}
else
{
cLetters++;
}
}
}
g_selectedHint = -1;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: DrawHint
//
// PURPOSE: Draws the row or column specified by the given hint onto the
// crossword offscreen buffer (g_hMemDC).
//
// ON ENTRY:
// HWND hWnd: the main window app (we need this to invalidate the window
// after we are done, so that it will send WM_PAINT).
// INT nHint: the hint whose row or column we wish to draw.
// COLORREF rgbColor: the background color of the squares we draw.
//
void DrawHint (HWND hWnd, INT nHint, COLORREF rgbColor)
{
if (nHint == -1) return;
HBRUSH hBrush = CreateSolidBrush(rgbColor);
for (int i = 0; i < g_hints[nHint].cLetters; i++)
{
RECT r;
int x = g_hints[nHint].x + (g_hints[nHint].fDown ? 0 : i);
int y = g_hints[nHint].y + (g_hints[nHint].fDown ? i : 0);
r.left = x * 16 + 1;
r.top = y * 16 + 1;
r.right = r.left + 15;
r.bottom = r.top + 15;
SetBkMode(g_hMemDC, TRANSPARENT);
FillRect(g_hMemDC, &r, hBrush);
DrawText(g_hMemDC, &g_crossword[y][x], 1, &r, DT_CENTER | DT_VCENTER);
//
// Invalidate the rectangle on the screen.
//
r.left += 8;
r.right += 8;
r.top += 26;
r.bottom += 26;
InvalidateRect(hWnd, &r, false);
}
DeleteObject(hBrush);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: PropSheetCallback.
//
// PURPOSE: Callback for the Tools / Options property sheet used by
// OnCommandToolsOptions. This is necessary so that dialog tabs get
// drawn in the flat PocketPC style.
//
int PropSheetCallback(HWND hwndDlg, UINT message, LPARAM lParam)
{
if (message == PSCB_GETVERSION)
{
return COMCTL32_VERSION;
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnCommandToolsOptions
//
// PURPOSE: Creates the dialog window for Tools / Options.
//
// ON ENTRY:
// HWND hWnd: the main window app.
//
void OnCommandToolsOptions(HWND hWnd)
{
PROPSHEETPAGE psp[2];
psp[0].dwSize = sizeof(psp[0]);
psp[0].dwFlags = PSP_DEFAULT;
psp[0].hInstance = g_hInst;
psp[0].pszTemplate = MAKEINTRESOURCE(IDD_TOOLS_OPTIONS_1);
psp[0].pfnDlgProc = (DLGPROC)&ToolsOptionsDialog1;
psp[1].dwSize = sizeof(psp[1]);
psp[1].dwFlags = PSP_DEFAULT;
psp[1].hInstance = g_hInst;
psp[1].pszTemplate = MAKEINTRESOURCE(IDD_TOOLS_OPTIONS_2);
psp[1].pfnDlgProc = (DLGPROC)&ToolsOptionsDialog2;
//
// See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/win_ce/htm/pwc_propertysheets.asp
// for more information about PSH_MAXIMIZE and handling PSCB_GETVERSION in the
// PropertySheet callback.
//
PROPSHEETHEADER psh;
psh.dwSize = sizeof(psh);
psh.dwFlags = PSH_DEFAULT | PSH_PROPSHEETPAGE | PSH_MAXIMIZE | PSH_NOAPPLYNOW | PSH_USECALLBACK;
psh.hwndParent = hWnd;
psh.hInstance = g_hInst;
psh.pszCaption = _T("Tools / Options");
psh.nPages = 2;
psh.nStartPage = 0;
psh.ppsp = &psp[0];
psh.pfnCallback = PropSheetCallback;
PropertySheet(&psh);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnClickEnterButton
//
// PURPOSE: Called when the enter button is clicked. Copies the text in the
// g_hwndEditBox to the crossword offscreen buffer (using DrawHint).
//
// ON ENTRY:
// HWND hWnd: the main window app.
// g_selectedHint: the destination row or column the text will
// be copied to.
//
// ON EXIT:
// The edit box is cleared.
//
void OnClickEnterButton(HWND hWnd)
{
WCHAR szBuffer[80];
SendDlgItemMessage(hWnd, IDC_MAIN_EDIT_BOX, WM_GETTEXT, sizeof(szBuffer)/sizeof(WCHAR), (LPARAM)szBuffer);
SendDlgItemMessage(hWnd, IDC_MAIN_EDIT_BOX, WM_SETTEXT, 0, (LPARAM)_T(""));
if (g_selectedHint == -1) return;
for (int i = 0; i < g_hints[g_selectedHint].cLetters; i++)
{
if (szBuffer[i] == '\0')
{
break;
}
int x = g_hints[g_selectedHint].x + (g_hints[g_selectedHint].fDown ? 0 : i);
int y = g_hints[g_selectedHint].y + (g_hints[g_selectedHint].fDown ? i : 0);
g_crossword[y][x] = towupper(szBuffer[i]);
}
DrawHint(hWnd, g_selectedHint, RGB(128,0,0));
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnLButtonDown
//
// PURPOSE: Called when the stylus is tapped on the screen. Selects a row or
// column based on the location of the tap.
//
// ON ENTRY:
// HWND hWnd: the window which was tapped.
// INT x: the x location of the screen tap in pixels.
// INT y: the y location of the screen tap in pixels.
//
// ON EXIT:
// g_selectedHint equals the location of the screen tap.
//
void OnLButtonDown(HWND hWnd, INT x, INT y)
{
x = (x - 8) / 16;
y = (y - 26) / 16;
if (x < 0 || y < 0 || x >= CROSSWORD_X - 1 || y >= CROSSWORD_Y - 1)
{
return;
}
//
// Erase the old hint.
//
DrawHint(hWnd, g_selectedHint, RGB(255,255,255));
//
// Search for the hint that we clicked.
//
int oldSelectedHint = g_selectedHint;
g_selectedHint = -1;
for (int i = 0; i < sizeof(g_hints) / sizeof(CROSSWORD_HINT); i++)
{
if (i == oldSelectedHint) continue;
if ((!g_hints[i].fDown && y == g_hints[i].y &&
x >= g_hints[i].x && x < g_hints[i].x + g_hints[i].cLetters) ||
(g_hints[i].fDown && x == g_hints[i].x &&
y >= g_hints[i].y && y < g_hints[i].y + g_hints[i].cLetters))
{
g_selectedHint = i;
break;
}
}
//
// Draw in this new hint.
//
DrawHint(hWnd, g_selectedHint, RGB(128, 0, 0));
if (g_selectedHint != -1)
{
SendDlgItemMessage(hWnd, IDC_MAIN_EDIT_BOX, EM_LIMITTEXT, g_hints[g_selectedHint].cLetters, 0);
}
//
// Invalidate the hint area so we redraw.
//
RECT r = { 0, 189, 240, 320 };
InvalidateRect(hWnd, &r, FALSE);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: OnPaint
//
// PURPOSE: Paints the main application window.
//
// ON ENTRY:
// HWND hWnd: the window to paint.
//
void OnPaint(HWND hWnd)
{
PAINTSTRUCT ps;
HDC hDC = BeginPaint(hWnd, &ps);
//
// Draw background.
//
HBITMAP hBMP = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BACKGROUND_1));
HDC hMemDC = CreateCompatibleDC(NULL);
HBITMAP hOldBMP = (HBITMAP)SelectObject(hMemDC, hBMP);
BitBlt(hDC, 0, 0, 240, 320, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOldBMP);
DeleteObject(hBMP);
DeleteDC(hMemDC);
//
// Draw crossword.
//
TransparentImage(hDC, 8, 26, 14 * 16 + 1, 10 * 16 + 1,
g_hMemDC, 0, 0, 14 * 16 + 1, 10 * 16 + 1, RGB(255, 255, 255));
POINT line[] = { {0, 188}, {240, 188} };
Polyline(hDC, line, 2);
//
// Erase the hint area using a pattern brush.
//
RECT r = { 25, 200, 230, 245 };
HBITMAP hPattern = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_PATTERN));
HBRUSH hNewBrush = CreatePatternBrush(hPattern);
HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, hNewBrush);
Rectangle(hDC, r.left, r.top, r.right, r.bottom);
SelectObject(hDC, hOldBrush);
DeleteObject(hNewBrush);
DeleteObject(hPattern);
if (g_selectedHint != -1)
{
//
// Print the hint out at bottom.
//
r.left += 4;
r.right -= 4;
SetBkMode(hDC, TRANSPARENT);
HFONT hOldFont = (HFONT)SelectObject(hDC, g_hFont);
DrawText(hDC, g_hints[g_selectedHint].szHint, -1, &r, DT_TOP | DT_LEFT | DT_WORDBREAK);
SelectObject(hDC, hOldFont);
//
// Display an arrow next to the hint.
//
POINT rgArrow[] = { {0,3}, {6,3}, {6,0}, {12, 5}, {6, 10}, {6, 7}, {0, 7} };
for (int i = 0; i < 7; i++)
{
//
// A vertical arrow is a horizontal arrow with X and Y flipped.
//
if (g_hints[g_selectedHint].fDown)
{
int t = rgArrow[i].x;
rgArrow[i].x = rgArrow[i].y;
rgArrow[i].y = t;
}
rgArrow[i].x += 5;
rgArrow[i].y += 200;
}
Polygon(hDC, rgArrow, 7);
}
EndPaint(hWnd, &ps);
}
//////////////////////////////////////////////////////////////////////////////
// FUNCTION: WndProc()
//
// PURPOSE: Processes messages for the main window.
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
g_hwndCB = CreateRpCommandBar(hWnd);
memset (&g_sai, 0, sizeof (g_sai));
g_sai.cbSize = sizeof (g_sai);
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_MAIN_ENTER_BUTTON:
OnClickEnterButton(hWnd);
break;
case ID_TOOLS_OPTIONS:
OnCommandToolsOptions(hWnd);
break;
case ID_TOOLS_ABOUT:
DialogBox(g_hInst, MAKEINTRESOURCE(IDD_TOOLS_ABOUT), hWnd, &ToolsAboutDialog);
break;
}
break;
case WM_DRAWITEM:
{
//
// Draws the Enter button.
//
LPDRAWITEMSTRUCT lpDis = (LPDRAWITEMSTRUCT)lParam;
DrawEdge(lpDis->hDC, &lpDis->rcItem,
(lpDis->itemState & ODS_SELECTED) ? EDGE_SUNKEN : EDGE_RAISED,
BF_RECT);
ImageList_Draw(g_hImageList,
(lpDis->itemState & ODS_SELECTED) ? 0 : 1,
lpDis->hDC, 2, 2, ILD_NORMAL);
}
break;
case WM_PAINT:
OnPaint(hWnd);
break;
case WM_LBUTTONDOWN:
OnLButtonDown(hWnd, LOWORD(lParam), HIWORD(lParam));
break;
case WM_DESTROY:
CommandBar_Destroy(g_hwndCB);
PostQuitMessage(0);
break;
case WM_ACTIVATE:
SHHandleWMActivate(hWnd, wParam, lParam, &g_sai, FALSE);
break;
case WM_SETTINGCHANGE:
SHHandleWMSettingChange(hWnd, wParam, lParam, &g_sai);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}