519b534dc19c149d965b427e7de42d4d74e98acd
[reactos.git] / base / applications / games / spider / spider.cpp
1 /*
2 * PROJECT: Spider Solitaire
3 * LICENSE: See COPYING in top level directory
4 * FILE: base/applications/games/spider/spider.cpp
5 * PURPOSE: Window and message queue for Spider Solitaire
6 * PROGRAMMER: Gregor Schneider
7 */
8
9 #include "spider.h"
10
11 #include <commctrl.h>
12 #include <tchar.h>
13
14 TCHAR szHelpPath[MAX_PATH];
15
16 DWORD dwAppStartTime;
17 HWND hwndMain;
18 HINSTANCE hInstance;
19
20 TCHAR szAppName[128];
21 TCHAR MsgQuit[128];
22 TCHAR MsgAbout[128];
23 TCHAR MsgWin[128];
24 TCHAR MsgDeal[128];
25 DWORD dwDifficulty;
26
27 CardWindow SpiderWnd;
28
29 typedef struct _CardBack
30 {
31 HWND hSelf;
32 WNDPROC hOldProc;
33 INT hdcNum;
34 INT imgNum;
35 BOOL bSelected;
36 } CARDBACK, *PCARDBACK;
37
38 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam);
39
40 void MakePath(TCHAR *szDest, UINT nDestLen, const TCHAR *szExt)
41 {
42 TCHAR *ptr;
43
44 ptr = szDest + GetModuleFileName(GetModuleHandle(0), szDest, nDestLen) - 1;
45 while(*ptr-- != '.');
46 lstrcpy(ptr + 1, szExt);
47 }
48
49 INT_PTR CALLBACK DifficultyDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
50 {
51 switch (uMsg)
52 {
53 case WM_INITDIALOG:
54 CheckRadioButton(hDlg, IDC_DIF_ONECOLOR, IDC_DIF_FOURCOLORS, IDC_DIF_ONECOLOR);
55 return TRUE;
56
57 case WM_COMMAND:
58 switch(LOWORD(wParam))
59 {
60 case IDOK:
61 if (IsDlgButtonChecked(hDlg, IDC_DIF_ONECOLOR) == BST_CHECKED)
62 dwDifficulty = IDC_DIF_ONECOLOR;
63 else if (IsDlgButtonChecked(hDlg, IDC_DIF_TWOCOLORS) == BST_CHECKED)
64 dwDifficulty = IDC_DIF_TWOCOLORS;
65 else if (IsDlgButtonChecked(hDlg, IDC_DIF_FOURCOLORS) == BST_CHECKED)
66 dwDifficulty = IDC_DIF_FOURCOLORS;
67
68 NewGame();
69 EndDialog(hDlg, TRUE);
70 return TRUE;
71
72 case IDCANCEL:
73 EndDialog(hDlg, FALSE);
74 return TRUE;
75 }
76 break;
77 }
78 return FALSE;
79 }
80
81 int WINAPI _tWinMain(HINSTANCE hInst, HINSTANCE hPrev, LPTSTR szCmdLine, int iCmdShow)
82 {
83 HWND hwnd;
84 MSG msg;
85 WNDCLASS wndclass;
86 INITCOMMONCONTROLSEX ice;
87 HACCEL hAccelTable;
88
89 hInstance = hInst;
90
91 /* Load application title */
92 LoadString(hInst, IDS_SPI_NAME, szAppName, sizeof(szAppName) / sizeof(szAppName[0]));
93 /* Load MsgBox() texts here to avoid loading them many times later */
94 LoadString(hInst, IDS_SPI_ABOUT, MsgAbout, sizeof(MsgAbout) / sizeof(MsgAbout[0]));
95 LoadString(hInst, IDS_SPI_QUIT, MsgQuit, sizeof(MsgQuit) / sizeof(MsgQuit[0]));
96 LoadString(hInst, IDS_SPI_WIN, MsgWin, sizeof(MsgWin) / sizeof(MsgWin[0]));
97 LoadString(hInst, IDS_SPI_DEAL, MsgDeal, sizeof(MsgDeal) / sizeof(MsgDeal[0]));
98
99 /* Window class for the main application parent window */
100 wndclass.style = 0;
101 wndclass.lpfnWndProc = WndProc;
102 wndclass.cbClsExtra = 0;
103 wndclass.cbWndExtra = 0;
104 wndclass.hInstance = hInst;
105 wndclass.hIcon = LoadIcon (hInst, MAKEINTRESOURCE(IDI_SPIDER));
106 wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
107 wndclass.hbrBackground = (HBRUSH)NULL;
108 wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
109 wndclass.lpszClassName = szAppName;
110
111 RegisterClass(&wndclass);
112
113 ice.dwSize = sizeof(ice);
114 ice.dwICC = ICC_BAR_CLASSES;
115 InitCommonControlsEx(&ice);
116
117 srand((unsigned)GetTickCount());
118
119 /* InitCardLib(); */
120
121 /* Construct the path to our help file */
122 MakePath(szHelpPath, MAX_PATH, _T(".hlp"));
123
124 hwnd = CreateWindow(szAppName,
125 szAppName,
126 WS_OVERLAPPEDWINDOW,
127 CW_USEDEFAULT,
128 CW_USEDEFAULT,
129 0, /*The real size will be computed in WndProc through WM_GETMINMAXINFO */
130 0, /* The real size will be computed in WndProc through WM_GETMINMAXINFO */
131 NULL,
132 NULL,
133 hInst,
134 NULL);
135
136 hwndMain = hwnd;
137
138 ShowWindow(hwnd, iCmdShow);
139 UpdateWindow(hwnd);
140
141 hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
142
143 DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIFFICULTY), hwnd, DifficultyDlgProc);
144
145 while (GetMessage(&msg, NULL,0,0))
146 {
147 if (!TranslateAccelerator(hwnd, hAccelTable, &msg))
148 {
149 TranslateMessage(&msg);
150 DispatchMessage(&msg);
151 }
152 }
153 return msg.wParam;
154 }
155
156 LRESULT CALLBACK CardImageWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
157 {
158 PCARDBACK pCardBack = (PCARDBACK)GetWindowLongPtr(hwnd, GWL_USERDATA);
159 static WNDPROC hOldProc = NULL;
160
161 if (!pCardBack)
162 return FALSE;
163
164 if (!hOldProc)
165 hOldProc = pCardBack->hOldProc;
166
167 switch (msg)
168 {
169 case WM_PAINT:
170 {
171 HDC hdc;
172 PAINTSTRUCT ps;
173 HPEN hPen, hOldPen;
174 HBRUSH hBrush, hOldBrush;
175 RECT rc;
176
177 hdc = BeginPaint(hwnd, &ps);
178
179 if (pCardBack->bSelected)
180 {
181 hPen = CreatePen(PS_SOLID, 2, RGB(0,0,0));
182 }
183 else
184 {
185 DWORD Face = GetSysColor(COLOR_3DFACE);
186 hPen = CreatePen(PS_SOLID, 2, Face);
187 }
188
189 GetClientRect(hwnd, &rc);
190 hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
191 hOldPen = (HPEN)SelectObject(hdc, hPen);
192 hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
193
194 Rectangle(hdc, rc.left+1, rc.top+1, rc.right, rc.bottom);
195
196 StretchBlt(hdc,
197 2,
198 2,
199 CARDBACK_OPTIONS_WIDTH,
200 CARDBACK_OPTIONS_HEIGHT,
201 __hdcCardBitmaps,
202 pCardBack->hdcNum * __cardwidth,
203 0,
204 __cardwidth,
205 __cardheight,
206 SRCCOPY);
207
208 SelectObject(hdc, hOldPen);
209 SelectObject(hdc, hOldBrush);
210
211 EndPaint(hwnd, &ps);
212
213 break;
214 }
215
216 case WM_LBUTTONDOWN:
217 pCardBack->bSelected = pCardBack->bSelected ? FALSE : TRUE;
218 break;
219 }
220
221 return CallWindowProc(hOldProc, hwnd, msg, wParam, lParam);
222 }
223
224
225 INT_PTR CALLBACK CardBackDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
226 {
227 static PCARDBACK pCardBacks = NULL;
228
229 switch (uMsg)
230 {
231 case WM_INITDIALOG:
232 {
233 INT i, c;
234 SIZE_T size = sizeof(CARDBACK) * NUM_CARDBACKS;
235
236 pCardBacks = (PCARDBACK)HeapAlloc(GetProcessHeap(), 0, size);
237
238 if (!pCardBacks)
239 return FALSE;
240
241 for (i = 0, c = CARDBACK_START; c <= CARDBACK_END; i++, c++)
242 {
243 pCardBacks[i].hSelf = GetDlgItem(hDlg, c);
244 pCardBacks[i].bSelected = FALSE;
245 pCardBacks[i].hdcNum = CARDBACK_RES_START + i;
246 pCardBacks[i].imgNum = i + 1;
247 pCardBacks[i].hOldProc = (WNDPROC)SetWindowLongPtr(pCardBacks[i].hSelf,
248 GWLP_WNDPROC,
249 (LONG_PTR)CardImageWndProc);
250
251 SetWindowLongPtr(pCardBacks[i].hSelf, GWL_USERDATA, (LONG_PTR)&pCardBacks[i]);
252 }
253
254 return TRUE;
255 }
256
257 case WM_COMMAND:
258 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
259 {
260 INT i, num = 0;
261 for (i = 0; i < NUM_CARDBACKS; i++)
262 {
263 if (pCardBacks[i].bSelected)
264 {
265 num = pCardBacks[i].imgNum;
266 }
267 }
268
269 EndDialog(hDlg, LOWORD(wParam) == IDOK ? num : FALSE);
270 HeapFree(GetProcessHeap(), 0, pCardBacks);
271 return TRUE;
272 }
273
274 if (HIWORD(wParam) == STN_CLICKED)
275 {
276 INT i;
277 RECT rc;
278 for (i = 0; i < NUM_CARDBACKS; i++)
279 {
280 pCardBacks[i].bSelected = pCardBacks[i].hSelf == (HWND)lParam;
281
282 GetClientRect(pCardBacks[i].hSelf, &rc);
283 InvalidateRect(pCardBacks[i].hSelf, &rc, TRUE);
284 }
285
286 break;
287 }
288 }
289
290 return FALSE;
291 }
292
293
294 VOID ShowDeckOptionsDlg(HWND hwnd)
295 {
296 INT cardBack;
297
298 if ((cardBack = DialogBox(hInstance, MAKEINTRESOURCE(IDD_CARDBACK), hwnd, CardBackDlgProc)))
299 {
300 SpiderWnd.SetBackCardIdx(CARDBACK_RES_START + (cardBack - 1));
301 SpiderWnd.Redraw();
302 }
303 }
304
305 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
306 {
307 static int nWidth, nHeight;
308
309 switch (iMsg)
310 {
311 case WM_CREATE:
312 {
313 SpiderWnd.Create(hwnd, 0, WS_CHILD | WS_VISIBLE, 0, 0, 100, 100);
314 dwDifficulty = IDC_DIF_ONECOLOR;
315 CreateSpider();
316
317 SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOZORDER);
318
319 dwAppStartTime = GetTickCount();
320
321 return 0;
322 }
323
324 case WM_DESTROY:
325 PostQuitMessage(0);
326 return 0;
327
328 case WM_SIZE:
329 nWidth = LOWORD(lParam);
330 nHeight = HIWORD(lParam);
331
332 MoveWindow(SpiderWnd, 0, 0, nWidth, nHeight, TRUE);
333 return 0;
334
335 case WM_GETMINMAXINFO:
336 {
337 MINMAXINFO *mmi;
338
339 mmi = (MINMAXINFO *)lParam;
340 mmi->ptMinTrackSize.x = NUM_STACKS * __cardwidth + (NUM_STACKS + 3) * X_BORDER + 12; // Border left and right of 6px
341 mmi->ptMinTrackSize.y = GetSystemMetrics(SM_CYCAPTION) +
342 GetSystemMetrics(SM_CYMENU) +
343 2 * Y_BORDER +
344 3 * __cardheight +
345 6 * yRowStackCardOffset;
346 return 0;
347 }
348
349 case WM_COMMAND:
350 switch (LOWORD(wParam))
351 {
352 case IDM_GAME_NEW:
353 NewGame();
354 return 0;
355
356 case IDM_GAME_DECK:
357 ShowDeckOptionsDlg(hwnd);
358 return 0;
359
360 case IDM_HELP_CONTENTS:
361 WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play");
362 return 0;
363
364 case IDM_HELP_ABOUT:
365 MessageBox(hwnd, MsgAbout, szAppName, MB_OK|MB_ICONINFORMATION);
366 return 0;
367
368 case IDM_GAME_EXIT:
369 PostMessage(hwnd, WM_CLOSE, 0, 0);
370 return 0;
371 }
372
373 return 0;
374
375 case WM_CLOSE:
376 if (fGameStarted == false)
377 {
378 DestroyWindow(hwnd);
379 return 0;
380 }
381 else
382 {
383 int ret;
384
385 ret = MessageBox(hwnd, MsgQuit, szAppName, MB_YESNO|MB_ICONQUESTION);
386 if (ret == IDYES)
387 {
388 WinHelp(hwnd, szHelpPath, HELP_QUIT, 0);
389 DestroyWindow(hwnd);
390 }
391 }
392 return 0;
393 }
394 return DefWindowProc (hwnd, iMsg, wParam, lParam);
395 }
396