95df4c32de6c9b59bdff3dd6aa17f065db4b3cb5
[reactos.git] / reactos / 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
157 CardImageWndProc(HWND hwnd,
158 UINT msg,
159 WPARAM wParam,
160 LPARAM lParam)
161 {
162 PCARDBACK pCardBack = (PCARDBACK)GetWindowLongPtr(hwnd,
163 GWL_USERDATA);
164 static WNDPROC hOldProc = NULL;
165
166 if (!hOldProc && pCardBack)
167 hOldProc = pCardBack->hOldProc;
168
169 switch (msg)
170 {
171 case WM_PAINT:
172 {
173 HDC hdc;
174 PAINTSTRUCT ps;
175 HPEN hPen, hOldPen;
176 HBRUSH hBrush, hOldBrush;
177 RECT rc;
178
179 hdc = BeginPaint(hwnd, &ps);
180
181 if (pCardBack->bSelected)
182 {
183 hPen = CreatePen(PS_SOLID, 2, RGB(0,0,0));
184 }
185 else
186 {
187 DWORD Face = GetSysColor(COLOR_3DFACE);
188 hPen = CreatePen(PS_SOLID, 2, Face);
189 }
190
191 GetClientRect(hwnd, &rc);
192 hBrush = (HBRUSH)GetStockObject(NULL_BRUSH);
193 hOldPen = (HPEN)SelectObject(hdc, hPen);
194 hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
195
196 Rectangle(hdc,
197 rc.left+1,
198 rc.top+1,
199 rc.right,
200 rc.bottom);
201
202 StretchBlt(hdc,
203 2,
204 2,
205 CARDBACK_OPTIONS_WIDTH,
206 CARDBACK_OPTIONS_HEIGHT,
207 __hdcCardBitmaps,
208 pCardBack->hdcNum * __cardwidth,
209 0,
210 __cardwidth,
211 __cardheight,
212 SRCCOPY);
213
214 SelectObject(hdc, hOldPen);
215 SelectObject(hdc, hOldBrush);
216
217 EndPaint(hwnd, &ps);
218
219 break;
220 }
221
222 case WM_LBUTTONDOWN:
223 pCardBack->bSelected = pCardBack->bSelected ? FALSE : TRUE;
224 break;
225 }
226
227 return CallWindowProc(hOldProc,
228 hwnd,
229 msg,
230 wParam,
231 lParam);
232 }
233
234
235 INT_PTR CALLBACK CardBackDlgProc(HWND hDlg,
236 UINT uMsg,
237 WPARAM wParam,
238 LPARAM lParam)
239 {
240 static PCARDBACK pCardBacks = NULL;
241
242 switch (uMsg)
243 {
244 case WM_INITDIALOG:
245 {
246 INT i, c;
247 SIZE_T size = sizeof(CARDBACK) * NUM_CARDBACKS;
248
249 pCardBacks = (PCARDBACK)HeapAlloc(GetProcessHeap(),
250 0,
251 size);
252
253 for (i = 0, c = CARDBACK_START; c <= CARDBACK_END; i++, c++)
254 {
255 pCardBacks[i].hSelf = GetDlgItem(hDlg, c);
256 pCardBacks[i].bSelected = FALSE;
257 pCardBacks[i].hdcNum = CARDBACK_RES_START + i;
258 pCardBacks[i].imgNum = i + 1;
259 pCardBacks[i].hOldProc = (WNDPROC)SetWindowLongPtr(pCardBacks[i].hSelf,
260 GWLP_WNDPROC,
261 (LONG_PTR)CardImageWndProc);
262
263 SetWindowLongPtr(pCardBacks[i].hSelf,
264 GWL_USERDATA,
265 (LONG_PTR)&pCardBacks[i]);
266 }
267
268 return TRUE;
269 }
270
271 case WM_COMMAND:
272 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
273 {
274 INT i, num = 0;
275 for (i = 0; i < NUM_CARDBACKS; i++)
276 {
277 if (pCardBacks[i].bSelected)
278 {
279 num = pCardBacks[i].imgNum;
280 }
281 }
282
283 EndDialog(hDlg, LOWORD(wParam) == IDOK ? num : FALSE);
284 HeapFree(GetProcessHeap(), 0, pCardBacks);
285 return TRUE;
286 }
287
288 if (HIWORD(wParam) == STN_CLICKED)
289 {
290 INT i;
291 RECT rc;
292 for (i = 0; i < NUM_CARDBACKS; i++)
293 {
294 if (pCardBacks[i].hSelf == (HWND)lParam)
295 {
296 pCardBacks[i].bSelected = TRUE;
297 }
298 else
299 pCardBacks[i].bSelected = FALSE;
300
301 GetClientRect(pCardBacks[i].hSelf, &rc);
302 InvalidateRect(pCardBacks[i].hSelf, &rc, TRUE);
303 }
304
305 break;
306 }
307 }
308
309 return FALSE;
310 }
311
312
313 VOID ShowDeckOptionsDlg(HWND hwnd)
314 {
315 INT cardBack;
316
317 if ((cardBack = DialogBox(hInstance,
318 MAKEINTRESOURCE(IDD_CARDBACK),
319 hwnd,
320 CardBackDlgProc)))
321 {
322 SpiderWnd.SetBackCardIdx(CARDBACK_RES_START + (cardBack - 1));
323 SpiderWnd.Redraw();
324 }
325 }
326
327 LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
328 {
329 static int nWidth, nHeight;
330
331 switch(iMsg)
332 {
333 case WM_CREATE:
334 {
335 SpiderWnd.Create(hwnd, WS_EX_CLIENTEDGE, WS_CHILD|WS_VISIBLE, 0, 0, 0, 0);
336 dwDifficulty = IDC_DIF_ONECOLOR;
337 CreateSpider();
338
339 SetWindowPos(hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOZORDER);
340
341 dwAppStartTime = GetTickCount();
342
343 return 0;
344 }
345
346 case WM_DESTROY:
347 PostQuitMessage(0);
348 return 0;
349
350 case WM_SIZE:
351 nWidth = LOWORD(lParam);
352 nHeight = HIWORD(lParam);
353
354 MoveWindow(SpiderWnd, 0, 0, nWidth, nHeight, TRUE);
355 return 0;
356
357 case WM_GETMINMAXINFO:
358 {
359 MINMAXINFO *mmi;
360
361 mmi = (MINMAXINFO *)lParam;
362 mmi->ptMinTrackSize.x = NUM_STACKS * __cardwidth + (NUM_STACKS + 3) * X_BORDER;
363 mmi->ptMinTrackSize.y = GetSystemMetrics(SM_CYCAPTION) +
364 GetSystemMetrics(SM_CYMENU) +
365 2 * Y_BORDER +
366 3 * __cardheight +
367 6 * yRowStackCardOffset;
368 return 0;
369 }
370
371 case WM_COMMAND:
372 switch(LOWORD(wParam))
373 {
374 case IDM_GAME_NEW:
375 NewGame();
376 return 0;
377
378 case IDM_GAME_DECK:
379 ShowDeckOptionsDlg(hwnd);
380 return 0;
381
382 case IDM_HELP_CONTENTS:
383 WinHelp(hwnd, szHelpPath, HELP_CONTENTS, 0);//HELP_KEY, (DWORD)"How to play");
384 return 0;
385
386 case IDM_HELP_ABOUT:
387 MessageBox(hwnd, MsgAbout, szAppName, MB_OK|MB_ICONINFORMATION);
388 return 0;
389
390 case IDM_GAME_EXIT:
391 PostMessage(hwnd, WM_CLOSE, 0, 0);
392 return 0;
393 }
394
395 return 0;
396
397 case WM_CLOSE:
398 if (fGameStarted == false)
399 {
400 DestroyWindow(hwnd);
401 return 0;
402 }
403 else
404 {
405 int ret;
406
407 ret = MessageBox(hwnd, MsgQuit, szAppName, MB_YESNO|MB_ICONQUESTION);
408 if (ret == IDYES)
409 {
410 WinHelp(hwnd, szHelpPath, HELP_QUIT, 0);
411 DestroyWindow(hwnd);
412 }
413 }
414 return 0;
415 }
416 return DefWindowProc (hwnd, iMsg, wParam, lParam);
417 }
418