|
|
#include <windows.h>
#include <port1632.h>
#include "cards.h"
#include "golf.h"
#include "cdt.h"
#include "stdlib.h"
#define ININAME "entpack.ini"
typedef INT X; typedef INT Y; typedef INT DX; typedef INT DY;
// ReCt structure
typedef struct _rc { X xLeft; Y yTop; X xRight; Y yBot; } RC;
#define abs(x) (((x) < 0) ? (-(x)) : (x))
#define IDCARDBACK 65
#define APPTITLE "Golf"
LRESULT APIENTRY WndProc (HWND, UINT, WPARAM, LPARAM) ; VOID Deal(VOID); VOID InitBoard(VOID); VOID DrawLayout(HDC hDC); VOID DrawPile(HDC hDC); VOID UpdateDeck(HDC hDC); BOOL UpdateLayout(HDC hDC, INT column, BOOL bValidate); VOID UndoMove(HDC hDC); VOID DoWinEffects(HDC hDC); VOID UpdateScore(HDC hDC); VOID APIENTRY Help(HWND hWnd, UINT wCommand, ULONG_PTR lParam); INT_PTR APIENTRY BackDlgProc(HANDLE hdlg, UINT wm, WPARAM wParam, LPARAM lParam); BOOL FDrawFocus(HDC hdc, RC *prc, BOOL fFocus); VOID ChangeBack(WORD wNewDeckBack); VOID DoBacks(VOID); VOID MyDrawText(HDC hDC, LPSTR lpBuf, INT w, LPRECT lpRect, WORD wFlags); INT Message(HWND hWnd, WORD wId, WORD wFlags); BOOL fDialog(INT id,HWND hwnd,DLGPROC fpfn);
BOOL APIENTRY cdtDrawExt(HDC hdc, INT x, INT y, INT dx, INT dy, INT cd, INT mode, DWORD rgbBgnd); BOOL APIENTRY cdtAnimate(HDC hdc, INT cd, INT x, INT y, INT ispr); VOID DrawAnimate(INT cd, MPOINT *ppt, INT iani); BOOL DeckAnimate(INT iqsec); VOID APIENTRY TimerProc(HWND hwnd, UINT wm, UINT_PTR id, DWORD dwTime); VOID SaveState(VOID); VOID RestoreState(VOID); LPSTR lstrtok(LPSTR lpStr, LPSTR lpDelim); static BOOL IsInString(CHAR c, LPSTR s); VOID DrawGameOver(HDC hDC); INT_PTR APIENTRY RecordDlgProc(HANDLE hdlg, UINT wm, WPARAM wParam, LPARAM lParam); LRESULT APIENTRY ReadOnlyProc(HWND hwnd, UINT wMessage, WPARAM wParam, LPARAM lParam); VOID MarkControlReadOnly(HWND hwndCtrl, BOOL bReadOnly);
BOOL CheckGameOver(HDC hDC);
INT layout[52], pile[52], col[7]; INT deckStart, deckEnd, pilePos, nCards; INT xClient, yClient, xCard, yCard; INT xPileInc, yPileInc; INT nCardsLeft[7], nWins, nGames;
DWORD dwBkgnd; RECT deckRect, cntRect, pileRect, colRect[7]; WORD wErrorMessages; WORD wDeckBack = IDCARDBACK; FARPROC lpfnTimerProc;
typedef struct tagUndoRec { enum { Layout, Deck } origin; INT column; } UndoRec; UndoRec undo[52]; INT undoPos;
HWND hWnd; HANDLE hMyInstance; CHAR szAppName[80]; CHAR szOOM[256]; CHAR szGameOver[80], szGameOverS[80], szRecordTitle[80]; BOOL bGameInProgress = FALSE;
MMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow) /* { */ MSG msg ; WNDCLASS wndclass ; HANDLE hAccel;
if (!LoadString(hInstance, IDSOOM, szOOM, 256) || !LoadString(hInstance, IDSAppName, szAppName, 80) || !LoadString(hInstance, IDSGameOver, szGameOver, 80) || !LoadString(hInstance, IDSGameOverS, szGameOverS, 80) || !LoadString(hInstance, IDSRecordTitle, szRecordTitle, 80) ) return FALSE;
if (hPrevInstance) { hWnd = FindWindow(szAppName, NULL); if (hWnd) { hWnd = GetLastActivePopup(hWnd); BringWindowToTop(hWnd); if (IsIconic(hWnd)) ShowWindow(hWnd, SW_RESTORE); } return FALSE; }
wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (hInstance, "Golf") ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = CreateSolidBrush(dwBkgnd = RGB(0,130,0)); wndclass.lpszMenuName = szAppName ; wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass)) return FALSE ;
hWnd = CreateWindow (szAppName, APPTITLE, WS_OVERLAPPEDWINDOW | WS_MAXIMIZE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ;
if (!hWnd) return FALSE;
hAccel = LoadAccelerators(hInstance, szAppName);
if (!hAccel) return FALSE;
if(SetTimer(hWnd, 666, 250, TimerProc) == 0) { return FALSE; }
RestoreState();
ShowWindow (hWnd, SW_SHOWMAXIMIZED) ; UpdateWindow (hWnd) ;
hMyInstance = hInstance; while (GetMessage (&msg, NULL, 0, 0)) { if (!TranslateAccelerator(hWnd, hAccel, &msg)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } } return (INT) msg.wParam ; }
VOID APIENTRY Help(HWND hWnd, UINT wCommand, ULONG_PTR lParam) { CHAR szHelpPath[100], *pPath;
pPath = szHelpPath + GetModuleFileName(hMyInstance, szHelpPath, 99); if (pPath != szHelpPath) { while (*pPath-- != '.') ; ++pPath; *++pPath = 'H'; *++pPath = 'L'; *++pPath = 'P'; *++pPath = '\0';
WinHelp(hWnd, szHelpPath, wCommand, lParam); } }
VOID MyDrawText(HDC hDC, LPSTR lpBuf, INT w, LPRECT lpRect, WORD wFlags) { DWORD dwOldBk, dwOldTextColor; HBRUSH hBrush, hOldBrush;
dwOldBk = SetBkColor(hDC, dwBkgnd); dwOldTextColor = SetTextColor(hDC, RGB(255,255,255)); if (hBrush = CreateSolidBrush(dwBkgnd)) { if (hOldBrush = SelectObject(hDC, hBrush)) { PatBlt(hDC, lpRect->left, lpRect->top, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, PATCOPY); SelectObject(hDC, hOldBrush); } DeleteObject(hBrush); } DrawText(hDC, lpBuf, w, lpRect, wFlags); SetBkColor(hDC, dwOldBk); SetTextColor(hDC, dwOldTextColor); }
VOID UpdateScore(HDC hDC) { CHAR buffer[5];
if (deckEnd - deckStart + 1) { wsprintf(buffer, "%2d", deckEnd - deckStart + 1); MyDrawText(hDC, buffer, -1, &cntRect, DT_RIGHT | DT_NOCLIP); } }
VOID DisplayWins(VOID) { fDialog(2, hWnd, RecordDlgProc); }
LRESULT APIENTRY WndProc ( HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { HDC hDC ; HMENU hMenu; PAINTSTRUCT ps ; SHORT i, j ; MPOINT pt; POINT mpt; static BOOL fBoard; FARPROC lpAbout; HANDLE hLib;
switch (iMessage) { case WM_CREATE: cdtInit(&xCard, &yCard); Deal(); fBoard = FALSE; break;
case WM_SIZE: xClient = LOWORD(lParam); yClient = HIWORD(lParam); break;
case WM_PAINT: hDC = BeginPaint (hWnd, &ps) ; if (!fBoard) { InitBoard(); fBoard = TRUE; } DrawLayout(hDC); DrawPile(hDC); EndPaint(hWnd, &ps); break;
case WM_LBUTTONDOWN: pt.x = LOWORD(lParam); pt.y = HIWORD(lParam);
MPOINT2POINT(pt, mpt); if (PtInRect(&deckRect, mpt)) { SendMessage(hWnd, WM_KEYDOWN, VK_SPACE, 0L); break; }
i = 0; for (j = 0; j < 7; ++j) if (PtInRect(colRect + j, mpt)) { i = (SHORT) (j + 1); break; } if (i) SendMessage(hWnd, WM_KEYDOWN, '0' + i, 0L);
break;
case WM_INITMENU: hMenu = GetMenu(hWnd); EnableMenuItem(hMenu, IDM_OPTIONSUNDO, MF_BYCOMMAND | undoPos ? MF_ENABLED : MF_GRAYED); CheckMenuItem(hMenu, IDM_OPTIONSERROR, wErrorMessages ? MF_CHECKED : MF_UNCHECKED); break;
case WM_RBUTTONDOWN: SendMessage(hWnd, WM_KEYDOWN, VK_SPACE, 0L); break;
case WM_KEYDOWN: hDC = GetDC(hWnd);
switch (wParam) { case VK_ESCAPE: ShowWindow(hWnd, SW_MINIMIZE); break;
case VK_SPACE: UpdateDeck(hDC); break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': UpdateLayout(hDC, (CHAR) wParam - '1', FALSE); break; }
ReleaseDC(hWnd, hDC); break;
case WM_COMMAND: switch(GET_WM_COMMAND_ID(wParam, lParam)) { case IDM_NEWGAME: Deal(); fBoard = FALSE; InvalidateRect(hWnd, NULL, TRUE); break;
case IDM_EXIT: DestroyWindow(hWnd); break;
case IDM_OPTIONSDECK: DoBacks(); break;
case IDM_GAMERECORD: DisplayWins(); break;
case IDM_ABOUT: hLib = MLoadLibrary("shell32.dll"); if (hLib < (HANDLE)32) break;
lpAbout = GetProcAddress(hLib, (LPSTR)"ShellAboutA");
if (lpAbout) { (*lpAbout)(hWnd, szAppName, "by Ken Sykes", LoadIcon(hMyInstance, szAppName)); }
FreeLibrary(hLib); break;
case MENU_INDEX: Help(hWnd, HELP_INDEX, 0L); break;
case MENU_HOWTOPLAY: Help(hWnd, HELP_CONTEXT, 1L); break;
case MENU_COMMANDS: Help(hWnd, HELP_CONTEXT, 2L); break;
case MENU_USINGHELP: Help(hWnd, HELP_HELPONHELP, 0L); break;
case IDM_OPTIONSERROR: wErrorMessages = (WORD) ~wErrorMessages; break;
case IDM_OPTIONSUNDO: hDC = GetDC(hWnd); UndoMove(hDC); ReleaseDC(hWnd, hDC); break;
} break;
case WM_DESTROY: KillTimer(hWnd, 666); FreeProcInstance(lpfnTimerProc); cdtTerm(); Help(hWnd, HELP_QUIT, 0L); SaveState(); PostQuitMessage (0) ; break ;
default: return DefWindowProc (hWnd, iMessage, wParam, lParam) ; } return 0L ; }
VOID Deal(VOID) { INT i, p1, p2, tmp;
/* stuff cards into layout */ for (i = 0; i < 52; ++i) layout[i] = i;
/* shuffle them around */ srand(LOWORD(GetTickCount())); for (i = 0; i < 500; ++i) { p1 = rand() % 52; p2 = rand() % 52; tmp = layout[p1]; layout[p1] = layout[p2]; layout[p2] = tmp; }
/* initialize column pointers */ for (i = 0; i < 7; ++i) col[i] = i * 5 + 4; deckStart = 35; deckEnd = 51; pilePos = 0;
/* turn over the first card */ pile[pilePos] = layout[deckEnd--]; nCards = 35;
bGameInProgress = TRUE; }
VOID InitBoard(VOID) { INT xPos, yPos; INT xStep, yStep, col;
xPos = 30; yPos = yClient - yCard - 30; deckRect.left = xPos; deckRect.right = xPos + xCard; deckRect.top = yPos; deckRect.bottom = yPos + yCard;
cntRect.left = xPos; cntRect.right = cntRect.left + xCard; cntRect.top = yPos + yCard + 5; cntRect.bottom = cntRect.top + 20;
xPos += xCard + 20; pileRect.left = xPos; pileRect.right = xPos + xCard; pileRect.top = yPos; pileRect.bottom = yPos + yCard; xPileInc = (xClient - 2 * xCard - 50) / 52; yPileInc = 18;
xStep = xCard + 10; yStep = yPileInc;
for (col = 0, xPos = 30; col < 7; ++col, xPos += xStep) { yPos = 10 + 5 * yStep; colRect[col].left = xPos; colRect[col].right = xPos + xCard; colRect[col].top = yPos - yStep; colRect[col].bottom = yPos - yStep + yCard; }
undoPos = 0;
}
VOID DrawLayout(HDC hDC) { INT xStep, yStep, column, i, *card; RECT rect;
xStep = xCard + 10; yStep = yPileInc;
for (column = 0; column < 7; ++column) { /* if column is empty skip it */ if (col[column] < 5 * column) continue;
/* start rectangle at top of column */ rect = colRect[column]; OffsetRect(&rect, 0, -yStep * (col[column] - 5 * column));
card = layout + 5 * column; while (rect.top <= colRect[column].top) { cdtDraw(hDC, rect.left, rect.top, *card++, faceup, dwBkgnd); OffsetRect(&rect, 0, yStep); } } }
VOID DrawPile(HDC hDC) { INT i, xPos;
if (bGameInProgress) cdtDraw(hDC, deckRect.left, deckRect.top, wDeckBack, facedown, dwBkgnd); else DrawGameOver(hDC);
UpdateScore(hDC);
for (i = 0, xPos = 50 + xCard; i <= pilePos; ++i, xPos += xPileInc) cdtDraw(hDC, xPos, pileRect.top, pile[i], faceup, dwBkgnd); }
VOID UpdateDeck(HDC hDC) { /* if deck is empty return */ if (deckEnd < deckStart) return;
/* move card to pile */ pile[++pilePos] = layout[deckEnd--];
/* fill in undo buffer */ undo[undoPos++].origin = Deck;
/* draw new card */ OffsetRect(&pileRect, xPileInc, 0); cdtDraw(hDC, pileRect.left, pileRect.top, pile[pilePos], faceup, dwBkgnd);
/* update counter */ UpdateScore(hDC);
/* if we turned up last card remove facedown bitmap */ CheckGameOver(hDC); }
BOOL CheckGameOver(HDC hDC) { RECT rect; INT i;
if (deckEnd >= deckStart) return FALSE;
SetBkColor(hDC, dwBkgnd); cdtDraw(hDC, 30, yClient - yCard - 30, 0, remove, dwBkgnd); rect = cntRect; MyDrawText(hDC, "", 0, &rect, DT_LEFT | DT_NOCLIP);
for (i = 0; i < 7; ++i) if (UpdateLayout(hDC, i, TRUE)) return FALSE;
bGameInProgress = FALSE;
DrawGameOver(hDC);
++nCardsLeft[(nCards - 1) / 5]; ++nGames;
return TRUE; }
VOID DrawGameOver(HDC hDC) { CHAR buffer[30]; RECT rect;
wsprintf(buffer, (nCards == 1) ? szGameOverS : szGameOver, nCards); rect = cntRect; rect.left = 0; rect.right = xClient; MyDrawText(hDC, buffer, -1, &rect, DT_CENTER | DT_NOCLIP); }
BOOL UpdateLayout(HDC hDC, INT column, BOOL bValidate) { INT colpos, dist;
/* if column is empty, ignore */ colpos = col[column]; if (colpos < 0 || (colpos / 5) != column) return FALSE;
/* if card on top of pile is a king, don't move card to pile */ if (CardRank(pile[pilePos]) == king) { if (wErrorMessages && !bValidate) Message(hWnd, IDSNoCardOnKing, MB_OK); return FALSE; }
/* if card is not adjacent, don't move it to pile */ dist = IndexValue(pile[pilePos], ACELOW) - IndexValue(layout[colpos], ACELOW); if (abs(dist) != 1) { if (wErrorMessages && !bValidate) Message(hWnd, IDSNotAdjacent, MB_OK); return FALSE; }
if (bValidate) return TRUE;
/* move card to pile */ pile[++pilePos] = layout[colpos--]; col[column] = colpos;
/* fill in undo buffer */ undo[undoPos].origin = Layout; undo[undoPos++].column = column;
/* remove card from layout */ SetBkColor(hDC, dwBkgnd); cdtDraw(hDC, colRect[column].left, colRect[column].top, pile[pilePos], remove, dwBkgnd);
if (colpos >= 5 * column) { OffsetRect(colRect + column, 0, -yPileInc); cdtDraw(hDC, colRect[column].left, colRect[column].top, layout[colpos], faceup, dwBkgnd); }
/* draw card on pile */ OffsetRect(&pileRect, xPileInc, 0); cdtDraw(hDC, pileRect.left, pileRect.top, pile[pilePos], faceup, dwBkgnd);
/* decrement # of cards */ --nCards;
if (!nCards) DoWinEffects(hDC);
/* if deck is empty display game over message */ CheckGameOver(hDC);
return TRUE; }
VOID UndoMove(HDC hDC) { CHAR buffer[10]; RECT *pRect, rect; INT column; HBRUSH hBrush;
--undoPos;
/* erase the top card on the pile */ SetBkColor(hDC, dwBkgnd); cdtDraw(hDC, pileRect.left, pileRect.top, pile[pilePos], remove, dwBkgnd); OffsetRect(&pileRect, -xPileInc, 0);
/* redraw the card that will now be at top of pile */ if (pilePos) cdtDraw(hDC, pileRect.left, pileRect.top, pile[pilePos-1], faceup, dwBkgnd);
if (!bGameInProgress) { rect = cntRect; rect.left = rect.right + 1; rect.right = xClient; rect.bottom = yClient; hBrush = CreateSolidBrush(dwBkgnd); if (hBrush) { FillRect(hDC, &rect, hBrush); DeleteObject(hBrush); }
if (nCards) --nCardsLeft[(nCards - 1) / 5]; else --nWins; --nGames;
bGameInProgress = TRUE; }
/* move the card back where it belongs */ if (undo[undoPos].origin == Deck) { if (deckEnd < deckStart) cdtDraw(hDC, 30, yClient - yCard - 30, wDeckBack, facedown, dwBkgnd);
layout[++deckEnd] = pile[pilePos--]; UpdateScore(hDC); } else { column = undo[undoPos].column; pRect = colRect + column; if (col[column] >= 5 * column) OffsetRect(pRect, 0, yPileInc); cdtDraw(hDC, pRect->left, pRect->top, pile[pilePos], faceup, dwBkgnd); layout[++col[undo[undoPos].column]] = pile[pilePos--];
++nCards; } }
VOID DoWinEffects(HDC hDC) { Message(hWnd, IDSWinner, MB_OK); ++nWins; ++nGames;
undoPos = 0; }
VOID DoBacks() { DialogBox(hMyInstance, MAKEINTRESOURCE(1), hWnd, BackDlgProc);
}
INT_PTR APIENTRY BackDlgProc(HANDLE hdlg, UINT wm, WPARAM wParam, LPARAM lParam) { static INT modeNew; INT iback; MEASUREITEMSTRUCT FAR *lpmi; DRAWITEMSTRUCT FAR *lpdi; HBRUSH hbr; RC rc, rcCrd; HDC hdc; INT i;
switch(wm) { case WM_INITDIALOG: modeNew = wDeckBack; SetFocus(GetDlgItem(hdlg, modeNew)); return FALSE;
case WM_COMMAND:
if(GET_WM_COMMAND_ID(wParam, lParam) >= IDFACEDOWNFIRST && GET_WM_COMMAND_ID(wParam, lParam) <= IDFACEDOWN12) { modeNew = GET_WM_COMMAND_ID(wParam, lParam) ; if (GET_WM_COMMAND_CMD(wParam, lParam) == BN_DOUBLECLICKED) { ChangeBack((WORD)modeNew); EndDialog(hdlg, 0); } } else switch(wParam) { case IDOK: ChangeBack((WORD)modeNew); /* fall thru */
case IDCANCEL: EndDialog(hdlg, 0); break;
} break;
case WM_MEASUREITEM: lpmi = (MEASUREITEMSTRUCT FAR *)lParam; lpmi->CtlType = ODT_BUTTON; lpmi->itemWidth = xCard /* 32 */; lpmi->itemHeight = yCard /* 54 */; break; case WM_DRAWITEM: lpdi = (DRAWITEMSTRUCT FAR *)lParam;
CopyRect((LPRECT) &rc, &lpdi->rcItem); rcCrd = rc; InflateRect((LPRECT) &rcCrd, -3, -3); hdc = lpdi->hDC;
if (lpdi->itemAction == ODA_DRAWENTIRE) { cdtDrawExt(hdc, rcCrd.xLeft, rcCrd.yTop, rcCrd.xRight-rcCrd.xLeft, rcCrd.yBot-rcCrd.yTop, lpdi->CtlID, FACEDOWN, 0L); FDrawFocus(hdc, &rc, lpdi->itemState & ODS_FOCUS); break; } if (lpdi->itemAction == ODA_SELECT) InvertRect(hdc, (LPRECT)&rcCrd);
if (lpdi->itemAction == ODA_FOCUS) FDrawFocus(hdc, &rc, lpdi->itemState & ODS_FOCUS);
break; default: return FALSE; } return TRUE; }
BOOL FDrawFocus(HDC hdc, RC *prc, BOOL fFocus) { HBRUSH hbr; RC rc; hbr = CreateSolidBrush(GetSysColor(fFocus ? COLOR_HIGHLIGHT : COLOR_WINDOW)); if(hbr == NULL) return FALSE; rc = *prc; FrameRect(hdc, (LPRECT) &rc, hbr); InflateRect((LPRECT) &rc, -1, -1); FrameRect(hdc, (LPRECT) &rc, hbr); DeleteObject(hbr); return TRUE; }
VOID ChangeBack(WORD wNewDeckBack) { HDC hDC;
wDeckBack = wNewDeckBack;
if (deckEnd < deckStart) return;
hDC = GetDC(hWnd); if (hDC) { cdtDraw(hDC, deckRect.left, deckRect.top, wDeckBack, facedown, dwBkgnd); ReleaseDC(hWnd, hDC); } }
INT Message(HWND hWnd, WORD wId, WORD wFlags) { static CHAR szBuf[256];
if (!LoadString(hMyInstance, wId, szBuf, 256) || wId == IDSOOM) { lstrcpy(szBuf, szOOM); wFlags = MB_ICONHAND | MB_SYSTEMMODAL; }
if (!(wFlags & MB_SYSTEMMODAL)) wFlags |= MB_TASKMODAL;
if (!(wFlags & (MB_ICONHAND | MB_ICONEXCLAMATION | MB_ICONINFORMATION))) wFlags |= MB_ICONEXCLAMATION;
return MessageBox(hWnd, szBuf, szAppName, wFlags); }
VOID DrawAnimate(INT cd, MPOINT *ppt, INT iani) { HDC hDC;
if(!(hDC = GetDC(hWnd))) return; cdtAnimate(hDC, cd, ppt->x, ppt->y, iani); ReleaseDC(hWnd, hDC); }
BOOL DeckAnimate(INT iqsec) { INT iani; MPOINT pt;
pt.x = (SHORT) deckRect.left; pt.y = (SHORT) deckRect.top;
switch(wDeckBack) { case IDFACEDOWN3: DrawAnimate(IDFACEDOWN3, &pt, iqsec % 4); break; case IDFACEDOWN10: // krazy kastle
DrawAnimate(IDFACEDOWN10, &pt, iqsec % 2); break;
case IDFACEDOWN11: // sanflipe
if((iani = (iqsec+4) % (50*4)) < 4) DrawAnimate(IDFACEDOWN11, &pt, iani); else // if a menu overlapps an ani while it is ani'ing, leaves deck
// bitmap in inconsistent state...
if(iani % 6 == 0) DrawAnimate(IDFACEDOWN11, &pt, 3); break; case IDFACEDOWN12: // SLIME
if((iani = (iqsec+4) % (15*4)) < 4) DrawAnimate(IDFACEDOWN12, &pt, iani); else // if a menu overlapps an ani while it is ani'ing, leaves deck
// bitmap in inconsistent state...
if(iani % 6 == 0) DrawAnimate(IDFACEDOWN12, &pt, 3); break; }
return TRUE; }
VOID APIENTRY TimerProc(HWND hwnd, UINT wm, UINT_PTR id, DWORD dwTime) { static INT x = 0;
if (deckEnd >= deckStart) DeckAnimate(x++); return; }
VOID SaveState(VOID) { CHAR sz[80];
wsprintf(sz, "%d %d %d %d %d %d %d %d %d", nGames, nWins, nCardsLeft[0], nCardsLeft[1], nCardsLeft[2], nCardsLeft[3], nCardsLeft[4], nCardsLeft[5], nCardsLeft[6]); WritePrivateProfileString(szAppName, "Stats", sz, ININAME);
wsprintf(sz, "%d %d", wErrorMessages, wDeckBack); WritePrivateProfileString(szAppName, "MenuState", sz, ININAME); }
VOID RestoreState(VOID) { CHAR sz[80], *psz; INT col; DWORD cchRead;
cchRead = GetPrivateProfileString(szAppName, "Stats", "0 0 0 0 0 0 0 0 0", sz, sizeof(sz), ININAME);
psz = (cchRead > 0) ? lstrtok(sz, " ") : NULL; if (psz) { nGames = atoi(psz); psz = lstrtok(NULL, " "); nWins = psz ? atoi(psz) : 0; } else nGames = nWins = 0;
for (col = 0; col < 7 && psz; ++col) nCardsLeft[col] = atoi(psz = lstrtok(NULL, " "));
for (; col < 7; ++col) nCardsLeft[col] = 0;
cchRead = GetPrivateProfileString(szAppName, "MenuState", "0 65", sz, sizeof(sz), ININAME);
psz = (cchRead > 0) ? lstrtok(sz, " ") : NULL; if (psz) { wErrorMessages = (WORD) atoi(psz); psz = lstrtok(NULL, " ");
wDeckBack = (WORD) IDCARDBACK;
if (psz) wDeckBack = (WORD) atoi(psz);
} else { wErrorMessages = 0; wDeckBack = IDCARDBACK; } }
static BOOL IsInString(CHAR c, LPSTR s) { while (*s && *s != c) s = AnsiNext(s);
return *s; }
/* write our own strtok to avoid pulling in entire string library ... */ LPSTR lstrtok(LPSTR lpStr, LPSTR lpDelim) { static LPSTR lpString; LPSTR lpRetVal, lpTemp;
/* if we are passed new string skip leading delimiters */ if(lpStr) { lpString = lpStr;
while (*lpString && IsInString(*lpString, lpDelim)) lpString = AnsiNext(lpString); }
/* if there are no more tokens return NULL */ if(!*lpString) return NULL;
/* save head of token */ lpRetVal = lpString;
/* find delimiter or end of string */ while(*lpString && !IsInString(*lpString, lpDelim)) lpString = AnsiNext(lpString);
/* if we found a delimiter insert string terminator and skip */ if(*lpString) { lpTemp = AnsiNext(lpString); *lpString = '\0'; lpString = lpTemp; }
/* return token */ return(lpRetVal); }
/*----------------------------------------------------------------------------*\
| fDialog(id,hwnd,fpfn) | | | | Description: | | This function displays a dialog box and returns the exit code. | | the function passed will have a proc instance made for it. | | | | Arguments: | | id resource id of dialog to display | | hwnd parent window of dialog | | fpfn dialog message function | | | | Returns: | | exit code of dialog (what was passed to EndDialog) | | | \*----------------------------------------------------------------------------*/ BOOL fDialog(INT id,HWND hwnd,DLGPROC fpfn) { BOOL f; HANDLE hInst;
hInst = (HANDLE) GetWindowLongPtr(hwnd,GWLP_HINSTANCE); fpfn = MakeProcInstance(fpfn,hInst); f = (BOOL) DialogBox(hInst,MAKEINTRESOURCE(id),hwnd, fpfn); FreeProcInstance (fpfn); return f; }
INT_PTR APIENTRY RecordDlgProc(HANDLE hdlg, UINT wm, WPARAM wParam, LPARAM lParam) { CHAR sz[80]; HWND hwndEdit; INT i;
switch(wm) {
case WM_INITDIALOG: hwndEdit = GetDlgItem(hdlg, IDD_RECORD); SendMessage(hwndEdit, LB_ADDSTRING, 0, (LPARAM) (szRecordTitle));
wsprintf(sz, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d", nGames, nWins, nCardsLeft[0], nCardsLeft[1], nCardsLeft[2], nCardsLeft[3], nCardsLeft[4], nCardsLeft[5], nCardsLeft[6]); SendMessage(hwndEdit, LB_ADDSTRING, 0, (LPARAM) (sz)); MarkControlReadOnly(hwndEdit, TRUE); return TRUE;
case WM_COMMAND: switch(GET_WM_COMMAND_ID(wParam, lParam)) { case IDOK: /* fall thru */
case IDCANCEL: hwndEdit = GetDlgItem(hdlg, IDD_RECORD); MarkControlReadOnly(hwndEdit, FALSE); EndDialog(hdlg, GET_WM_COMMAND_ID(wParam, lParam) == IDOK);
break;
case IDD_CLEARSCORES: nGames = nWins = 0; for (i = 0; i < 7; ++i) nCardsLeft[i] = 0; lstrcpy(sz, "0\t0\t0\t0\t0\t0\t0\t0\t0"); hwndEdit = GetDlgItem(hdlg, IDD_RECORD); SendMessage(hwndEdit, LB_DELETESTRING, 1, 0L); SendMessage(hwndEdit, LB_ADDSTRING, 0, (LPARAM) (sz)); break; } break; }
return FALSE; }
static WNDPROC lpOldWP;
VOID MarkControlReadOnly(HWND hwndCtrl, BOOL bReadOnly) { if (bReadOnly) lpOldWP = (WNDPROC) SetWindowLongPtr(hwndCtrl, GWLP_WNDPROC, (LONG_PTR) ReadOnlyProc); else SetWindowLongPtr(hwndCtrl, GWLP_WNDPROC, (LONG_PTR)lpOldWP); }
LRESULT APIENTRY ReadOnlyProc(HWND hwnd, UINT wMessage, WPARAM wParam, LPARAM lParam) { switch (wMessage) { case WM_LBUTTONDOWN: case WM_RBUTTONDOWN: case WM_LBUTTONDBLCLK: case WM_RBUTTONDBLCLK: return 0L; }
return CallWindowProc(lpOldWP, hwnd, wMessage, wParam, lParam); }
|