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