Sync with trunk r63192.
[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 separate 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_RETURN:
422 {
423 HTREEITEM hSelected = TreeView_GetSelection(Info->hTreeView);
424 if (Info->Display == DevicesByType)
425 {
426 OpenPropSheet(Info->hTreeView, hSelected);
427 }
428 else if (Info->Display == DevicesByConnection)
429 {
430 if (hSelected != TreeView_GetRoot(Info->hTreeView))
431 {
432 OpenPropSheet(Info->hTreeView, hSelected);
433 }
434 }
435 }
436 break;
437
438 case NM_DBLCLK:
439 {
440 HTREEITEM hSelected = TreeView_GetSelection(Info->hTreeView);
441 TV_HITTESTINFO HitTest;
442
443 if (Info->Display == DevicesByType)
444 {
445 if (!TreeView_GetChild(Info->hTreeView,
446 hSelected))
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 else if (Info->Display == DevicesByConnection)
464 {
465 if (hSelected != TreeView_GetRoot(Info->hTreeView))
466 {
467 if (GetCursorPos(&HitTest.pt) &&
468 ScreenToClient(Info->hTreeView, &HitTest.pt))
469 {
470 if (TreeView_HitTest(Info->hTreeView, &HitTest))
471 {
472 if (HitTest.hItem == hSelected)
473 {
474 OpenPropSheet(Info->hTreeView,
475 hSelected);
476 ret = TRUE;
477 }
478 }
479 }
480 }
481 }
482 }
483 break;
484
485 case NM_RCLICK:
486 {
487 TV_HITTESTINFO HitTest;
488
489 if (GetCursorPos(&HitTest.pt) &&
490 ScreenToClient(Info->hTreeView, &HitTest.pt))
491 {
492 if (TreeView_HitTest(Info->hTreeView, &HitTest))
493 (void)TreeView_SelectItem(Info->hTreeView, HitTest.hItem);
494 }
495 }
496 break;
497
498 case TTN_GETDISPINFO:
499 {
500 LPTOOLTIPTEXT lpttt;
501 UINT idButton;
502
503 lpttt = (LPTOOLTIPTEXT)lParam;
504
505 idButton = (UINT)lpttt->hdr.idFrom;
506 switch (idButton)
507 {
508 case IDC_PROP:
509 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP);
510 break;
511
512 case IDC_REFRESH:
513 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
514 break;
515
516 case IDC_PROGHELP:
517 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_HELP);
518 break;
519
520 case IDC_EXIT:
521 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXIT);
522 break;
523 }
524 }
525 break;
526 }
527
528 return ret;
529 }
530
531
532 static VOID
533 OnRefresh(PMAIN_WND_INFO Info)
534 {
535 HANDLE DevEnumThread;
536
537 SendMessage(Info->hTool,
538 TB_SETSTATE,
539 IDC_PROP,
540 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
541
542 EnableMenuItem(GetMenu(Info->hMainWnd), IDC_PROP, MF_GRAYED);
543 EnableMenuItem(Info->hShortcutMenu, IDC_PROP, MF_GRAYED);
544
545 /* create seperate thread to emum devices */
546 DevEnumThread = CreateThread(NULL,
547 0,
548 DeviceEnumThread,
549 Info,
550 0,
551 NULL);
552 if (!DevEnumThread)
553 {
554 DisplayString(_T("Failed to enumerate devices"));
555 return;
556 }
557
558 CloseHandle(DevEnumThread);
559 }
560
561
562 static VOID
563 MainWndCommand(PMAIN_WND_INFO Info,
564 WORD CmdId,
565 HWND hControl)
566 {
567 UNREFERENCED_PARAMETER(hControl);
568
569 switch (CmdId)
570 {
571 case IDC_PROP:
572 {
573 HTREEITEM hSelected = TreeView_GetSelection(Info->hTreeView);
574 OpenPropSheet(Info->hTreeView,
575 hSelected);
576 }
577 break;
578
579 case IDC_REFRESH:
580 {
581 OnRefresh(Info);
582 }
583 break;
584
585 case IDC_PROGHELP:
586 {
587 DisplayString(_T("Help is not yet implemented\n"));
588 SetFocus(Info->hTreeView);
589 }
590 break;
591
592 case IDC_EXIT:
593 {
594 PostMessage(Info->hMainWnd,
595 WM_CLOSE,
596 0,
597 0);
598 }
599 break;
600
601 case IDC_ABOUT:
602 {
603 DialogBox(hInstance,
604 MAKEINTRESOURCE(IDD_ABOUTBOX),
605 Info->hMainWnd,
606 AboutDialogProc);
607
608 SetFocus(Info->hTreeView);
609 }
610 break;
611
612 case IDC_DEVBYTYPE:
613 {
614 Info->Display = DevicesByType;
615 UpdateViewMenu(Info);
616 OnRefresh(Info);
617 }
618 break;
619
620 case IDC_DEVBYCONN:
621 {
622 Info->Display = DevicesByConnection;
623 UpdateViewMenu(Info);
624 OnRefresh(Info);
625 }
626 break;
627
628 case IDC_SHOWHIDDEN:
629 {
630 Info->bShowHidden = !Info->bShowHidden;
631 UpdateViewMenu(Info);
632 OnRefresh(Info);
633 }
634 break;
635 }
636 }
637
638
639 static VOID CALLBACK
640 MainWndResize(PMAIN_WND_INFO Info,
641 WORD cx,
642 WORD cy)
643 {
644 RECT rcClient, rcTool, rcStatus;
645 int lvHeight, iToolHeight, iStatusHeight;
646
647 /* Size toolbar and get height */
648 SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
649 GetWindowRect(Info->hTool, &rcTool);
650 iToolHeight = rcTool.bottom - rcTool.top;
651
652 /* Size status bar and get height */
653 SendMessage(Info->hStatus, WM_SIZE, 0, 0);
654 GetWindowRect(Info->hStatus, &rcStatus);
655 iStatusHeight = rcStatus.bottom - rcStatus.top;
656
657 /* Calculate remaining height and size list view */
658 GetClientRect(Info->hMainWnd, &rcClient);
659 lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
660 SetWindowPos(Info->hTreeView,
661 NULL,
662 0,
663 iToolHeight,
664 rcClient.right,
665 lvHeight,
666 SWP_NOZORDER);
667 }
668
669
670 static LRESULT CALLBACK
671 MainWndProc(HWND hwnd,
672 UINT msg,
673 WPARAM wParam,
674 LPARAM lParam)
675 {
676 PMAIN_WND_INFO Info;
677 LRESULT Ret = 0;
678
679 /* Get the window context */
680 Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
681 GWLP_USERDATA);
682 if (Info == NULL && msg != WM_CREATE)
683 {
684 goto HandleDefaultMessage;
685 }
686
687 switch(msg)
688 {
689 case WM_CREATE:
690 {
691 Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
692
693 /* Initialize the main window context */
694 Info->hMainWnd = hwnd;
695
696 SetWindowLongPtr(hwnd,
697 GWLP_USERDATA,
698 (LONG_PTR)Info);
699
700 if (!InitMainWnd(Info))
701 SendMessage(hwnd, WM_CLOSE, 0, 0);
702
703 /* Show the window */
704 ShowWindow(hwnd,
705 Info->nCmdShow);
706 }
707 break;
708
709 case WM_SETFOCUS:
710 {
711 if (Info->hTreeView != NULL)
712 SetFocus(Info->hTreeView);
713 }
714 break;
715
716 case WM_SIZE:
717 {
718 MainWndResize(Info,
719 LOWORD(lParam),
720 HIWORD(lParam));
721 }
722 break;
723
724 case WM_NOTIFY:
725 {
726 Ret = OnNotify(Info, lParam);
727 }
728 break;
729
730 case WM_CONTEXTMENU:
731 {
732 OnContext(Info, lParam);
733 }
734 break;
735
736 case WM_COMMAND:
737 {
738 MainWndCommand(Info,
739 LOWORD(wParam),
740 (HWND)lParam);
741 goto HandleDefaultMessage;
742 }
743
744 case WM_MENUSELECT:
745 {
746 if (Info->hStatus != NULL)
747 {
748 if (!MainWndMenuHint(Info,
749 LOWORD(wParam),
750 MainMenuHintTable,
751 sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
752 IDS_HINT_BLANK))
753 {
754 MainWndMenuHint(Info,
755 LOWORD(wParam),
756 SystemMenuHintTable,
757 sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
758 IDS_HINT_BLANK);
759 }
760 }
761 }
762 break;
763
764 case WM_ENTERMENULOOP:
765 {
766 Info->InMenuLoop = TRUE;
767 UpdateMainStatusBar(Info);
768 break;
769 }
770
771 case WM_EXITMENULOOP:
772 {
773 Info->InMenuLoop = FALSE;
774 UpdateMainStatusBar(Info);
775 break;
776 }
777
778 case WM_CLOSE:
779 {
780 FreeDeviceStrings(Info->hTreeView);
781 DestroyMenu(Info->hShortcutMenu);
782 DestroyWindow(hwnd);
783 }
784 break;
785
786 case WM_DESTROY:
787 {
788 HeapFree(ProcessHeap,
789 0,
790 Info);
791 SetWindowLongPtr(hwnd,
792 GWLP_USERDATA,
793 0);
794
795 /* Break the message queue loop */
796 PostQuitMessage(0);
797 }
798 break;
799
800 default:
801 {
802 HandleDefaultMessage:
803
804 Ret = DefWindowProc(hwnd,
805 msg,
806 wParam,
807 lParam);
808 }
809 break;
810 }
811 return Ret;
812 }
813
814
815
816 HWND
817 CreateMainWindow(LPCTSTR lpCaption,
818 int nCmdShow)
819 {
820 PMAIN_WND_INFO Info;
821 HWND hMainWnd = NULL;
822
823 Info = (PMAIN_WND_INFO)HeapAlloc(ProcessHeap,
824 HEAP_ZERO_MEMORY,
825 sizeof(MAIN_WND_INFO));
826
827 if (Info != NULL)
828 {
829 Info->nCmdShow = nCmdShow;
830 Info->Display = DevicesByType;
831 Info->bShowHidden = TRUE;
832
833 hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
834 szMainWndClass,
835 lpCaption,
836 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
837 CW_USEDEFAULT,
838 CW_USEDEFAULT,
839 600,
840 450,
841 NULL,
842 NULL,
843 hInstance,
844 Info);
845 if (hMainWnd == NULL)
846 {
847 GetError();
848 HeapFree(ProcessHeap,
849 0,
850 Info);
851 }
852 }
853
854 return hMainWnd;
855 }
856
857 BOOL
858 InitMainWindowImpl(VOID)
859 {
860 WNDCLASSEX wc = {0};
861
862 wc.cbSize = sizeof(WNDCLASSEX);
863 wc.lpfnWndProc = MainWndProc;
864 wc.hInstance = hInstance;
865 wc.hIcon = LoadIcon(hInstance,
866 MAKEINTRESOURCE(IDI_MAIN_ICON));
867 wc.hCursor = LoadCursor(NULL,
868 IDC_ARROW);
869 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
870 wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
871 wc.lpszClassName = szMainWndClass;
872 wc.hIconSm = (HICON)LoadImage(hInstance,
873 MAKEINTRESOURCE(IDI_MAIN_ICON),
874 IMAGE_ICON,
875 16,
876 16,
877 LR_SHARED);
878
879 return RegisterClassEx(&wc) != (ATOM)0;
880 }
881
882
883 VOID
884 UninitMainWindowImpl(VOID)
885 {
886 UnregisterClass(szMainWndClass,
887 hInstance);
888 }
889
890