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