1 #include "solitaire.h"
2 
3 #include <winreg.h>
4 #include <commctrl.h>
5 #include <tchar.h>
6 
7 #include "resource.h"
8 
9 TCHAR szHelpPath[MAX_PATH];
10 
11 DWORD        dwAppStartTime;
12 HWND        hwndMain;
13 HWND        hwndStatus;
14 HINSTANCE    hInstance;
15 HMENU        hGameMenu;
16 
17 TCHAR szAppName[128];
18 TCHAR szScore[64];
19 TCHAR szTime[64];
20 TCHAR MsgQuit[128];
21 TCHAR MsgAbout[128];
22 TCHAR MsgWin[128];
23 TCHAR MsgDeal[128];
24 DWORD dwOptions = OPTION_THREE_CARDS;
25 
26 DWORD dwTime;
27 DWORD dwWasteCount;
28 DWORD dwWasteTreshold;
29 DWORD dwPrevMode;
30 long lScore;
31 UINT_PTR PlayTimer = 0;
32 
33 CardWindow SolWnd;
34 
35 typedef struct _CardBack
36 {
37     HWND hSelf;
38     WNDPROC hOldProc;
39     INT hdcNum;
40     INT imgNum;
41     BOOL bSelected;
42 } CARDBACK, *PCARDBACK;
43 
44 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
45 
46 void MakePath(TCHAR *szDest, UINT nDestLen, const TCHAR *szExt)
47 {
48     TCHAR *ptr;
49 
50     ptr = szDest + GetModuleFileName(GetModuleHandle(0), szDest, nDestLen) - 1;
51     while(*ptr-- != '.');
52     lstrcpy(ptr + 1, szExt);
53 }
54 
55 VOID LoadSettings(VOID)
56 {
57     DWORD dwDisposition;
58     DWORD dwSize;
59     DWORD dwBack;
60     HKEY hKey;
61 
62     if (RegCreateKeyEx(HKEY_CURRENT_USER,
63                        _T("Software\\ReactOS\\Solitaire"),
64                        0,
65                        NULL,
66                        REG_OPTION_NON_VOLATILE,
67                        KEY_READ,
68                        NULL,
69                        &hKey,
70                        &dwDisposition))
71         return;
72 
73     dwSize = sizeof(DWORD);
74     RegQueryValueEx(hKey,
75                     _T("Options"),
76                     NULL,
77                     NULL,
78                     (LPBYTE)&dwOptions,
79                     &dwSize);
80 
81     dwSize = sizeof(DWORD);
82     RegQueryValueEx(hKey,
83                     _T("Back"),
84                     NULL,
85                     NULL,
86                     (LPBYTE)&dwBack,
87                     &dwSize);
88     SolWnd.SetBackCardIdx(dwBack);
89 
90     RegCloseKey(hKey);
91 }
92 
93 VOID SaveSettings(VOID)
94 {
95     DWORD dwDisposition;
96     DWORD dwBack;
97     HKEY hKey;
98 
99     if (RegCreateKeyEx(HKEY_CURRENT_USER,
100                        _T("Software\\ReactOS\\Solitaire"),
101                        0,
102                        NULL,
103                        REG_OPTION_NON_VOLATILE,
104                        KEY_WRITE,
105                        NULL,
106                        &hKey,
107                        &dwDisposition))
108         return;
109 
110     RegSetValueEx(hKey,
111                   _T("Options"),
112                   0,
113                   REG_DWORD,
114                   (CONST BYTE *)&dwOptions,
115                   sizeof(DWORD));
116 
117     dwBack = SolWnd.GetBackCardIdx();
118     RegSetValueEx(hKey,
119                   _T("Back"),
120                   0,
121                   REG_DWORD,
122                   (CONST BYTE *)&dwBack,
123                   sizeof(DWORD));
124 
125     RegCloseKey(hKey);
126 }
127 
128 // Returns 0 for no points, 1 for Standard and 2 for Vegas
129 int GetScoreMode(void)
130 {
131     if ((dwOptions & OPTION_SCORE_STD) && (dwOptions & OPTION_SCORE_VEGAS))
132     {
133         return SCORE_NONE;
134     }
135 
136     if (dwOptions & OPTION_SCORE_STD)
137     {
138         return SCORE_STD;
139     }
140 
141     if (dwOptions & OPTION_SCORE_VEGAS)
142     {
143         return SCORE_VEGAS;
144     }
145 
146     return 0;
147 }
148 
149 void UpdateStatusBar(void)
150 {
151     TCHAR szStatusText[128];
152     TCHAR szTempText[64];
153 
154     ZeroMemory(szStatusText, sizeof(szStatusText));
155 
156     if (GetScoreMode() != SCORE_NONE)
157     {
158         _stprintf(szStatusText, szScore, lScore);
159         _tcscat(szStatusText, _T("   "));
160     }
161 
162     if (dwOptions & OPTION_SHOW_TIME)
163     {
164         _stprintf(szTempText, szTime, dwTime);
165         _tcscat(szStatusText, szTempText);
166     }
167 
168     SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)(LPTSTR)szStatusText);
169 }
170 
171 void SetPlayTimer(void)
172 {
173     if (dwOptions & OPTION_SHOW_TIME)
174     {
175         if (!PlayTimer)
176         {
177             PlayTimer = SetTimer(hwndMain, IDT_PLAYTIMER, 1000, NULL);
178         }
179     }
180 }
181 
182 void SetUndoMenuState(bool enable)
183 {
184     if (enable)
185     {
186         EnableMenuItem(hGameMenu, IDM_GAME_UNDO, MF_BYCOMMAND | MF_ENABLED);
187     }
188     else
189     {
190         EnableMenuItem(hGameMenu, IDM_GAME_UNDO, MF_BYCOMMAND | MF_GRAYED);
191     }
192 }
193 
194 //
195 //    Main entry point
196 //
197 int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR szCmdLine, int iCmdShow)
198 {
199     HWND        hwnd;
200     MSG            msg;
201     WNDCLASS    wndclass;
202     INITCOMMONCONTROLSEX ice;
203     HACCEL        hAccelTable;
204 
205     hInstance = hInst;
206 
207     // Load application title
208     LoadString(hInst, IDS_SOL_NAME, szAppName, sizeof(szAppName) / sizeof(szAppName[0]));
209     // Load MsgBox() texts here to avoid loading them many times later
210     LoadString(hInst, IDS_SOL_ABOUT, MsgAbout, sizeof(MsgAbout) / sizeof(MsgAbout[0]));
211     LoadString(hInst, IDS_SOL_QUIT, MsgQuit, sizeof(MsgQuit) / sizeof(MsgQuit[0]));
212     LoadString(hInst, IDS_SOL_WIN, MsgWin, sizeof(MsgWin) / sizeof(MsgWin[0]));
213     LoadString(hInst, IDS_SOL_DEAL, MsgDeal, sizeof(MsgDeal) / sizeof(MsgDeal[0]));
214 
215     LoadString(hInst, IDS_SOL_SCORE, szScore, sizeof(szScore) / sizeof(TCHAR));
216     LoadString(hInst, IDS_SOL_TIME, szTime, sizeof(szTime) / sizeof(TCHAR));
217 
218     //Window class for the main application parent window
219     wndclass.style            = 0;//CS_HREDRAW | CS_VREDRAW;
220     wndclass.lpfnWndProc    = WndProc;
221     wndclass.cbClsExtra        = 0;
222     wndclass.cbWndExtra        = 0;
223     wndclass.hInstance        = hInst;
224     wndclass.hIcon            = LoadIcon (hInst, MAKEINTRESOURCE(IDI_SOLITAIRE));
225     wndclass.hCursor        = LoadCursor (NULL, IDC_ARROW);
226     wndclass.hbrBackground    = (HBRUSH)NULL;
227     wndclass.lpszMenuName    = MAKEINTRESOURCE(IDR_MENU1);
228     wndclass.lpszClassName    = szAppName;
229 
230     RegisterClass(&wndclass);
231 
232     ice.dwSize = sizeof(ice);
233     ice.dwICC = ICC_BAR_CLASSES;
234     InitCommonControlsEx(&ice);
235 
236     srand((unsigned)GetTickCount());//timeGetTime());
237 
238 //    InitCardLib();
239 
240     LoadSettings();
241 
242     dwPrevMode = GetScoreMode();
243 
244     //Construct the path to our help file
245     MakePath(szHelpPath, MAX_PATH, _T(".hlp"));
246 
247     hwnd = CreateWindow(szAppName,        // window class name
248                 szAppName,                // window caption
249                 WS_OVERLAPPEDWINDOW
250                 ,//|WS_CLIPCHILDREN,      // window style
251                 CW_USEDEFAULT,            // initial x position
252                 CW_USEDEFAULT,            // initial y position
253                 0,                        // The real size will be computed in WndProc through WM_GETMINMAXINFO
254                 0,                        // The real size will be computed in WndProc through WM_GETMINMAXINFO
255                 NULL,                     // parent window handle
256                 NULL,                     // use window class menu
257                 hInst,                    // program instance handle
258                 NULL);                    // creation parameters
259     if (hwnd == NULL)
260         return 1;
261 
262     hwndMain = hwnd;
263 
264     hGameMenu = GetSubMenu(GetMenu(hwndMain), 0);
265 
266     UpdateStatusBar();
267 
268     ShowWindow(hwnd, iCmdShow);
269     UpdateWindow(hwnd);
270 
271     hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
272 
273     while(GetMessage(&msg, NULL,0,0))
274     {
275         if(!TranslateAccelerator(hwnd, hAccelTable, &msg))
276         {
277             TranslateMessage(&msg);
278             DispatchMessage(&msg);
279         }
280     }
281 
282     SaveSettings();
283 
284     return msg.wParam;
285 }
286 
287 
288 INT_PTR CALLBACK OptionsDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
289 {
290     HWND hCtrl;
291 
292     switch (uMsg)
293     {
294     case WM_INITDIALOG:
295          // For now, the Help dialog item is disabled because of lacking of HTML Help support
296         EnableMenuItem(GetMenu(hDlg), IDM_HELP_CONTENTS, MF_BYCOMMAND | MF_GRAYED);
297 
298         CheckRadioButton(hDlg, IDC_OPT_DRAWONE, IDC_OPT_DRAWTHREE,
299                          (dwOptions & OPTION_THREE_CARDS) ? IDC_OPT_DRAWTHREE : IDC_OPT_DRAWONE);
300 
301         CheckDlgButton(hDlg,
302                        IDC_OPT_STATUSBAR,
303                        (dwOptions & OPTION_SHOW_STATUS) ? BST_CHECKED : BST_UNCHECKED);
304 
305         CheckDlgButton(hDlg,
306                        IDC_OPT_SHOWTIME,
307                        (dwOptions & OPTION_SHOW_TIME) ? BST_CHECKED : BST_UNCHECKED);
308 
309         CheckDlgButton(hDlg,
310                        IDC_OPT_KEEPSCORE,
311                        (dwOptions & OPTION_KEEP_SCORE) ? BST_CHECKED : BST_UNCHECKED);
312 
313         hCtrl = GetDlgItem(hDlg, IDC_OPT_KEEPSCORE);
314 
315         if (GetScoreMode() == SCORE_NONE)
316         {
317             CheckRadioButton(hDlg, IDC_OPT_STANDARD, IDC_OPT_NOSCORE, IDC_OPT_NOSCORE);
318             EnableWindow(hCtrl, FALSE);
319         }
320         else if (GetScoreMode() == SCORE_STD)
321         {
322             CheckRadioButton(hDlg, IDC_OPT_STANDARD, IDC_OPT_NOSCORE, IDC_OPT_STANDARD);
323             EnableWindow(hCtrl, FALSE);
324         }
325         else if (GetScoreMode() == SCORE_VEGAS)
326         {
327             CheckRadioButton(hDlg, IDC_OPT_STANDARD, IDC_OPT_NOSCORE, IDC_OPT_VEGAS);
328             EnableWindow(hCtrl, TRUE);
329         }
330         return TRUE;
331 
332     case WM_COMMAND:
333         switch(LOWORD(wParam))
334         {
335         case IDC_OPT_NOSCORE:
336         case IDC_OPT_STANDARD:
337         case IDC_OPT_VEGAS:
338             hCtrl = GetDlgItem(hDlg, IDC_OPT_KEEPSCORE);
339             if (wParam == IDC_OPT_VEGAS)
340                 EnableWindow(hCtrl, TRUE);
341             else
342                 EnableWindow(hCtrl, FALSE);
343             return TRUE;
344 
345         case IDOK:
346             dwOptions &= ~OPTION_THREE_CARDS;
347             if (IsDlgButtonChecked(hDlg, IDC_OPT_DRAWTHREE) == BST_CHECKED)
348                 dwOptions |= OPTION_THREE_CARDS;
349 
350             if (IsDlgButtonChecked(hDlg, IDC_OPT_STATUSBAR) == BST_CHECKED)
351                 dwOptions |= OPTION_SHOW_STATUS;
352             else
353                 dwOptions &= ~OPTION_SHOW_STATUS;
354 
355             if (IsDlgButtonChecked(hDlg, IDC_OPT_SHOWTIME) == BST_CHECKED)
356                 dwOptions |= OPTION_SHOW_TIME;
357             else
358                 dwOptions &= ~OPTION_SHOW_TIME;
359 
360             if (IsDlgButtonChecked(hDlg, IDC_OPT_KEEPSCORE) == BST_CHECKED)
361                 dwOptions |= OPTION_KEEP_SCORE;
362             else
363                 dwOptions &= ~OPTION_KEEP_SCORE;
364 
365             if (IsDlgButtonChecked(hDlg, IDC_OPT_STANDARD) == BST_CHECKED)
366             {
367                 dwOptions |= OPTION_SCORE_STD;
368                 dwOptions &= ~OPTION_SCORE_VEGAS;
369             }
370             else if (IsDlgButtonChecked(hDlg, IDC_OPT_VEGAS) == BST_CHECKED)
371             {
372                 dwOptions |= OPTION_SCORE_VEGAS;
373                 dwOptions &= ~OPTION_SCORE_STD;
374             }
375             else if (IsDlgButtonChecked(hDlg, IDC_OPT_NOSCORE) == BST_CHECKED)
376             {
377                 dwOptions |= OPTION_SCORE_VEGAS;
378                 dwOptions |= OPTION_SCORE_STD;
379             }
380 
381             UpdateStatusBar();
382 
383             EndDialog(hDlg, TRUE);
384             return TRUE;
385 
386         case IDCANCEL:
387             EndDialog(hDlg, FALSE);
388             return TRUE;
389         }
390         break;
391     }
392     return FALSE;
393 }
394 
395 VOID ShowGameOptionsDlg(HWND hwnd)
396 {
397     DWORD dwOldOptions = dwOptions;
398     RECT rcMain, rcStatus;
399 
400     int iOldScoreMode = GetScoreMode();
401 
402     if (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS), hwnd, OptionsDlgProc))
403     {
404         if (((dwOldOptions & OPTION_THREE_CARDS) != (dwOptions & OPTION_THREE_CARDS)) ||
405             ((dwOldOptions & OPTION_SHOW_TIME) != (dwOptions & OPTION_SHOW_TIME)) ||
406             (iOldScoreMode != GetScoreMode()))
407             NewGame();
408 
409         if ((dwOldOptions & OPTION_SHOW_STATUS) != (dwOptions & OPTION_SHOW_STATUS))
410         {
411             int nWidth, nHeight, nStatusHeight;
412 
413             GetClientRect(hwndMain, &rcMain);
414             nHeight = rcMain.bottom - rcMain.top;
415             nWidth = rcMain.right - rcMain.left;
416 
417             if (dwOptions & OPTION_SHOW_STATUS)
418             {
419                 RECT rc;
420 
421                 ShowWindow(hwndStatus, SW_SHOW);
422                 GetWindowRect(hwndStatus, &rcStatus);
423                 nStatusHeight = rcStatus.bottom - rcStatus.top;
424                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight-nStatusHeight, TRUE);
425                 MoveWindow(hwndStatus, 0, nHeight-nStatusHeight, nWidth, nHeight, TRUE);
426 
427                 // Force the window to process WM_GETMINMAXINFO again
428                 GetWindowRect(hwndMain, &rc);
429                 SetWindowPos(hwndMain, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER);
430             }
431             else
432             {
433                 ShowWindow(hwndStatus, SW_HIDE);
434                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight, TRUE);
435             }
436         }
437     }
438 }
439 
440 
441 LRESULT CALLBACK
442 CardImageWndProc(HWND hwnd,
443                  UINT msg,
444                  WPARAM wParam,
445                  LPARAM lParam)
446 {
447     PCARDBACK pCardBack = (PCARDBACK)GetWindowLongPtr(hwnd,
448                                                       GWLP_USERDATA);
449     static WNDPROC hOldProc = NULL;
450 
451     if (!hOldProc && pCardBack)
452         hOldProc = pCardBack->hOldProc;
453 
454     switch (msg)
455     {
456     case WM_PAINT:
457     {
458         HDC hdc;
459         PAINTSTRUCT ps;
460         HPEN hPen, hOldPen;
461         HBRUSH hBrush, hOldBrush;
462         RECT rc;
463 
464         hdc = BeginPaint(hwnd, &ps);
465 
466         if (pCardBack->bSelected)
467         {
468             hPen = CreatePen(PS_SOLID, 2, RGB(0,0,0));
469         }
470         else
471         {
472             DWORD Face = GetSysColor(COLOR_3DFACE);
473             hPen = CreatePen(PS_SOLID, 2, Face);
474         }
475 
476         GetClientRect(hwnd, &rc);
477         hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
478         hOldPen = (HPEN)SelectObject(hdc, hPen);
479         hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
480 
481         Rectangle(hdc,
482                   rc.left+1,
483                   rc.top+1,
484                   rc.right,
485                   rc.bottom);
486 
487         StretchBlt(hdc,
488                    2,
489                    2,
490                    CARDBACK_OPTIONS_WIDTH,
491                    CARDBACK_OPTIONS_HEIGHT,
492                    __hdcCardBitmaps,
493                    pCardBack->hdcNum * __cardwidth,
494                    0,
495                    __cardwidth,
496                    __cardheight,
497                    SRCCOPY);
498 
499         SelectObject(hdc, hOldPen);
500         SelectObject(hdc, hOldBrush);
501 
502         EndPaint(hwnd, &ps);
503 
504         break;
505     }
506 
507     case WM_LBUTTONDOWN:
508         pCardBack->bSelected = pCardBack->bSelected ? FALSE : TRUE;
509         break;
510     }
511 
512     return CallWindowProc(hOldProc,
513                           hwnd,
514                           msg,
515                           wParam,
516                           lParam);
517 }
518 
519 
520 INT_PTR CALLBACK CardBackDlgProc(HWND hDlg,
521                               UINT uMsg,
522                               WPARAM wParam,
523                               LPARAM lParam)
524 {
525     static PCARDBACK pCardBacks = NULL;
526 
527     switch (uMsg)
528     {
529     case WM_INITDIALOG:
530     {
531         INT i, c;
532         SIZE_T size = sizeof(CARDBACK) * NUM_CARDBACKS;
533 
534         pCardBacks = (PCARDBACK)HeapAlloc(GetProcessHeap(),
535                                           0,
536                                           size);
537 
538         for (i = 0, c = CARDBACK_START; c <= CARDBACK_END; i++, c++)
539         {
540             pCardBacks[i].hSelf = GetDlgItem(hDlg, c);
541             pCardBacks[i].bSelected = FALSE;
542             pCardBacks[i].hdcNum = CARDBACK_RES_START + i;
543             pCardBacks[i].imgNum = i + 1;
544             pCardBacks[i].hOldProc = (WNDPROC)SetWindowLongPtr(pCardBacks[i].hSelf,
545                                                                GWLP_WNDPROC,
546                                                                (LONG_PTR)CardImageWndProc);
547 
548             SetWindowLongPtr(pCardBacks[i].hSelf,
549                              GWLP_USERDATA,
550                              (LONG_PTR)&pCardBacks[i]);
551         }
552 
553         return TRUE;
554     }
555 
556     case WM_COMMAND:
557         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
558         {
559             INT i, num = 0;
560             for (i = 0; i < NUM_CARDBACKS; i++)
561             {
562                 if (pCardBacks[i].bSelected)
563                 {
564                     num = pCardBacks[i].imgNum;
565                 }
566             }
567 
568             EndDialog(hDlg, LOWORD(wParam) == IDOK ? num : FALSE);
569             HeapFree(GetProcessHeap(), 0, pCardBacks);
570             return TRUE;
571         }
572 
573         if (HIWORD(wParam) == STN_CLICKED)
574         {
575             INT i;
576             RECT rc;
577             for (i = 0; i < NUM_CARDBACKS; i++)
578             {
579                 if (pCardBacks[i].hSelf == (HWND)lParam)
580                 {
581                     pCardBacks[i].bSelected = TRUE;
582                 }
583                 else
584                     pCardBacks[i].bSelected = FALSE;
585 
586                 GetClientRect(pCardBacks[i].hSelf, &rc);
587                 InvalidateRect(pCardBacks[i].hSelf, &rc, TRUE);
588             }
589 
590             break;
591         }
592     }
593 
594     return FALSE;
595 }
596 
597 
598 VOID ShowDeckOptionsDlg(HWND hwnd)
599 {
600     INT cardBack;
601 
602     if ((cardBack = DialogBox(hInstance,
603                               MAKEINTRESOURCE(IDD_CARDBACK),
604                               hwnd,
605                               CardBackDlgProc)))
606     {
607         SolWnd.SetBackCardIdx(CARDBACK_RES_START + (cardBack - 1));
608         SolWnd.Redraw();
609     }
610 }
611 
612 //-----------------------------------------------------------------------------
613 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
614 {
615     static int nWidth, nHeight, nStatusHeight;
616 
617     switch(iMsg)
618     {
619         case WM_CREATE:
620         {
621             int parts[] = { 150, -1 };
622             RECT rcStatus;
623 
624             // For now, the Help dialog item is disabled because of lacking of HTML Help support
625             EnableMenuItem(GetMenu(hwnd), IDM_HELP_CONTENTS, MF_BYCOMMAND | MF_GRAYED);
626 
627             hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, _T("Ready"), hwnd, 0);
628 
629             //SendMessage(hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0);
630 
631             SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
632             SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)"");
633 
634             SolWnd.Create(hwnd, 0, WS_CHILD | WS_VISIBLE, 0, 0, 100, 100);
635 
636             CreateSol();
637 
638             // The status bar height is fixed and needed later in WM_SIZE and WM_GETMINMAXINFO
639             // Force the window to process WM_GETMINMAXINFO again
640             GetWindowRect(hwndStatus, &rcStatus);
641             nStatusHeight = rcStatus.bottom - rcStatus.top;
642 
643             // Hide status bar if options say so
644             if (!(dwOptions & OPTION_SHOW_STATUS))
645             {
646                 ShowWindow(hwndStatus, SW_HIDE);
647             }
648 
649             SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOZORDER);
650 
651             NewGame();
652 
653             dwAppStartTime = GetTickCount();
654 
655             return 0;
656         }
657 
658         case WM_DESTROY:
659             PostQuitMessage(0);
660             return 0;
661 
662         case WM_TIMER:
663             if (!fGameStarted)
664             {
665                 KillTimer(hwndMain, IDT_PLAYTIMER);
666                 PlayTimer = 0;
667             }
668             else if (dwOptions & OPTION_SHOW_TIME)
669             {
670                 if (((dwTime + 1) % 10 == 0) && (GetScoreMode() == SCORE_STD))
671                 {
672                     lScore = lScore >= 2 ? lScore - 2 : 0;
673                 }
674 
675                 dwTime++;
676             }
677 
678             UpdateStatusBar();
679             return 0;
680 
681         case WM_SIZE:
682             nWidth  = LOWORD(lParam);
683             nHeight = HIWORD(lParam);
684 
685             if (dwOptions & OPTION_SHOW_STATUS)
686             {
687                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight - nStatusHeight, TRUE);
688                 MoveWindow(hwndStatus, 0, nHeight - nStatusHeight, nWidth, nStatusHeight, TRUE);
689             }
690             else
691             {
692                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight, TRUE);
693             }
694             //parts[0] = nWidth - 256;
695             //SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
696             return 0;
697 
698         case WM_GETMINMAXINFO:
699         {
700             MINMAXINFO *mmi;
701 
702             mmi = (MINMAXINFO *)lParam;
703             mmi->ptMinTrackSize.x = X_BORDER + NUM_ROW_STACKS * (__cardwidth + X_ROWSTACK_BORDER) + X_BORDER;
704             mmi->ptMinTrackSize.y = GetSystemMetrics(SM_CYCAPTION) +
705                                     GetSystemMetrics(SM_CYMENU) +
706                                     Y_BORDER +
707                                     __cardheight +
708                                     Y_ROWSTACK_BORDER +
709                                     6 * yRowStackCardOffset +
710                                     __cardheight +
711                                     Y_BORDER +
712                                     (dwOptions & OPTION_SHOW_STATUS ? nStatusHeight : 0);
713             return 0;
714         }
715 
716         case WM_COMMAND:
717             switch(LOWORD(wParam))
718             {
719             case IDM_GAME_NEW:
720                 //simulate a button click on the new button..
721                 NewGame();
722                 return 0;
723 
724             case IDM_GAME_UNDO:
725                 Undo();
726                 return 0;
727 
728             case IDM_GAME_DECK:
729                 ShowDeckOptionsDlg(hwnd);
730                 return 0;
731 
732             case IDM_GAME_OPTIONS:
733                 ShowGameOptionsDlg(hwnd);
734                 return 0;
735 
736             case IDM_HELP_CONTENTS:
737                 WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play");
738                 return 0;
739 
740             case IDM_HELP_ABOUT:
741                 MessageBox(hwnd, MsgAbout, szAppName, MB_OK|MB_ICONINFORMATION);
742                 return 0;
743 
744             case IDM_GAME_EXIT:
745                 PostMessage(hwnd, WM_CLOSE, 0, 0);
746                 return 0;
747             }
748 
749             return 0;
750 
751         case WM_CLOSE:
752             if (fGameStarted == false)
753             {
754                 DestroyWindow(hwnd);
755                 return 0;
756             }
757             else
758             {
759                 int ret;
760 
761                 ret = MessageBox(hwnd, MsgQuit, szAppName, MB_YESNO|MB_ICONQUESTION);
762                 if (ret == IDYES)
763                 {
764                     WinHelp(hwnd, szHelpPath, HELP_QUIT, 0);
765                     DestroyWindow(hwnd);
766                 }
767             }
768             return 0;
769     }
770 
771     return DefWindowProc (hwnd, iMsg, wParam, lParam);
772 }
773 
774 
775