- Add simple multimedia player
[reactos.git] / reactos / base / applications / mplay32 / mplay32.c
1 /*
2 * PROJECT: ReactOS Multimedia Player
3 * FILE: base\applications\mplay32\mplay32.c
4 * PROGRAMMERS: Dmitry Chapyshev (dmitry@reactos.org)
5 */
6
7 #include "mplay32.h"
8
9 #define MAIN_WINDOW_HEIGHT 125
10 #define MAIN_WINDOW_MIN_WIDTH 250
11
12 HINSTANCE hInstance = NULL;
13 HWND hTrackBar = NULL;
14 HWND hToolBar = NULL;
15 TCHAR szAppTitle[256] = _T("");
16 TCHAR szPrevFile[MAX_PATH] = _T("\0");
17 WORD wDeviceId;
18 BOOL bIsOpened = FALSE;
19 BOOL bIsPaused = FALSE;
20 UINT MaxFilePos = 0;
21
22 /* Known types table */
23 static const TYPEBYEXT ExtTypes[] =
24 {
25 { _T(".wav"), WAVE_FILE },
26 { _T(".wave"), WAVE_FILE },
27 { _T(".mid"), MIDI_FILE },
28 { _T(".midi"), MIDI_FILE },
29 { _T(".cda"), AUDIOCD_FILE },
30 { _T(".avi"), AVI_FILE },
31 { _T("\0"), 0 }
32 };
33
34 /* ToolBar Buttons */
35 static const TBBUTTON Buttons[] =
36 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
37 {TBICON_PLAY, IDC_PLAY, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
38 {TBICON_STOP, IDC_STOP, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
39 {TBICON_EJECT, IDC_EJECT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
40 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0},
41 {TBICON_BACKWARD, IDC_BACKWARD, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
42 {TBICON_SEEKBACK, IDC_SEEKBACK, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
43 {TBICON_SEEKFORW, IDC_SEEKFORW, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0},
44 {TBICON_FORWARD, IDC_FORWARD, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}
45 };
46
47 static VOID
48 SetImageList(HWND hwnd)
49 {
50 HIMAGELIST hImageList;
51
52 hImageList = ImageList_Create(16, 16, ILC_MASK | ILC_COLOR24, 1, 1);
53
54 if (!hImageList)
55 {
56 MessageBox(hwnd, _T("ImageList it is not created!"), NULL, MB_OK);
57 return;
58 }
59
60 ImageList_AddMasked(hImageList,
61 LoadImage(hInstance, MAKEINTRESOURCE(IDB_PLAYICON), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR),
62 RGB(255, 255, 255));
63
64 ImageList_AddMasked(hImageList,
65 LoadImage(hInstance, MAKEINTRESOURCE(IDB_STOPICON), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR),
66 RGB(255, 255, 255));
67
68 ImageList_AddMasked(hImageList,
69 LoadImage(hInstance, MAKEINTRESOURCE(IDB_EJECTICON), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR),
70 RGB(255, 255, 255));
71
72 ImageList_AddMasked(hImageList,
73 LoadImage(hInstance, MAKEINTRESOURCE(IDB_BACKWARDICON), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR),
74 RGB(255, 255, 255));
75
76 ImageList_AddMasked(hImageList,
77 LoadImage(hInstance, MAKEINTRESOURCE(IDB_SEEKBACKICON), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR),
78 RGB(255, 255, 255));
79
80 ImageList_AddMasked(hImageList,
81 LoadImage(hInstance, MAKEINTRESOURCE(IDB_SEEKFORWICON), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR),
82 RGB(255, 255, 255));
83
84 ImageList_AddMasked(hImageList,
85 LoadImage(hInstance, MAKEINTRESOURCE(IDB_FORWARDICON), IMAGE_BITMAP, 16, 16, LR_DEFAULTCOLOR),
86 RGB(255, 255, 255));
87
88 ImageList_Destroy((HIMAGELIST)SendMessage(hToolBar,
89 TB_SETIMAGELIST,
90 0,
91 (LPARAM)hImageList));
92 }
93
94 static VOID
95 InitControls(HWND hwnd)
96 {
97 INT NumButtons = sizeof(Buttons) / sizeof(Buttons[0]);
98
99 InitCommonControls();
100
101 /* Create trackbar */
102 hTrackBar = CreateWindowEx(0,
103 TRACKBAR_CLASS,
104 NULL,
105 TBS_ENABLESELRANGE | WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS,
106 0,
107 0,
108 340,
109 30,
110 hwnd,
111 NULL,
112 hInstance,
113 NULL);
114 if (!hTrackBar)
115 {
116 MessageBox(hwnd, _T("TrackBar it is not created!"), NULL, MB_OK);
117 return;
118 }
119
120 /* Create toolbar */
121 hToolBar = CreateWindowEx(0,
122 TOOLBARCLASSNAME,
123 NULL,
124 WS_CHILD | WS_VISIBLE | WS_TABSTOP | WS_CLIPSIBLINGS |
125 TBSTYLE_FLAT | CCS_BOTTOM | TBSTYLE_TOOLTIPS,
126 0,
127 40,
128 340,
129 30,
130 hwnd,
131 NULL,
132 hInstance,
133 NULL);
134 if (!hToolBar)
135 {
136 MessageBox(hwnd, _T("ToolBar it is not created!"), NULL, MB_OK);
137 return;
138 }
139
140 SetImageList(hwnd);
141 SendMessage(hToolBar, TB_ADDBUTTONS, NumButtons, (LPARAM)Buttons);
142 }
143
144 static UINT
145 IsSupportedFileExtension(LPWSTR lpFileName)
146 {
147 TCHAR szExt[MAX_PATH];
148 INT DotPos = 0, i, j;
149
150 for (i = _tcslen(lpFileName); i >= 0; --i)
151 {
152 if (lpFileName[i] == '.')
153 {
154 DotPos = _tcslen(lpFileName) - i;
155 break;
156 }
157 }
158
159 if (!DotPos) return UNSUPPORTED_FILE;
160
161 szExt[DotPos + 1] = _T('\0');
162 for (i = _tcslen(lpFileName), j = DotPos; j >= 0; --i, --j)
163 {
164 szExt[j] = lpFileName[i];
165 }
166
167 for (i = 0; ; i++)
168 {
169 if (ExtTypes[i].uType == UNSUPPORTED_FILE)
170 {
171 return UNSUPPORTED_FILE;
172 }
173
174 if (_tcscmp(ExtTypes[i].szExt, szExt) == 0)
175 {
176 return ExtTypes[i].uType;
177 }
178 }
179
180 return UNSUPPORTED_FILE;
181 }
182
183 static DWORD
184 CloseMciDevice(VOID)
185 {
186 MCI_GENERIC_PARMS mciGeneric;
187 DWORD dwError;
188
189 if (bIsOpened)
190 {
191 dwError = mciSendCommand(wDeviceId, MCI_CLOSE, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGeneric);
192 if (dwError) return dwError;
193 bIsOpened = FALSE;
194 }
195
196 return TRUE;
197 }
198
199 static DWORD
200 OpenMciDevice(LPTSTR lpType, LPTSTR lpFileName)
201 {
202 MCI_STATUS_PARMS mciStatus;
203 MCI_OPEN_PARMS mciOpen;
204 DWORD dwError;
205
206 if (bIsOpened)
207 {
208 CloseMciDevice();
209 }
210
211 mciOpen.lpstrDeviceType = lpType;
212 mciOpen.lpstrElementName = lpFileName;
213 mciOpen.dwCallback = 0;
214 mciOpen.wDeviceID = 0;
215 mciOpen.lpstrAlias = NULL;
216
217 dwError = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE | MCI_OPEN_ELEMENT | MCI_WAIT, (DWORD)(LPVOID)&mciOpen);
218 if (dwError != 0)
219 {
220 MessageBox(0, _T("Can't open device! (1)"), NULL, MB_OK);
221 return dwError;
222 }
223
224 mciStatus.dwItem = MCI_STATUS_LENGTH;
225
226 dwError = mciSendCommand(mciOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM | MCI_WAIT, (DWORD)(LPVOID)&mciStatus);
227 if (dwError != 0)
228 {
229 MessageBox(0, _T("Can't open device! (2)"), NULL, MB_OK);
230 return dwError;
231 }
232
233 SendMessage(hTrackBar, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM) MAKELONG(1, mciStatus.dwReturn));
234 SendMessage(hTrackBar, TBM_SETPAGESIZE, 0, 10);
235 SendMessage(hTrackBar, TBM_SETLINESIZE, 0, 1);
236 SendMessage(hTrackBar, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) 1);
237
238 if (mciStatus.dwReturn < 10000)
239 {
240 SendMessage(hTrackBar, TBM_SETTICFREQ, (WPARAM) 100, (LPARAM) 0);
241 }
242 else if (mciStatus.dwReturn < 100000)
243 {
244 SendMessage(hTrackBar, TBM_SETTICFREQ, (WPARAM) 1000, (LPARAM) 0);
245 }
246 else if (mciStatus.dwReturn < 1000000)
247 {
248 SendMessage(hTrackBar, TBM_SETTICFREQ, (WPARAM) 10000, (LPARAM) 0);
249 }
250 else
251 {
252 SendMessage(hTrackBar, TBM_SETTICFREQ, (WPARAM) 100000, (LPARAM) 0);
253 }
254
255 MaxFilePos = mciStatus.dwReturn;
256 wDeviceId = mciOpen.wDeviceID;
257 bIsOpened = TRUE;
258 lstrcpy(szPrevFile, lpFileName);
259 return TRUE;
260 }
261
262 static VOID
263 StopPlayback(HWND hwnd)
264 {
265 if (bIsOpened)
266 {
267 SendMessage(hTrackBar, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) 1);
268 KillTimer(hwnd, IDT_PLAYTIMER);
269 CloseMciDevice();
270 }
271 }
272
273 static VOID
274 SeekPlayback(HWND hwnd, DWORD dwNewPos)
275 {
276 MCI_SEEK_PARMS mciSeek;
277 MCI_PLAY_PARMS mciPlay;
278 DWORD dwError;
279
280 if (bIsOpened)
281 {
282 mciSeek.dwTo = dwNewPos;
283 dwError = mciSendCommand(wDeviceId, MCI_SEEK, MCI_WAIT | MCI_TO, (DWORD)(LPVOID)&mciSeek);
284 if (dwError != 0)
285 {
286 MessageBox(hwnd, _T("SeekPlayback: Can't seek!"), NULL, MB_OK);
287 }
288
289 mciPlay.dwCallback = (DWORD)hwnd;
290 dwError = mciSendCommand(wDeviceId, MCI_PLAY, MCI_NOTIFY, (DWORD)(LPVOID)&mciPlay);
291 if (dwError != 0)
292 {
293 MessageBox(hwnd, _T("SeekPlayback: Can't play!"), NULL, MB_OK);
294 }
295 }
296 }
297
298 static VOID
299 SeekBackPlayback(HWND hwnd)
300 {
301 MCI_STATUS_PARMS mciStatus;
302 DWORD dwNewPos;
303
304 if (!bIsOpened) return;
305
306 mciStatus.dwItem = MCI_STATUS_POSITION;
307 mciSendCommand(wDeviceId, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)(LPVOID)&mciStatus);
308
309 dwNewPos = mciStatus.dwReturn - 1;
310
311 if((UINT)dwNewPos <= 1)
312 {
313 StopPlayback(hwnd);
314 }
315 else
316 {
317 SeekPlayback(hwnd, dwNewPos);
318 }
319 }
320
321 static VOID
322 SeekForwPlayback(HWND hwnd)
323 {
324 MCI_STATUS_PARMS mciStatus;
325 DWORD dwNewPos;
326
327 if (!bIsOpened) return;
328
329 mciStatus.dwItem = MCI_STATUS_POSITION;
330 mciSendCommand(wDeviceId, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)(LPVOID)&mciStatus);
331
332 dwNewPos = mciStatus.dwReturn + 1;
333
334 if((UINT)dwNewPos >= MaxFilePos)
335 {
336 StopPlayback(hwnd);
337 }
338 else
339 {
340 SeekPlayback(hwnd, dwNewPos);
341 }
342 }
343
344 static VOID
345 PausePlayback(HWND hwnd)
346 {
347 MCI_GENERIC_PARMS mciGeneric;
348 DWORD dwError;
349
350 if (bIsOpened)
351 {
352 dwError = mciSendCommand(wDeviceId, MCI_PAUSE, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGeneric);
353 if (dwError != 0)
354 {
355 MessageBox(hwnd, _T("Can't pause!"), NULL, MB_OK);
356 }
357 bIsPaused = TRUE;
358 }
359 }
360
361 static VOID
362 ResumePlayback(HWND hwnd)
363 {
364 MCI_GENERIC_PARMS mciGeneric;
365 DWORD dwError;
366
367 if (bIsPaused)
368 {
369 dwError = mciSendCommand(wDeviceId, MCI_RESUME, MCI_WAIT, (DWORD)(LPMCI_GENERIC_PARMS)&mciGeneric);
370 if (dwError != 0)
371 {
372 MessageBox(hwnd, _T("Can't resume!"), NULL, MB_OK);
373 }
374 bIsPaused = FALSE;
375 }
376 }
377
378 VOID CALLBACK
379 PlayTimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
380 {
381 MCI_STATUS_PARMS mciStatus;
382 DWORD dwPos;
383
384 if (!bIsOpened) KillTimer(hwnd, IDT_PLAYTIMER);
385
386 mciStatus.dwItem = MCI_STATUS_POSITION;
387 mciSendCommand(wDeviceId, MCI_STATUS, MCI_STATUS_ITEM, (DWORD)(LPVOID)&mciStatus);
388 dwPos = mciStatus.dwReturn;
389
390 if((UINT)dwPos >= MaxFilePos)
391 {
392 StopPlayback(hwnd);
393 }
394 else
395 {
396 SendMessage(hTrackBar, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) dwPos);
397 }
398 }
399
400 static VOID
401 PlayFile(HWND hwnd, LPWSTR lpFileName)
402 {
403 MCI_PLAY_PARMS mciPlay;
404 TCHAR szLocalFileName[MAX_PATH];
405 UINT FileType;
406 DWORD dwError;
407
408 if (lpFileName == NULL)
409 {
410 if (szPrevFile[0] == _T('\0'))
411 return;
412
413 lstrcpy(szLocalFileName, szPrevFile);
414 }
415 else
416 {
417 lstrcpy(szLocalFileName, lpFileName);
418 }
419
420 if (GetFileAttributes(szLocalFileName) == INVALID_FILE_ATTRIBUTES)
421 {
422 MessageBox(hwnd, _T("Wrong path to a file!"), NULL, MB_OK);
423 return;
424 }
425
426 FileType = IsSupportedFileExtension(szLocalFileName);
427
428 switch (FileType)
429 {
430 case UNSUPPORTED_FILE:
431 MessageBox(hwnd, _T("Unsupported format!"), NULL, MB_OK);
432 return;
433 case WAVE_FILE:
434 OpenMciDevice(_T("waveaudio"), szLocalFileName);
435 break;
436 case MIDI_FILE:
437 OpenMciDevice(_T("sequencer"), szLocalFileName);
438 break;
439 case AUDIOCD_FILE:
440 OpenMciDevice(_T("cdaudio"), szLocalFileName);
441 break;
442 case AVI_FILE:
443 OpenMciDevice(_T("avivideo"), szLocalFileName);
444 break;
445 }
446
447 SetTimer(hwnd, IDT_PLAYTIMER, 100, (TIMERPROC) PlayTimerProc);
448
449 dwError = mciSendCommand(wDeviceId, MCI_SEEK, MCI_WAIT | MCI_SEEK_TO_START, 0);
450
451 mciPlay.dwCallback = (DWORD)hwnd;
452 mciPlay.dwFrom = 0;
453 mciPlay.dwTo = MaxFilePos;
454
455 dwError = mciSendCommand(wDeviceId, MCI_PLAY, MCI_NOTIFY | MCI_FROM | MCI_TO, (DWORD)(LPVOID)&mciPlay);
456 if (dwError != 0)
457 {
458 MessageBox(hwnd, _T("Can't play!"), NULL, MB_OK);
459 }
460 }
461
462 static VOID
463 OpenFileDialog(HWND hwnd)
464 {
465 OPENFILENAME OpenFileName;
466 TCHAR szFile[MAX_PATH + 1] = _T("\0");
467 TCHAR szFilter[MAX_PATH], szCurrentDir[MAX_PATH];
468
469 ZeroMemory(&OpenFileName, sizeof(OpenFileName));
470
471 LoadString(hInstance, IDS_ALL_TYPES_FILTER, szFilter, sizeof(szFilter) / sizeof(TCHAR));
472
473 if (!GetCurrentDirectory(sizeof(szCurrentDir) / sizeof(TCHAR), szCurrentDir))
474 {
475 lstrcpy(szCurrentDir, _T("c:\\"));
476 }
477
478 OpenFileName.lStructSize = sizeof(OpenFileName);
479 OpenFileName.hwndOwner = hwnd;
480 OpenFileName.hInstance = hInstance;
481 OpenFileName.lpstrFilter = szFilter;
482 OpenFileName.lpstrFile = szFile;
483 OpenFileName.nMaxFile = sizeof(szFile) / sizeof((szFile)[0]);
484 OpenFileName.lpstrInitialDir = szCurrentDir;
485 OpenFileName.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_SHAREAWARE;
486 OpenFileName.lpstrDefExt = _T("\0");
487
488 if (GetOpenFileName(&OpenFileName))
489 {
490 PlayFile(hwnd, OpenFileName.lpstrFile);
491 }
492 }
493
494 LRESULT CALLBACK
495 MainWndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
496 {
497 switch (Message)
498 {
499 case WM_CREATE:
500 InitControls(hwnd);
501 break;
502
503 case WM_NOTIFY:
504 {
505 LPNMHDR pnmhdr = (LPNMHDR)lParam;
506
507 switch (pnmhdr->code)
508 {
509 case TTN_GETDISPINFO:
510 {
511 LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT)lParam;
512 UINT idButton = (UINT)lpttt->hdr.idFrom;
513
514 switch (idButton)
515 {
516 case IDC_PLAY:
517 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PLAY);
518 break;
519 case IDC_STOP:
520 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_STOP);
521 break;
522 case IDC_EJECT:
523 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EJECT);
524 break;
525 case IDC_BACKWARD:
526 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_BACKWARD);
527 break;
528 case IDC_SEEKBACK:
529 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_SEEKBACK);
530 break;
531 case IDC_SEEKFORW:
532 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_SEEKFORW);
533 break;
534 case IDC_FORWARD:
535 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_FORWARD);
536 break;
537 }
538 break;
539 }
540 }
541 }
542 break;
543
544 case WM_SIZING:
545 {
546 LPRECT pRect = (LPRECT)lParam;
547
548 if (pRect->right - pRect->left < MAIN_WINDOW_MIN_WIDTH)
549 pRect->right = pRect->left + MAIN_WINDOW_MIN_WIDTH;
550
551 if (pRect->bottom - pRect->top != MAIN_WINDOW_HEIGHT)
552 pRect->bottom = pRect->top + MAIN_WINDOW_HEIGHT;
553
554 return TRUE;
555 }
556
557 case WM_SIZE:
558 {
559 RECT Rect;
560 UINT Size;
561
562 if (hToolBar && hTrackBar)
563 {
564 SendMessage(hToolBar, TB_AUTOSIZE, 0, 0);
565 SendMessage(hToolBar, TB_GETITEMRECT, 1, (LPARAM)&Rect);
566
567 Size = GetSystemMetrics(SM_CYMENU) + Rect.bottom;
568 MoveWindow(hTrackBar, 0, 0, LOWORD(lParam), HIWORD(lParam) - Size, TRUE);
569 }
570 return 0L;
571 }
572
573 case WM_HSCROLL:
574 {
575 if (hTrackBar == (HWND) lParam)
576 {
577 DWORD dwNewPos = (DWORD) SendMessage(hTrackBar, TBM_GETPOS, 0, 0);
578 SeekPlayback(hwnd, dwNewPos);
579 }
580 }
581 break;
582
583 case WM_COMMAND:
584 switch (LOWORD(wParam))
585 {
586 case IDC_PLAY:
587 if (bIsOpened)
588 {
589 if (bIsPaused)
590 ResumePlayback(hwnd);
591 else
592 PausePlayback(hwnd);
593 }
594 else
595 {
596 if (szPrevFile[0] == _T('\0'))
597 OpenFileDialog(hwnd);
598 else
599 PlayFile(hwnd, NULL);
600 }
601 break;
602
603 case IDC_STOP:
604 StopPlayback(hwnd);
605 break;
606
607 case IDC_EJECT:
608 break;
609
610 case IDC_BACKWARD:
611 break;
612
613 case IDC_SEEKBACK:
614 SeekBackPlayback(hwnd);
615 break;
616
617 case IDC_SEEKFORW:
618 SeekForwPlayback(hwnd);
619 break;
620
621 case IDC_FORWARD:
622 break;
623
624 case IDM_OPEN_FILE:
625 OpenFileDialog(hwnd);
626 return 0;
627
628 case IDM_CLOSE_FILE:
629 StopPlayback(hwnd);
630 lstrcpy(szPrevFile, _T("\0"));
631 break;
632
633 case IDM_ABOUT:
634 ShellAbout(hwnd, szAppTitle, 0, 0);
635 break;
636
637 case IDM_EXIT:
638 PostMessage(hwnd, WM_CLOSE, 0, 0);
639 return 0;
640 }
641 break;
642
643 case WM_DESTROY:
644 StopPlayback(hwnd);
645 PostQuitMessage(0);
646 return 0;
647 }
648
649 return DefWindowProc(hwnd, Message, wParam, lParam);
650 }
651
652 INT WINAPI
653 _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, INT nCmdShow)
654 {
655 WNDCLASSEX WndClass = {0};
656 TCHAR szClassName[] = _T("ROSMPLAY32");
657 HWND hwnd;
658 MSG msg;
659
660 hInstance = hInst;
661
662 LoadString(hInstance, IDS_APPTITLE, szAppTitle, sizeof(szAppTitle) / sizeof(TCHAR));
663
664 WndClass.cbSize = sizeof(WNDCLASSEX);
665 WndClass.lpszClassName = szClassName;
666 WndClass.lpfnWndProc = MainWndProc;
667 WndClass.hInstance = hInstance;
668 WndClass.style = CS_HREDRAW | CS_VREDRAW;
669 WndClass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_MAIN));
670 WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
671 WndClass.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
672 WndClass.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
673
674 RegisterClassEx(&WndClass);
675
676 hwnd = CreateWindow(szClassName,
677 szAppTitle,
678 WS_SYSMENU | WS_MINIMIZEBOX | WS_THICKFRAME | WS_OVERLAPPED | WS_CAPTION | WS_CLIPCHILDREN,
679 CW_USEDEFAULT,
680 CW_USEDEFAULT,
681 350,
682 MAIN_WINDOW_HEIGHT,
683 NULL,
684 NULL,
685 hInstance,
686 NULL);
687
688 /* Show it */
689 ShowWindow(hwnd, SW_SHOW);
690 UpdateWindow(hwnd);
691
692 /* Message Loop */
693 while (GetMessage(&msg, NULL, 0, 0))
694 {
695 TranslateMessage(&msg);
696 DispatchMessage(&msg);
697 }
698
699 return 0;
700 }