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