[INTL]
[reactos.git] / base / applications / mscutils / devmgmt / mainwnd.c
1 /*
2 * PROJECT: ReactOS Device Managment
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/devmgmt/mainwnd.c
5 * PURPOSE: Main window message handler
6 * COPYRIGHT: Copyright 2006 Ged Murphy <gedmurphy@gmail.com>
7 *
8 */
9
10 #include "precomp.h"
11
12 #include <windowsx.h>
13
14 static BOOL pCreateToolbar(PMAIN_WND_INFO Info);
15
16 static const TCHAR szMainWndClass[] = TEXT("DevMgmtWndClass");
17
18
19 /* Toolbar buttons */
20 TBBUTTON Buttons [] =
21 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
22 {TBICON_PROP, IDC_PROP, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0}, /* properties */
23 {TBICON_REFRESH, IDC_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* refresh */
24
25 /* Note: First item for a seperator is its width in pixels */
26 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
27
28 {TBICON_HELP, IDC_PROGHELP,TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* help */
29 {TBICON_EXIT, IDC_EXIT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }, /* exit */
30
31 };
32
33
34 /* menu hints */
35 static const MENU_HINT MainMenuHintTable[] = {
36 /* File Menu */
37 {IDC_EXIT, IDS_HINT_EXIT},
38
39 /* Action Menu */
40 {IDC_REFRESH, IDS_HINT_REFRESH},
41 {IDC_PROP, IDS_HINT_PROP},
42
43 /* Help Menu */
44 {IDC_PROGHELP, IDS_HINT_HELP},
45 {IDC_ABOUT, IDS_HINT_ABOUT}
46 };
47
48 /* system menu hints */
49 static const MENU_HINT SystemMenuHintTable[] = {
50 {SC_RESTORE, IDS_HINT_SYS_RESTORE},
51 {SC_MOVE, IDS_HINT_SYS_MOVE},
52 {SC_SIZE, IDS_HINT_SYS_SIZE},
53 {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
54 {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
55 {SC_CLOSE, IDS_HINT_SYS_CLOSE},
56 };
57
58
59 static BOOL
60 MainWndMenuHint(PMAIN_WND_INFO Info,
61 WORD CmdId,
62 const MENU_HINT *HintArray,
63 DWORD HintsCount,
64 UINT DefHintId)
65 {
66 BOOL Found = FALSE;
67 const MENU_HINT *LastHint;
68 UINT HintId = DefHintId;
69
70 LastHint = HintArray + HintsCount;
71 while (HintArray != LastHint)
72 {
73 if (HintArray->CmdId == CmdId)
74 {
75 HintId = HintArray->HintId;
76 Found = TRUE;
77 break;
78 }
79 HintArray++;
80 }
81
82 StatusBarLoadString(Info->hStatus,
83 SB_SIMPLEID,
84 hInstance,
85 HintId);
86
87 return Found;
88 }
89
90
91 static VOID
92 UpdateMainStatusBar(PMAIN_WND_INFO Info)
93 {
94 if (Info->hStatus != NULL)
95 {
96 SendMessage(Info->hStatus,
97 SB_SIMPLE,
98 (WPARAM)Info->InMenuLoop,
99 0);
100 }
101 }
102
103
104 static BOOL
105 pCreateToolbar(PMAIN_WND_INFO Info)
106 {
107 INT NumButtons = sizeof(Buttons) / sizeof(Buttons[0]);
108
109 Info->hTool = CreateWindowEx(0,
110 TOOLBARCLASSNAME,
111 NULL,
112 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS,
113 0, 0, 0, 0,
114 Info->hMainWnd,
115 (HMENU)IDC_TOOLBAR,
116 hInstance,
117 NULL);
118 if(Info->hTool != NULL)
119 {
120 HIMAGELIST hImageList;
121
122 SendMessage(Info->hTool,
123 TB_SETEXTENDEDSTYLE,
124 0,
125 TBSTYLE_EX_HIDECLIPPEDBUTTONS);
126
127 SendMessage(Info->hTool,
128 TB_BUTTONSTRUCTSIZE,
129 sizeof(Buttons[0]),
130 0);
131
132 hImageList = InitImageList(IDB_PROP,
133 IDB_EXIT,
134 16,
135 16);
136 if (hImageList == NULL)
137 return FALSE;
138
139 ImageList_Destroy((HIMAGELIST)SendMessage(Info->hTool,
140 TB_SETIMAGELIST,
141 0,
142 (LPARAM)hImageList));
143
144 SendMessage(Info->hTool,
145 TB_ADDBUTTONS,
146 NumButtons,
147 (LPARAM)Buttons);
148
149 return TRUE;
150 }
151
152 return FALSE;
153 }
154
155
156 static BOOL
157 CreateTreeView(PMAIN_WND_INFO Info)
158 {
159 Info->hTreeView = CreateWindowEx(WS_EX_CLIENTEDGE,
160 WC_TREEVIEW,
161 NULL,
162 WS_CHILD | WS_VISIBLE | WS_BORDER | TVS_HASLINES |
163 TVS_HASBUTTONS | TVS_SHOWSELALWAYS | TVS_LINESATROOT,
164 0, 0, 0, 0,
165 Info->hMainWnd,
166 (HMENU)IDC_TREEVIEW,
167 hInstance,
168 NULL);
169 if (Info->hTreeView == NULL)
170 {
171 DisplayString(_T("Could not create TreeView."));
172 return FALSE;
173 }
174
175 return TRUE;
176 }
177
178 static BOOL
179 CreateStatusBar(PMAIN_WND_INFO Info)
180 {
181 INT StatWidths[] = {110, -1}; /* widths of status bar */
182
183 Info->hStatus = CreateWindowEx(0,
184 STATUSCLASSNAME,
185 NULL,
186 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
187 0, 0, 0, 0,
188 Info->hMainWnd,
189 (HMENU)IDC_STATUSBAR,
190 hInstance,
191 NULL);
192 if(Info->hStatus == NULL)
193 return FALSE;
194
195
196 SendMessage(Info->hStatus,
197 SB_SETPARTS,
198 sizeof(StatWidths) / sizeof(INT),
199 (LPARAM)StatWidths);
200
201 return TRUE;
202 }
203
204
205 static DWORD WINAPI
206 DeviceEnumThread(LPVOID lpParameter)
207 {
208 PMAIN_WND_INFO Info;
209 HTREEITEM hRoot;
210
211 Info = (PMAIN_WND_INFO)lpParameter;
212
213 if (Info->hTreeView)
214 FreeDeviceStrings(Info->hTreeView);
215
216 hRoot = InitTreeView(Info->hTreeView);
217 if (hRoot)
218 {
219 switch (Info->Display)
220 {
221 case DevicesByType:
222 ListDevicesByType(Info->hTreeView, hRoot, Info->bShowHidden);
223 break;
224
225 case DevicesByConnection:
226 ListDevicesByConnection(Info->hTreeView, hRoot, Info->bShowHidden);
227 break;
228
229 default:
230 break;
231 }
232 return 0;
233 }
234
235 return -1;
236 }
237
238
239 static VOID
240 UpdateViewMenu(PMAIN_WND_INFO Info)
241 {
242 UINT id = IDC_DEVBYTYPE;
243 HMENU hMenu;
244
245 hMenu = GetMenu(Info->hMainWnd);
246
247 switch (Info->Display)
248 {
249 case DevicesByType:
250 id = IDC_DEVBYTYPE;
251 break;
252 case DevicesByConnection:
253 id = IDC_DEVBYCONN;
254 break;
255 case RessourcesByType:
256 id = IDC_RESBYTYPE;
257 break;
258 case RessourcesByConnection:
259 id = IDC_RESBYCONN;
260 break;
261 }
262
263 CheckMenuRadioItem(hMenu,
264 IDC_DEVBYTYPE,
265 IDC_RESBYCONN,
266 id,
267 MF_BYCOMMAND);
268
269 CheckMenuItem(hMenu,
270 IDC_SHOWHIDDEN,
271 MF_BYCOMMAND | (Info->bShowHidden) ? MF_CHECKED : MF_UNCHECKED);
272 }
273
274
275 static BOOL
276 InitMainWnd(PMAIN_WND_INFO Info)
277 {
278 HANDLE DevEnumThread;
279 HMENU hMenu;
280
281 if (!pCreateToolbar(Info))
282 DisplayString(_T("error creating toolbar"));
283
284 if (!CreateTreeView(Info))
285 {
286 DisplayString(_T("error creating list view"));
287 return FALSE;
288 }
289
290 if (!CreateStatusBar(Info))
291 DisplayString(_T("error creating status bar"));
292
293 UpdateViewMenu(Info);
294
295 /* make 'properties' bold */
296 hMenu = GetMenu(Info->hMainWnd);
297 hMenu = GetSubMenu(hMenu, 1);
298 SetMenuDefaultItem(hMenu, IDC_PROP, FALSE);
299
300 /* Create Popup Menu */
301 Info->hShortcutMenu = LoadMenu(hInstance,
302 MAKEINTRESOURCE(IDR_POPUP));
303 Info->hShortcutMenu = GetSubMenu(Info->hShortcutMenu,
304 0);
305 SetMenuDefaultItem(Info->hShortcutMenu, IDC_PROP, FALSE);
306
307 /* create seperate thread to emum devices */
308 DevEnumThread = CreateThread(NULL,
309 0,
310 DeviceEnumThread,
311 Info,
312 0,
313 NULL);
314 if (!DevEnumThread)
315 {
316 DisplayString(_T("Failed to enumerate devices"));
317 return FALSE;
318 }
319
320 CloseHandle(DevEnumThread);
321 return TRUE;
322 }
323
324
325 static VOID
326 OnContext(PMAIN_WND_INFO Info,
327 LPARAM lParam)
328 {
329 HTREEITEM hSelected;
330 POINT pt;
331 RECT rc;
332
333 INT xPos = GET_X_LPARAM(lParam);
334 INT yPos = GET_Y_LPARAM(lParam);
335
336 hSelected = TreeView_GetSelection(Info->hTreeView);
337
338 if (TreeView_GetItemRect(Info->hTreeView,
339 hSelected,
340 &rc,
341 TRUE))
342 {
343 if (GetCursorPos(&pt) &&
344 ScreenToClient(Info->hTreeView, &pt) &&
345 PtInRect(&rc, pt))
346 {
347 TrackPopupMenuEx(Info->hShortcutMenu,
348 TPM_RIGHTBUTTON,
349 xPos,
350 yPos,
351 Info->hMainWnd,
352 NULL);
353 }
354 }
355 }
356
357
358 static LRESULT
359 OnNotify(PMAIN_WND_INFO Info,
360 LPARAM lParam)
361 {
362 LPNMHDR pnmhdr = (LPNMHDR)lParam;
363 LRESULT ret = 0;
364
365 switch (pnmhdr->code)
366 {
367 case TVN_SELCHANGED:
368 {
369 LPNM_TREEVIEW pnmtv = (LPNM_TREEVIEW)lParam;
370
371 if (Info->Display == DevicesByType)
372 {
373 if (!TreeView_GetChild(Info->hTreeView,
374 pnmtv->itemNew.hItem))
375 {
376 SendMessage(Info->hTool,
377 TB_SETSTATE,
378 IDC_PROP,
379 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
380
381 EnableMenuItem(GetMenu(Info->hMainWnd), IDC_PROP, MF_ENABLED);
382 EnableMenuItem(Info->hShortcutMenu, IDC_PROP, MF_ENABLED);
383 }
384 else
385 {
386 SendMessage(Info->hTool,
387 TB_SETSTATE,
388 IDC_PROP,
389 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
390
391 EnableMenuItem(GetMenu(Info->hMainWnd), IDC_PROP, MF_GRAYED);
392 EnableMenuItem(Info->hShortcutMenu, IDC_PROP, MF_GRAYED);
393 }
394 }
395 else if (Info->Display == DevicesByConnection)
396 {
397 if (pnmtv->itemNew.hItem == TreeView_GetRoot(Info->hTreeView))
398 {
399 SendMessage(Info->hTool,
400 TB_SETSTATE,
401 IDC_PROP,
402 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
403
404 EnableMenuItem(GetMenu(Info->hMainWnd), IDC_PROP, MF_GRAYED);
405 EnableMenuItem(Info->hShortcutMenu, IDC_PROP, MF_GRAYED);
406 }
407 else
408 {
409 SendMessage(Info->hTool,
410 TB_SETSTATE,
411 IDC_PROP,
412 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
413
414 EnableMenuItem(GetMenu(Info->hMainWnd), IDC_PROP, MF_ENABLED);
415 EnableMenuItem(Info->hShortcutMenu, IDC_PROP, MF_ENABLED);
416 }
417 }
418 }
419 break;
420
421 case NM_DBLCLK:
422 {
423 HTREEITEM hSelected = TreeView_GetSelection(Info->hTreeView);
424 TV_HITTESTINFO HitTest;
425
426 if (Info->Display == DevicesByType)
427 {
428 if (!TreeView_GetChild(Info->hTreeView,
429 hSelected))
430 {
431 if (GetCursorPos(&HitTest.pt) &&
432 ScreenToClient(Info->hTreeView, &HitTest.pt))
433 {
434 if (TreeView_HitTest(Info->hTreeView, &HitTest))
435 {
436 if (HitTest.hItem == hSelected)
437 {
438 OpenPropSheet(Info->hTreeView,
439 hSelected);
440 ret = TRUE;
441 }
442 }
443 }
444 }
445 }
446 else if (Info->Display == DevicesByConnection)
447 {
448 if (hSelected != TreeView_GetRoot(Info->hTreeView))
449 {
450 if (GetCursorPos(&HitTest.pt) &&
451 ScreenToClient(Info->hTreeView, &HitTest.pt))
452 {
453 if (TreeView_HitTest(Info->hTreeView, &HitTest))
454 {
455 if (HitTest.hItem == hSelected)
456 {
457 OpenPropSheet(Info->hTreeView,
458 hSelected);
459 ret = TRUE;
460 }
461 }
462 }
463 }
464 }
465 }
466 break;
467
468 case NM_RCLICK:
469 {
470 TV_HITTESTINFO HitTest;
471
472 if (GetCursorPos(&HitTest.pt) &&
473 ScreenToClient(Info->hTreeView, &HitTest.pt))
474 {
475 if (TreeView_HitTest(Info->hTreeView, &HitTest))
476 (void)TreeView_SelectItem(Info->hTreeView, HitTest.hItem);
477 }
478 }
479 break;
480
481 case TTN_GETDISPINFO:
482 {
483 LPTOOLTIPTEXT lpttt;
484 UINT idButton;
485
486 lpttt = (LPTOOLTIPTEXT)lParam;
487
488 idButton = (UINT)lpttt->hdr.idFrom;
489 switch (idButton)
490 {
491 case IDC_PROP:
492 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP);
493 break;
494
495 case IDC_REFRESH:
496 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
497 break;
498
499 case IDC_PROGHELP:
500 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_HELP);
501 break;
502
503 case IDC_EXIT:
504 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXIT);
505 break;
506 }
507 }
508 break;
509 }
510
511 return ret;
512 }
513
514
515 static VOID
516 OnRefresh(PMAIN_WND_INFO Info)
517 {
518 HANDLE DevEnumThread;
519
520 SendMessage(Info->hTool,
521 TB_SETSTATE,
522 IDC_PROP,
523 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
524
525 EnableMenuItem(GetMenu(Info->hMainWnd), IDC_PROP, MF_GRAYED);
526 EnableMenuItem(Info->hShortcutMenu, IDC_PROP, MF_GRAYED);
527
528 /* create seperate thread to emum devices */
529 DevEnumThread = CreateThread(NULL,
530 0,
531 DeviceEnumThread,
532 Info,
533 0,
534 NULL);
535 if (!DevEnumThread)
536 {
537 DisplayString(_T("Failed to enumerate devices"));
538 return;
539 }
540
541 CloseHandle(DevEnumThread);
542 }
543
544
545 static VOID
546 MainWndCommand(PMAIN_WND_INFO Info,
547 WORD CmdId,
548 HWND hControl)
549 {
550 UNREFERENCED_PARAMETER(hControl);
551
552 switch (CmdId)
553 {
554 case IDC_PROP:
555 {
556 HTREEITEM hSelected = TreeView_GetSelection(Info->hTreeView);
557 OpenPropSheet(Info->hTreeView,
558 hSelected);
559 }
560 break;
561
562 case IDC_REFRESH:
563 {
564 OnRefresh(Info);
565 }
566 break;
567
568 case IDC_PROGHELP:
569 {
570 DisplayString(_T("Help is not yet implemented\n"));
571 SetFocus(Info->hTreeView);
572 }
573 break;
574
575 case IDC_EXIT:
576 {
577 PostMessage(Info->hMainWnd,
578 WM_CLOSE,
579 0,
580 0);
581 }
582 break;
583
584 case IDC_ABOUT:
585 {
586 DialogBox(hInstance,
587 MAKEINTRESOURCE(IDD_ABOUTBOX),
588 Info->hMainWnd,
589 AboutDialogProc);
590
591 SetFocus(Info->hTreeView);
592 }
593 break;
594
595 case IDC_DEVBYTYPE:
596 {
597 Info->Display = DevicesByType;
598 UpdateViewMenu(Info);
599 OnRefresh(Info);
600 }
601 break;
602
603 case IDC_DEVBYCONN:
604 {
605 Info->Display = DevicesByConnection;
606 UpdateViewMenu(Info);
607 OnRefresh(Info);
608 }
609 break;
610
611 case IDC_SHOWHIDDEN:
612 {
613 Info->bShowHidden = !Info->bShowHidden;
614 UpdateViewMenu(Info);
615 OnRefresh(Info);
616 }
617 break;
618 }
619 }
620
621
622 static VOID CALLBACK
623 MainWndResize(PMAIN_WND_INFO Info,
624 WORD cx,
625 WORD cy)
626 {
627 RECT rcClient, rcTool, rcStatus;
628 int lvHeight, iToolHeight, iStatusHeight;
629
630 /* Size toolbar and get height */
631 SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
632 GetWindowRect(Info->hTool, &rcTool);
633 iToolHeight = rcTool.bottom - rcTool.top;
634
635 /* Size status bar and get height */
636 SendMessage(Info->hStatus, WM_SIZE, 0, 0);
637 GetWindowRect(Info->hStatus, &rcStatus);
638 iStatusHeight = rcStatus.bottom - rcStatus.top;
639
640 /* Calculate remaining height and size list view */
641 GetClientRect(Info->hMainWnd, &rcClient);
642 lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
643 SetWindowPos(Info->hTreeView,
644 NULL,
645 0,
646 iToolHeight,
647 rcClient.right,
648 lvHeight,
649 SWP_NOZORDER);
650 }
651
652
653 static LRESULT CALLBACK
654 MainWndProc(HWND hwnd,
655 UINT msg,
656 WPARAM wParam,
657 LPARAM lParam)
658 {
659 PMAIN_WND_INFO Info;
660 LRESULT Ret = 0;
661
662 /* Get the window context */
663 Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
664 GWLP_USERDATA);
665 if (Info == NULL && msg != WM_CREATE)
666 {
667 goto HandleDefaultMessage;
668 }
669
670 switch(msg)
671 {
672 case WM_CREATE:
673 {
674 Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
675
676 /* Initialize the main window context */
677 Info->hMainWnd = hwnd;
678
679 SetWindowLongPtr(hwnd,
680 GWLP_USERDATA,
681 (LONG_PTR)Info);
682
683 if (!InitMainWnd(Info))
684 SendMessage(hwnd, WM_CLOSE, 0, 0);
685
686 /* Show the window */
687 ShowWindow(hwnd,
688 Info->nCmdShow);
689 }
690 break;
691
692 case WM_SETFOCUS:
693 {
694 if (Info->hTreeView != NULL)
695 SetFocus(Info->hTreeView);
696 }
697 break;
698
699 case WM_SIZE:
700 {
701 MainWndResize(Info,
702 LOWORD(lParam),
703 HIWORD(lParam));
704 }
705 break;
706
707 case WM_NOTIFY:
708 {
709 Ret = OnNotify(Info, lParam);
710 }
711 break;
712
713 case WM_CONTEXTMENU:
714 {
715 OnContext(Info, lParam);
716 }
717 break;
718
719 case WM_COMMAND:
720 {
721 MainWndCommand(Info,
722 LOWORD(wParam),
723 (HWND)lParam);
724 goto HandleDefaultMessage;
725 }
726
727 case WM_MENUSELECT:
728 {
729 if (Info->hStatus != NULL)
730 {
731 if (!MainWndMenuHint(Info,
732 LOWORD(wParam),
733 MainMenuHintTable,
734 sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
735 IDS_HINT_BLANK))
736 {
737 MainWndMenuHint(Info,
738 LOWORD(wParam),
739 SystemMenuHintTable,
740 sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
741 IDS_HINT_BLANK);
742 }
743 }
744 }
745 break;
746
747 case WM_ENTERMENULOOP:
748 {
749 Info->InMenuLoop = TRUE;
750 UpdateMainStatusBar(Info);
751 break;
752 }
753
754 case WM_EXITMENULOOP:
755 {
756 Info->InMenuLoop = FALSE;
757 UpdateMainStatusBar(Info);
758 break;
759 }
760
761 case WM_CLOSE:
762 {
763 FreeDeviceStrings(Info->hTreeView);
764 DestroyMenu(Info->hShortcutMenu);
765 DestroyWindow(hwnd);
766 }
767 break;
768
769 case WM_DESTROY:
770 {
771 HeapFree(ProcessHeap,
772 0,
773 Info);
774 SetWindowLongPtr(hwnd,
775 GWLP_USERDATA,
776 0);
777
778 /* Break the message queue loop */
779 PostQuitMessage(0);
780 }
781 break;
782
783 default:
784 {
785 HandleDefaultMessage:
786
787 Ret = DefWindowProc(hwnd,
788 msg,
789 wParam,
790 lParam);
791 }
792 break;
793 }
794 return Ret;
795 }
796
797
798
799 HWND
800 CreateMainWindow(LPCTSTR lpCaption,
801 int nCmdShow)
802 {
803 PMAIN_WND_INFO Info;
804 HWND hMainWnd = NULL;
805
806 Info = (PMAIN_WND_INFO)HeapAlloc(ProcessHeap,
807 HEAP_ZERO_MEMORY,
808 sizeof(MAIN_WND_INFO));
809
810 if (Info != NULL)
811 {
812 Info->nCmdShow = nCmdShow;
813 Info->Display = DevicesByType;
814 Info->bShowHidden = TRUE;
815
816 hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
817 szMainWndClass,
818 lpCaption,
819 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
820 CW_USEDEFAULT,
821 CW_USEDEFAULT,
822 600,
823 450,
824 NULL,
825 NULL,
826 hInstance,
827 Info);
828 if (hMainWnd == NULL)
829 {
830 GetError();
831 HeapFree(ProcessHeap,
832 0,
833 Info);
834 }
835 }
836
837 return hMainWnd;
838 }
839
840 BOOL
841 InitMainWindowImpl(VOID)
842 {
843 WNDCLASSEX wc = {0};
844
845 wc.cbSize = sizeof(WNDCLASSEX);
846 wc.lpfnWndProc = MainWndProc;
847 wc.hInstance = hInstance;
848 wc.hIcon = LoadIcon(hInstance,
849 MAKEINTRESOURCE(IDI_MAIN_ICON));
850 wc.hCursor = LoadCursor(NULL,
851 IDC_ARROW);
852 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
853 wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
854 wc.lpszClassName = szMainWndClass;
855 wc.hIconSm = (HICON)LoadImage(hInstance,
856 MAKEINTRESOURCE(IDI_MAIN_ICON),
857 IMAGE_ICON,
858 16,
859 16,
860 LR_SHARED);
861
862 return RegisterClassEx(&wc) != (ATOM)0;
863 }
864
865
866 VOID
867 UninitMainWindowImpl(VOID)
868 {
869 UnregisterClass(szMainWndClass,
870 hInstance);
871 }
872
873