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