[DEVMGR]
[reactos.git] / reactos / dll / win32 / devmgr_new / devmgmt / MainWindow.cpp
1 /*
2 * PROJECT: ReactOS Device Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/devmgr/devmgmt/MainWindow.cpp
5 * PURPOSE: Implements the main container window for the device view
6 * COPYRIGHT: Copyright 2014 - 2015 Ged Murphy <gedmurphy@reactos.org>
7 */
8
9
10 #include "precomp.h"
11 #include "devmgmt.h"
12 #include "MainWindow.h"
13
14
15 /* DATA *****************************************************/
16
17 #define BTN_PROPERTIES 0
18 #define BTN_SCAN_HARDWARE 1
19 #define BTN_ENABLE_DRV 2
20 #define BTN_DISABLE_DRV 3
21 #define BTN_UPDATE_DRV 4
22 #define BTN_UNINSTALL_DRV 5
23
24 HINSTANCE g_hThisInstance = NULL;
25 HINSTANCE g_hParentInstance = NULL;
26
27 // menu hints
28 static const MENU_HINT MainMenuHintTable[] =
29 {
30 // File Menu
31 { IDC_EXIT, IDS_HINT_EXIT },
32
33 // Action Menu
34 { IDC_PROPERTIES, IDS_HINT_PROPERTIES },
35 { IDC_SCAN_HARDWARE, IDS_HINT_SCAN },
36 { IDC_ENABLE_DRV, IDS_HINT_ENABLE },
37 { IDC_DISABLE_DRV, IDS_HINT_DISABLE },
38 { IDC_UPDATE_DRV, IDS_HINT_UPDATE },
39 { IDC_UNINSTALL_DRV, IDS_HINT_UNINSTALL },
40 { IDC_ADD_HARDWARE, IDS_HINT_ADD },
41
42
43 // View Menu
44 { IDC_DEVBYTYPE, IDS_HINT_DEV_BY_TYPE},
45 { IDC_DEVBYCONN, IDS_HINT_DEV_BY_CONN},
46 { IDC_RESBYTYPE, IDS_HINT_RES_BY_TYPE},
47 { IDC_RESBYCONN, IDS_HINT_RES_BY_TYPE},
48 { IDC_SHOWHIDDEN, IDS_HINT_SHOW_HIDDEN },
49
50 { IDC_ABOUT, IDS_HINT_ABOUT }
51
52 };
53
54
55 // system menu hints
56 static const MENU_HINT SystemMenuHintTable[] =
57 {
58 {SC_RESTORE, IDS_HINT_SYS_RESTORE},
59 {SC_MOVE, IDS_HINT_SYS_MOVE},
60 {SC_SIZE, IDS_HINT_SYS_SIZE},
61 {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
62 {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
63 {SC_CLOSE, IDS_HINT_SYS_CLOSE}
64 };
65
66 static TBBUTTON TbButtons[] =
67 {
68 { BTN_PROPERTIES, IDC_PROPERTIES, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 },
69 { BTN_SCAN_HARDWARE, IDC_SCAN_HARDWARE, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 },
70 { 2, IDC_STATIC, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0 },
71 { BTN_ENABLE_DRV, IDC_ENABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 },
72 { BTN_DISABLE_DRV, IDC_DISABLE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 },
73 { BTN_UPDATE_DRV, IDC_UPDATE_DRV, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 },
74 { BTN_UNINSTALL_DRV, IDC_UNINSTALL_DRV, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0 }
75 };
76
77
78 /* PUBLIC METHODS **********************************************/
79
80 CDeviceManager::CDeviceManager(void) :
81 m_hMainWnd(NULL),
82 m_hStatusBar(NULL),
83 m_hToolBar(NULL),
84 m_CmdShow(0)
85 {
86 m_szMainWndClass = L"DevMgmtWndClass";
87 }
88
89 CDeviceManager::~CDeviceManager(void)
90 {
91 }
92
93
94 bool
95 CDeviceManager::Create(_In_ HWND /*hWndParent*/,
96 _In_ HINSTANCE hInst,
97 _In_opt_z_ LPCWSTR /*lpMachineName*/,
98 _In_ int nCmdShow)
99 {
100 CDeviceManager MainWindow;
101 INITCOMMONCONTROLSEX icex;
102 CAtlStringW szAppName;
103 int Ret = 1;
104
105 // Store the instances
106 g_hParentInstance = hInst;
107 g_hThisInstance = GetModuleHandleW(L"devmgr.dll");
108
109 // Initialize common controls
110 icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
111 icex.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES;
112 InitCommonControlsEx(&icex);
113
114 // Load the application name
115 if (szAppName.LoadStringW(g_hThisInstance, IDS_APPNAME))
116 {
117 // Initialize the main window
118 if (MainWindow.Initialize(szAppName, nCmdShow))
119 {
120 // Run the application
121 Ret = MainWindow.Run();
122
123 // Uninitialize the main window
124 MainWindow.Uninitialize();
125 }
126 }
127
128 return (Ret == 0);
129 }
130
131
132
133 /* PRIVATE METHODS **********************************************/
134
135 bool
136 CDeviceManager::Initialize(_In_z_ LPCTSTR lpCaption,
137 _In_ int nCmdShow)
138 {
139 CAtlStringW szCaption;
140 WNDCLASSEXW wc = {0};
141
142 // Store the show window value
143 m_CmdShow = nCmdShow;
144
145 // Setup the window class struct
146 wc.cbSize = sizeof(WNDCLASSEXW);
147 wc.lpfnWndProc = MainWndProc;
148 wc.hInstance = g_hThisInstance;
149 wc.hIcon = LoadIcon(g_hThisInstance, MAKEINTRESOURCEW(IDI_MAIN_ICON));
150 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
151 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
152 wc.lpszMenuName = MAKEINTRESOURCEW(IDR_MAINMENU);
153 wc.lpszClassName = m_szMainWndClass;
154 wc.hIconSm = (HICON)LoadImage(g_hThisInstance,
155 MAKEINTRESOURCE(IDI_MAIN_ICON),
156 IMAGE_ICON,
157 16,
158 16,
159 LR_SHARED);
160
161 // Register the window
162 if (RegisterClassExW(&wc))
163 {
164 // Create the main window and store the object pointer
165 m_hMainWnd = CreateWindowExW(WS_EX_WINDOWEDGE,
166 m_szMainWndClass,
167 lpCaption,
168 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
169 CW_USEDEFAULT,
170 CW_USEDEFAULT,
171 550,
172 500,
173 NULL,
174 NULL,
175 g_hThisInstance,
176 this);
177 }
178
179 // Return creation result
180 return !!(m_hMainWnd);
181 }
182
183 void
184 CDeviceManager::Uninitialize(void)
185 {
186 // Unregister the window class
187 UnregisterClassW(m_szMainWndClass, g_hThisInstance);
188 }
189
190 int
191 CDeviceManager::Run(void)
192 {
193 MSG Msg;
194
195 // Pump the message queue
196 while (GetMessageW(&Msg, NULL, 0, 0 ) != 0)
197 {
198 TranslateMessage(&Msg);
199 DispatchMessageW(&Msg);
200 }
201
202 return 0;
203 }
204
205 bool
206 CDeviceManager::MainWndMenuHint(_In_ WORD CmdId,
207 _In_ const MENU_HINT *HintArray,
208 _In_ DWORD HintsCount,
209 _In_ UINT DefHintId)
210 {
211 bool Found = false;
212 const MENU_HINT *LastHint;
213 UINT HintId = DefHintId;
214
215 LastHint = HintArray + HintsCount;
216 while (HintArray != LastHint)
217 {
218 if (HintArray->CmdId == CmdId)
219 {
220 HintId = HintArray->HintId;
221 Found = true;
222 break;
223 }
224 HintArray++;
225 }
226
227 StatusBarLoadString(m_hStatusBar,
228 SB_SIMPLEID,
229 g_hThisInstance,
230 HintId);
231
232 return Found;
233 }
234
235 void
236 CDeviceManager::UpdateStatusBar(_In_ bool InMenuLoop)
237 {
238 SendMessageW(m_hStatusBar,
239 SB_SIMPLE,
240 (WPARAM)InMenuLoop,
241 0);
242 }
243
244 bool
245 CDeviceManager::RefreshView(_In_ ViewType Type)
246 {
247 UINT CheckId = 0;
248
249 // Refreshed the cached view
250 m_DeviceView->Refresh(Type, FALSE, TRUE, NULL);
251
252 // Get the menu item id
253 switch (Type)
254 {
255 case DevicesByType: CheckId = IDC_DEVBYTYPE; break;
256 case DevicesByConnection: CheckId = IDC_DEVBYCONN; break;
257 case ResourcesByType: CheckId = IDC_RESBYTYPE; break;
258 case ResourcesByConnection: CheckId = IDC_RESBYCONN; break;
259 default: ATLASSERT(FALSE); break;
260 }
261
262 // Set the new check item
263 CheckMenuRadioItem(m_hMenu,
264 IDC_DEVBYTYPE,
265 IDC_RESBYCONN,
266 CheckId,
267 MF_BYCOMMAND);
268
269 return true;
270 }
271
272 bool
273 CDeviceManager::CreateToolBar(void)
274 {
275 TBADDBITMAP TbAddBitmap;
276
277 DWORD dwStyles = WS_CHILDWINDOW | TBSTYLE_FLAT | TBSTYLE_WRAPABLE | TBSTYLE_TOOLTIPS | CCS_NODIVIDER;
278 DWORD dwExStyles = WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
279
280 // Create the toolbar window
281 m_hToolBar = CreateWindowExW(dwExStyles,
282 TOOLBARCLASSNAME,
283 NULL,
284 dwStyles,
285 0, 0, 0, 0,
286 m_hMainWnd,
287 (HMENU)IDC_TOOLBAR,
288 g_hThisInstance,
289 NULL);
290 if (m_hToolBar == NULL) return FALSE;
291
292 // Don't show clipped buttons
293 SendMessageW(m_hToolBar,
294 TB_SETEXTENDEDSTYLE,
295 0,
296 TBSTYLE_EX_HIDECLIPPEDBUTTONS);
297
298 SendMessageW(m_hToolBar, TB_SETBITMAPSIZE, 0, MAKELONG(16, 16));
299
300 // Set the struct size, the toobar needs this...
301 SendMessageW(m_hToolBar,
302 TB_BUTTONSTRUCTSIZE,
303 sizeof(TBBUTTON),
304 0);
305
306 TbAddBitmap.hInst = g_hThisInstance;
307 TbAddBitmap.nID = IDB_TOOLBAR;
308 SendMessageW(m_hToolBar, TB_ADDBITMAP, _countof(TbButtons), (LPARAM)&TbAddBitmap);
309
310 SendMessageW(m_hToolBar, TB_ADDBUTTONSW, _countof(TbButtons), (LPARAM)TbButtons);
311 SendMessageW(m_hToolBar, TB_AUTOSIZE, 0, 0);
312
313 if (TRUE)
314 {
315 ShowWindow(m_hToolBar, SW_SHOW);
316 }
317
318 return TRUE;
319 }
320
321 bool
322 CDeviceManager::CreateStatusBar(void)
323 {
324 int StatWidths[] = {110, -1}; // widths of status bar
325 bool bRet = FALSE;
326
327 // Create the status bar
328 m_hStatusBar = CreateWindowExW(0,
329 STATUSCLASSNAME,
330 NULL,
331 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
332 0, 0, 0, 0,
333 m_hMainWnd,
334 (HMENU)IDC_STATUSBAR,
335 g_hThisInstance,
336 NULL);
337 if (m_hStatusBar)
338 {
339 // Set the width
340 bRet = (SendMessageW(m_hStatusBar,
341 SB_SETPARTS,
342 sizeof(StatWidths) / sizeof(int),
343 (LPARAM)StatWidths) != 0);
344 }
345
346 return bRet;
347 }
348
349 void CDeviceManager::UpdateToolbar()
350 {
351 WORD State;
352
353 CNode *Node = m_DeviceView->GetSelectedNode();
354
355 // properties button
356 if (Node->HasProperties())
357 {
358 State = TBSTATE_ENABLED;
359 }
360 else
361 {
362 State = TBSTATE_HIDDEN;
363 }
364 SendMessageW(m_hToolBar, TB_SETSTATE, IDC_PROPERTIES, MAKELPARAM(State, 0));
365 SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UPDATE_DRV, MAKELPARAM(State, 0)); //hack
366 SendMessageW(m_hToolBar, TB_SETSTATE, IDC_UNINSTALL_DRV, MAKELPARAM(State, 0)); // hack
367
368
369
370 // enable driver button
371 if (Node->GetNodeType() == DeviceNode &&
372 dynamic_cast<CDeviceNode *>(Node)->IsDisabled())
373 {
374 State = TBSTATE_ENABLED;
375 }
376 else
377 {
378 State = TBSTATE_HIDDEN;
379 }
380 SendMessageW(m_hToolBar, TB_SETSTATE, IDC_ENABLE_DRV, MAKELPARAM(State, 0));
381
382 // disable driver button
383 if (Node->GetNodeType() == DeviceNode &&
384 dynamic_cast<CDeviceNode *>(Node)->CanDisable() &&
385 !dynamic_cast<CDeviceNode *>(Node)->IsDisabled())
386 {
387 State = TBSTATE_ENABLED;
388 }
389 else
390 {
391 State = TBSTATE_HIDDEN;
392 }
393 SendMessageW(m_hToolBar, TB_SETSTATE, IDC_DISABLE_DRV, MAKELPARAM(State, 0));
394
395
396
397
398
399 }
400
401
402
403 bool
404 CDeviceManager::StatusBarLoadString(_In_ HWND hStatusBar,
405 _In_ INT PartId,
406 _In_ HINSTANCE hInstance,
407 _In_ UINT uID)
408 {
409 CAtlStringW szMessage;
410 bool bRet = false;
411
412 // Load the string
413 if (szMessage.LoadStringW(hInstance, uID))
414 {
415 // Show the string on the status bar
416 bRet = (SendMessageW(hStatusBar,
417 SB_SETTEXT,
418 (WPARAM)PartId,
419 (LPARAM)szMessage.GetBuffer()) != 0);
420 }
421
422 return bRet;
423 }
424
425 LRESULT
426 CDeviceManager::OnCreate(_In_ HWND hwnd)
427 {
428 LRESULT RetCode;
429
430 RetCode = -1;
431 m_hMainWnd = hwnd;
432
433 // Store a handle to the main menu
434 m_hMenu = GetMenu(m_hMainWnd);
435
436 // Create the toolbar and statusbar
437 if (CreateToolBar() && CreateStatusBar())
438 {
439 // Create the device view object
440 m_DeviceView = new CDeviceView(m_hMainWnd);
441 if (m_DeviceView->Initialize())
442 {
443 // Do the initial scan
444 m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
445 true,
446 true,
447 NULL);
448
449 // Display the window according to the user request
450 ShowWindow(hwnd, m_CmdShow);
451 RetCode = 0;
452 }
453 }
454
455 return RetCode;
456 }
457
458 LRESULT
459 CDeviceManager::OnSize(void)
460 {
461 RECT rcClient, rcTool, rcStatus;
462 INT lvHeight, iToolHeight, iStatusHeight;
463
464 // Autosize the toolbar
465 SendMessage(m_hToolBar, TB_AUTOSIZE, 0, 0);
466
467 // Get the toolbar rect and save the height
468 GetWindowRect(m_hToolBar, &rcTool);
469 iToolHeight = rcTool.bottom - rcTool.top;
470
471 // Resize the status bar
472 SendMessage(m_hStatusBar, WM_SIZE, 0, 0);
473
474 // Get the statusbar rect and save the height
475 GetWindowRect(m_hStatusBar, &rcStatus);
476 iStatusHeight = rcStatus.bottom - rcStatus.top;
477
478 // Get the full client rect
479 GetClientRect(m_hMainWnd, &rcClient);
480
481 // Calculate the remaining height for the treeview
482 lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
483
484 // Resize the device view
485 m_DeviceView->OnSize(0,
486 iToolHeight,
487 rcClient.right,
488 lvHeight);
489
490 return 0;
491 }
492
493 LRESULT
494 CDeviceManager::OnNotify(_In_ LPARAM lParam)
495 {
496 LPNMHDR NmHdr = (LPNMHDR)lParam;
497 LRESULT Ret = 0;
498
499 switch (NmHdr->code)
500 {
501 case TVN_SELCHANGED:
502 {
503 UpdateToolbar();
504 break;
505 }
506
507 case NM_DBLCLK:
508 {
509 m_DeviceView->DisplayPropertySheet();
510 break;
511 }
512
513 case NM_RCLICK:
514 {
515 Ret = m_DeviceView->OnRightClick(NmHdr);
516 break;
517 }
518
519 case NM_RETURN:
520 {
521 m_DeviceView->DisplayPropertySheet();
522 break;
523 }
524
525 case TTN_GETDISPINFO:
526 {
527 LPTOOLTIPTEXT lpttt = (LPTOOLTIPTEXT)lParam;
528 lpttt->hinst = g_hThisInstance;
529
530 UINT_PTR idButton = lpttt->hdr.idFrom;
531 switch (idButton)
532 {
533 case IDC_PROPERTIES:
534 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_PROPERTIES);
535 break;
536 case IDC_SCAN_HARDWARE:
537 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_SCAN);
538 break;
539 case IDC_ENABLE_DRV:
540 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_ENABLE);
541 break;
542 case IDC_DISABLE_DRV:
543 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_DISABLE);
544 break;
545 case IDC_UPDATE_DRV:
546 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE);
547 break;
548 case IDC_UNINSTALL_DRV:
549 lpttt->lpszText = MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL);
550 break;
551 }
552 idButton = idButton;
553 break;
554 }
555 }
556
557 return Ret;
558 }
559
560 LRESULT
561 CDeviceManager::OnContext(_In_ LPARAM lParam)
562 {
563 return m_DeviceView->OnContextMenu(lParam);
564 }
565
566 LRESULT
567 CDeviceManager::OnCommand(_In_ WPARAM wParam,
568 _In_ LPARAM /*lParam*/)
569 {
570 LRESULT RetCode = 0;
571 WORD Msg;
572
573 // Get the message
574 Msg = LOWORD(wParam);
575
576 switch (Msg)
577 {
578 case IDC_PROPERTIES:
579 case IDC_SCAN_HARDWARE:
580 case IDC_ENABLE_DRV:
581 case IDC_DISABLE_DRV:
582 case IDC_UPDATE_DRV:
583 case IDC_UNINSTALL_DRV:
584 case IDC_ADD_HARDWARE:
585 {
586 m_DeviceView->OnAction(Msg);
587 break;
588 }
589
590 case IDC_ACTIONMENU:
591 {
592 // Create a popup menu with all the actions for the selected node
593 HMENU hMenu = CreatePopupMenu();
594 m_DeviceView->CreateActionMenu(hMenu, true);
595
596 // Calculate where to put the menu
597 RECT rc;
598 GetMenuItemRect(m_hMainWnd, m_hMenu, 1, &rc);
599 LONG Height = rc.bottom - rc.top;
600
601 // Display the menu
602 TrackPopupMenuEx(hMenu,
603 TPM_RIGHTBUTTON,
604 rc.left,
605 rc.top + Height,
606 m_hMainWnd,
607 NULL);
608
609 DestroyMenu(hMenu);
610 break;
611 }
612
613 case IDC_DEVBYTYPE:
614 {
615 RefreshView(DevicesByType);
616 break;
617 }
618
619 case IDC_DEVBYCONN:
620 {
621 RefreshView(DevicesByConnection);
622 break;
623 }
624
625 case IDC_SHOWHIDDEN:
626 {
627 // Get the current state
628 UINT CurCheckState = GetMenuState(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND);
629 if (CurCheckState == MF_CHECKED)
630 {
631 m_DeviceView->SetHiddenDevices(false);
632 CheckMenuItem(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND | MF_UNCHECKED);
633 }
634 else if (CurCheckState == MF_UNCHECKED)
635 {
636 m_DeviceView->SetHiddenDevices(true);
637 CheckMenuItem(m_hMenu, IDC_SHOWHIDDEN, MF_BYCOMMAND | MF_CHECKED);
638 }
639 // Refresh the device view
640 m_DeviceView->Refresh(m_DeviceView->GetCurrentView(),
641 false,
642 true,
643 NULL);
644 break;
645 }
646
647 case IDC_ABOUT:
648 {
649 // Apportion blame
650 MessageBoxW(m_hMainWnd,
651 L"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
652 L"About",
653 MB_OK | MB_APPLMODAL);
654
655 // Set focus back to the treeview
656 m_DeviceView->SetFocus();
657 break;
658 }
659
660 case IDC_EXIT:
661 {
662 // Post a close message to the window
663 PostMessageW(m_hMainWnd,
664 WM_CLOSE,
665 0,
666 0);
667 break;
668 }
669
670 default:
671 // We didn't handle it
672 RetCode = -1;
673 break;
674 }
675
676 return RetCode;
677 }
678
679 LRESULT
680 CDeviceManager::OnDestroy(void)
681 {
682 // Uninitialize the device view
683 m_DeviceView->Uninitialize();
684
685 // Kill the object
686 delete m_DeviceView;
687 m_DeviceView = NULL;
688
689 // Clear the user data pointer
690 SetWindowLongPtr(m_hMainWnd, GWLP_USERDATA, 0);
691
692 // Break the message loop
693 PostQuitMessage(0);
694
695 return 0;
696 }
697
698 LRESULT CALLBACK
699 CDeviceManager::MainWndProc(_In_ HWND hwnd,
700 _In_ UINT msg,
701 _In_ WPARAM wParam,
702 _In_ LPARAM lParam)
703 {
704 CDeviceManager *This;
705 LRESULT RetCode = 0;
706
707 // Get the object pointer from window context
708 This = (CDeviceManager *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
709 if (This == NULL)
710 {
711 // Check that this isn't a create message
712 if (msg != WM_CREATE)
713 {
714 // Don't handle null info pointer
715 goto HandleDefaultMessage;
716 }
717 }
718
719 switch(msg)
720 {
721 case WM_CREATE:
722 {
723 // Get the object pointer from the create param
724 This = (CDeviceManager *)((LPCREATESTRUCT)lParam)->lpCreateParams;
725
726 // Store the pointer in the window's global user data
727 SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)This);
728
729 // Call the create handler
730 RetCode = This->OnCreate(hwnd);
731 break;
732 }
733
734 case WM_SIZE:
735 {
736 RetCode = This->OnSize();
737 break;
738 }
739
740 case WM_NOTIFY:
741 {
742 RetCode = This->OnNotify(lParam);
743 break;
744 }
745
746 case WM_CONTEXTMENU:
747 {
748 RetCode = This->OnContext(lParam);
749 break;
750 }
751
752 case WM_MENUSELECT:
753 {
754 if (This->m_hStatusBar != NULL)
755 {
756 if (!This->MainWndMenuHint(LOWORD(wParam),
757 MainMenuHintTable,
758 sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
759 IDS_HINT_BLANK))
760 {
761 This->MainWndMenuHint(LOWORD(wParam),
762 SystemMenuHintTable,
763 sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
764 IDS_HINT_BLANK);
765 }
766 }
767
768 break;
769 }
770
771 case WM_COMMAND:
772 {
773 // Handle the command message
774 RetCode = This->OnCommand(wParam, lParam);
775 if (RetCode == -1)
776 {
777 // Hand it off to the default message handler
778 goto HandleDefaultMessage;
779 }
780 break;
781 }
782
783 case WM_ENTERMENULOOP:
784 {
785 This->UpdateStatusBar(true);
786 break;
787 }
788
789 case WM_EXITMENULOOP:
790 {
791 This->UpdateStatusBar(false);
792 break;
793 }
794
795 case WM_CLOSE:
796 {
797 // Destroy the main window
798 DestroyWindow(hwnd);
799 break;
800 }
801
802
803 case WM_DESTROY:
804 {
805 // Call the destroy handler
806 RetCode = This->OnDestroy();
807 break;
808 }
809
810 default:
811 {
812 HandleDefaultMessage:
813 RetCode = DefWindowProc(hwnd, msg, wParam, lParam);
814 break;
815 }
816 }
817
818 return RetCode;
819 }