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         CheckRadioButton(hDlg, IDC_OPT_DRAWONE, IDC_OPT_DRAWTHREE,
281                          (dwOptions & OPTION_THREE_CARDS) ? IDC_OPT_DRAWTHREE : IDC_OPT_DRAWONE);
282 
283         CheckDlgButton(hDlg,
284                        IDC_OPT_STATUSBAR,
285                        (dwOptions & OPTION_SHOW_STATUS) ? BST_CHECKED : BST_UNCHECKED);
286 
287         CheckDlgButton(hDlg,
288                        IDC_OPT_SHOWTIME,
289                        (dwOptions & OPTION_SHOW_TIME) ? BST_CHECKED : BST_UNCHECKED);
290 
291         CheckDlgButton(hDlg,
292                        IDC_OPT_KEEPSCORE,
293                        (dwOptions & OPTION_KEEP_SCORE) ? BST_CHECKED : BST_UNCHECKED);
294 
295         hCtrl = GetDlgItem(hDlg, IDC_OPT_KEEPSCORE);
296 
297         if (GetScoreMode() == SCORE_NONE)
298         {
299             CheckRadioButton(hDlg, IDC_OPT_STANDARD, IDC_OPT_NOSCORE, IDC_OPT_NOSCORE);
300             EnableWindow(hCtrl, FALSE);
301         }
302         else if (GetScoreMode() == SCORE_STD)
303         {
304             CheckRadioButton(hDlg, IDC_OPT_STANDARD, IDC_OPT_NOSCORE, IDC_OPT_STANDARD);
305             EnableWindow(hCtrl, FALSE);
306         }
307         else if (GetScoreMode() == SCORE_VEGAS)
308         {
309             CheckRadioButton(hDlg, IDC_OPT_STANDARD, IDC_OPT_NOSCORE, IDC_OPT_VEGAS);
310             EnableWindow(hCtrl, TRUE);
311         }
312         return TRUE;
313 
314     case WM_COMMAND:
315         switch(LOWORD(wParam))
316         {
317         case IDC_OPT_NOSCORE:
318         case IDC_OPT_STANDARD:
319         case IDC_OPT_VEGAS:
320             hCtrl = GetDlgItem(hDlg, IDC_OPT_KEEPSCORE);
321             if (wParam == IDC_OPT_VEGAS)
322                 EnableWindow(hCtrl, TRUE);
323             else
324                 EnableWindow(hCtrl, FALSE);
325             return TRUE;
326 
327         case IDOK:
328             dwOptions &= ~OPTION_THREE_CARDS;
329             if (IsDlgButtonChecked(hDlg, IDC_OPT_DRAWTHREE) == BST_CHECKED)
330                 dwOptions |= OPTION_THREE_CARDS;
331 
332             if (IsDlgButtonChecked(hDlg, IDC_OPT_STATUSBAR) == BST_CHECKED)
333                 dwOptions |= OPTION_SHOW_STATUS;
334             else
335                 dwOptions &= ~OPTION_SHOW_STATUS;
336 
337             if (IsDlgButtonChecked(hDlg, IDC_OPT_SHOWTIME) == BST_CHECKED)
338                 dwOptions |= OPTION_SHOW_TIME;
339             else
340                 dwOptions &= ~OPTION_SHOW_TIME;
341 
342             if (IsDlgButtonChecked(hDlg, IDC_OPT_KEEPSCORE) == BST_CHECKED)
343                 dwOptions |= OPTION_KEEP_SCORE;
344             else
345                 dwOptions &= ~OPTION_KEEP_SCORE;
346 
347             if (IsDlgButtonChecked(hDlg, IDC_OPT_STANDARD) == BST_CHECKED)
348             {
349                 dwOptions |= OPTION_SCORE_STD;
350                 dwOptions &= ~OPTION_SCORE_VEGAS;
351             }
352             else if (IsDlgButtonChecked(hDlg, IDC_OPT_VEGAS) == BST_CHECKED)
353             {
354                 dwOptions |= OPTION_SCORE_VEGAS;
355                 dwOptions &= ~OPTION_SCORE_STD;
356             }
357             else if (IsDlgButtonChecked(hDlg, IDC_OPT_NOSCORE) == BST_CHECKED)
358             {
359                 dwOptions |= OPTION_SCORE_VEGAS;
360                 dwOptions |= OPTION_SCORE_STD;
361             }
362 
363             UpdateStatusBar();
364 
365             EndDialog(hDlg, TRUE);
366             return TRUE;
367 
368         case IDCANCEL:
369             EndDialog(hDlg, FALSE);
370             return TRUE;
371         }
372         break;
373     }
374     return FALSE;
375 }
376 
377 VOID ShowGameOptionsDlg(HWND hwnd)
378 {
379     DWORD dwOldOptions = dwOptions;
380     RECT rcMain, rcStatus;
381 
382     int iOldScoreMode = GetScoreMode();
383 
384     if (DialogBox(hInstance, MAKEINTRESOURCE(IDD_OPTIONS), hwnd, OptionsDlgProc))
385     {
386         if (((dwOldOptions & OPTION_THREE_CARDS) != (dwOptions & OPTION_THREE_CARDS)) ||
387             ((dwOldOptions & OPTION_SHOW_TIME) != (dwOptions & OPTION_SHOW_TIME)) ||
388             (iOldScoreMode != GetScoreMode()))
389             NewGame();
390 
391         if ((dwOldOptions & OPTION_SHOW_STATUS) != (dwOptions & OPTION_SHOW_STATUS))
392         {
393             int nWidth, nHeight, nStatusHeight;
394 
395             GetClientRect(hwndMain, &rcMain);
396             nHeight = rcMain.bottom - rcMain.top;
397             nWidth = rcMain.right - rcMain.left;
398 
399             if (dwOptions & OPTION_SHOW_STATUS)
400             {
401                 RECT rc;
402 
403                 ShowWindow(hwndStatus, SW_SHOW);
404                 GetWindowRect(hwndStatus, &rcStatus);
405                 nStatusHeight = rcStatus.bottom - rcStatus.top;
406                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight-nStatusHeight, TRUE);
407                 MoveWindow(hwndStatus, 0, nHeight-nStatusHeight, nWidth, nHeight, TRUE);
408 
409                 // Force the window to process WM_GETMINMAXINFO again
410                 GetWindowRect(hwndMain, &rc);
411                 SetWindowPos(hwndMain, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top, SWP_NOMOVE | SWP_NOZORDER);
412             }
413             else
414             {
415                 ShowWindow(hwndStatus, SW_HIDE);
416                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight, TRUE);
417             }
418         }
419     }
420 }
421 
422 
423 LRESULT CALLBACK
424 CardImageWndProc(HWND hwnd,
425                  UINT msg,
426                  WPARAM wParam,
427                  LPARAM lParam)
428 {
429     PCARDBACK pCardBack = (PCARDBACK)GetWindowLongPtr(hwnd,
430                                                       GWLP_USERDATA);
431     static WNDPROC hOldProc = NULL;
432 
433     if (!hOldProc && pCardBack)
434         hOldProc = pCardBack->hOldProc;
435 
436     switch (msg)
437     {
438     case WM_PAINT:
439     {
440         HDC hdc;
441         PAINTSTRUCT ps;
442         HPEN hPen, hOldPen;
443         HBRUSH hBrush, hOldBrush;
444         RECT rc;
445 
446         hdc = BeginPaint(hwnd, &ps);
447 
448         if (pCardBack->bSelected)
449         {
450             hPen = CreatePen(PS_SOLID, 2, RGB(0,0,0));
451         }
452         else
453         {
454             DWORD Face = GetSysColor(COLOR_3DFACE);
455             hPen = CreatePen(PS_SOLID, 2, Face);
456         }
457 
458         GetClientRect(hwnd, &rc);
459         hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
460         hOldPen = (HPEN)SelectObject(hdc, hPen);
461         hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
462 
463         Rectangle(hdc,
464                   rc.left+1,
465                   rc.top+1,
466                   rc.right,
467                   rc.bottom);
468 
469         StretchBlt(hdc,
470                    2,
471                    2,
472                    CARDBACK_OPTIONS_WIDTH,
473                    CARDBACK_OPTIONS_HEIGHT,
474                    __hdcCardBitmaps,
475                    pCardBack->hdcNum * __cardwidth,
476                    0,
477                    __cardwidth,
478                    __cardheight,
479                    SRCCOPY);
480 
481         SelectObject(hdc, hOldPen);
482         SelectObject(hdc, hOldBrush);
483 
484         EndPaint(hwnd, &ps);
485 
486         break;
487     }
488 
489     case WM_LBUTTONDOWN:
490         pCardBack->bSelected = pCardBack->bSelected ? FALSE : TRUE;
491         break;
492     }
493 
494     return CallWindowProc(hOldProc,
495                           hwnd,
496                           msg,
497                           wParam,
498                           lParam);
499 }
500 
501 
502 INT_PTR CALLBACK CardBackDlgProc(HWND hDlg,
503                               UINT uMsg,
504                               WPARAM wParam,
505                               LPARAM lParam)
506 {
507     static PCARDBACK pCardBacks = NULL;
508 
509     switch (uMsg)
510     {
511     case WM_INITDIALOG:
512     {
513         INT i, c;
514         SIZE_T size = sizeof(CARDBACK) * NUM_CARDBACKS;
515 
516         pCardBacks = (PCARDBACK)HeapAlloc(GetProcessHeap(),
517                                           0,
518                                           size);
519 
520         for (i = 0, c = CARDBACK_START; c <= CARDBACK_END; i++, c++)
521         {
522             pCardBacks[i].hSelf = GetDlgItem(hDlg, c);
523             pCardBacks[i].bSelected = FALSE;
524             pCardBacks[i].hdcNum = CARDBACK_RES_START + i;
525             pCardBacks[i].imgNum = i + 1;
526             pCardBacks[i].hOldProc = (WNDPROC)SetWindowLongPtr(pCardBacks[i].hSelf,
527                                                                GWLP_WNDPROC,
528                                                                (LONG_PTR)CardImageWndProc);
529 
530             SetWindowLongPtr(pCardBacks[i].hSelf,
531                              GWLP_USERDATA,
532                              (LONG_PTR)&pCardBacks[i]);
533         }
534 
535         return TRUE;
536     }
537 
538     case WM_COMMAND:
539         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
540         {
541             INT i, num = 0;
542             for (i = 0; i < NUM_CARDBACKS; i++)
543             {
544                 if (pCardBacks[i].bSelected)
545                 {
546                     num = pCardBacks[i].imgNum;
547                 }
548             }
549 
550             EndDialog(hDlg, LOWORD(wParam) == IDOK ? num : FALSE);
551             HeapFree(GetProcessHeap(), 0, pCardBacks);
552             return TRUE;
553         }
554 
555         if (HIWORD(wParam) == STN_CLICKED)
556         {
557             INT i;
558             RECT rc;
559             for (i = 0; i < NUM_CARDBACKS; i++)
560             {
561                 if (pCardBacks[i].hSelf == (HWND)lParam)
562                 {
563                     pCardBacks[i].bSelected = TRUE;
564                 }
565                 else
566                     pCardBacks[i].bSelected = FALSE;
567 
568                 GetClientRect(pCardBacks[i].hSelf, &rc);
569                 InvalidateRect(pCardBacks[i].hSelf, &rc, TRUE);
570             }
571 
572             break;
573         }
574     }
575 
576     return FALSE;
577 }
578 
579 
580 VOID ShowDeckOptionsDlg(HWND hwnd)
581 {
582     INT cardBack;
583 
584     if ((cardBack = DialogBox(hInstance,
585                               MAKEINTRESOURCE(IDD_CARDBACK),
586                               hwnd,
587                               CardBackDlgProc)))
588     {
589         SolWnd.SetBackCardIdx(CARDBACK_RES_START + (cardBack - 1));
590         SolWnd.Redraw();
591     }
592 }
593 
594 //-----------------------------------------------------------------------------
595 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
596 {
597     static int nWidth, nHeight, nStatusHeight;
598 
599     switch(iMsg)
600     {
601         case WM_CREATE:
602         {
603             int parts[] = { 150, -1 };
604             RECT rcStatus;
605 
606             hwndStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM | SBARS_SIZEGRIP, _T("Ready"), hwnd, 0);
607 
608             //SendMessage(hwndStatus, SB_SIMPLE, (WPARAM)TRUE, 0);
609 
610             SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
611             SendMessage(hwndStatus, SB_SETTEXT, 0 | SBT_NOBORDERS, (LPARAM)"");
612 
613             SolWnd.Create(hwnd, 0, WS_CHILD | WS_VISIBLE, 0, 0, 100, 100);
614 
615             CreateSol();
616 
617             // The status bar height is fixed and needed later in WM_SIZE and WM_GETMINMAXINFO
618             // Force the window to process WM_GETMINMAXINFO again
619             GetWindowRect(hwndStatus, &rcStatus);
620             nStatusHeight = rcStatus.bottom - rcStatus.top;
621 
622             // Hide status bar if options say so
623             if (!(dwOptions & OPTION_SHOW_STATUS))
624             {
625                 ShowWindow(hwndStatus, SW_HIDE);
626             }
627 
628             SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOZORDER);
629 
630             NewGame();
631 
632             dwAppStartTime = GetTickCount();
633 
634             return 0;
635         }
636 
637         case WM_DESTROY:
638             PostQuitMessage(0);
639             return 0;
640 
641         case WM_TIMER:
642             if (!fGameStarted)
643             {
644                 KillTimer(hwndMain, IDT_PLAYTIMER);
645                 PlayTimer = 0;
646             }
647             else if (dwOptions & OPTION_SHOW_TIME)
648             {
649                 if (((dwTime + 1) % 10 == 0) && (GetScoreMode() == SCORE_STD))
650                 {
651                     lScore = lScore >= 2 ? lScore - 2 : 0;
652                 }
653 
654                 dwTime++;
655             }
656 
657             UpdateStatusBar();
658             return 0;
659 
660         case WM_SIZE:
661             nWidth  = LOWORD(lParam);
662             nHeight = HIWORD(lParam);
663 
664             if (dwOptions & OPTION_SHOW_STATUS)
665             {
666                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight - nStatusHeight, TRUE);
667                 MoveWindow(hwndStatus, 0, nHeight - nStatusHeight, nWidth, nStatusHeight, TRUE);
668             }
669             else
670             {
671                 MoveWindow(SolWnd, 0, 0, nWidth, nHeight, TRUE);
672             }
673             //parts[0] = nWidth - 256;
674             //SendMessage(hwndStatus, SB_SETPARTS, 2, (LPARAM)parts);
675             return 0;
676 
677         case WM_GETMINMAXINFO:
678         {
679             MINMAXINFO *mmi;
680 
681             mmi = (MINMAXINFO *)lParam;
682             mmi->ptMinTrackSize.x = X_BORDER + NUM_ROW_STACKS * (__cardwidth + X_ROWSTACK_BORDER) + X_BORDER;
683             mmi->ptMinTrackSize.y = GetSystemMetrics(SM_CYCAPTION) +
684                                     GetSystemMetrics(SM_CYMENU) +
685                                     Y_BORDER +
686                                     __cardheight +
687                                     Y_ROWSTACK_BORDER +
688                                     6 * yRowStackCardOffset +
689                                     __cardheight +
690                                     Y_BORDER +
691                                     (dwOptions & OPTION_SHOW_STATUS ? nStatusHeight : 0);
692             return 0;
693         }
694 
695         case WM_COMMAND:
696             switch(LOWORD(wParam))
697             {
698             case IDM_GAME_NEW:
699                 //simulate a button click on the new button..
700                 NewGame();
701                 return 0;
702 
703             case IDM_GAME_DECK:
704                 ShowDeckOptionsDlg(hwnd);
705                 return 0;
706 
707             case IDM_GAME_OPTIONS:
708                 ShowGameOptionsDlg(hwnd);
709                 return 0;
710 
711             case IDM_HELP_CONTENTS:
712                 WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play");
713                 return 0;
714 
715             case IDM_HELP_ABOUT:
716                 MessageBox(hwnd, MsgAbout, szAppName, MB_OK|MB_ICONINFORMATION);
717                 return 0;
718 
719             case IDM_GAME_EXIT:
720                 PostMessage(hwnd, WM_CLOSE, 0, 0);
721                 return 0;
722             }
723 
724             return 0;
725 
726         case WM_CLOSE:
727             if (fGameStarted == false)
728             {
729                 DestroyWindow(hwnd);
730                 return 0;
731             }
732             else
733             {
734                 int ret;
735 
736                 ret = MessageBox(hwnd, MsgQuit, szAppName, MB_YESNO|MB_ICONQUESTION);
737                 if (ret == IDYES)
738                 {
739                     WinHelp(hwnd, szHelpPath, HELP_QUIT, 0);
740                     DestroyWindow(hwnd);
741                 }
742             }
743             return 0;
744     }
745 
746     return DefWindowProc (hwnd, iMsg, wParam, lParam);
747 }
748 
749 
750 
751