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