2 * PROJECT: ReactOS Device Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/devmgr/devmgr/MainWindow.cpp
5 * PURPOSE: Implements the main container window for the device view
6 * COPYRIGHT: Copyright 2014 - 2015 Ged Murphy <gedmurphy@reactos.org>
12 #include "MainWindow.h"
15 /* DATA *****************************************************/
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
24 HINSTANCE g_hThisInstance
= NULL
;
25 HINSTANCE g_hParentInstance
= NULL
;
28 static const MENU_HINT MainMenuHintTable
[] =
31 { IDC_EXIT
, IDS_HINT_EXIT
},
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
},
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
},
50 { IDC_ABOUT
, IDS_HINT_ABOUT
}
56 static const MENU_HINT SystemMenuHintTable
[] =
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
},
66 static TBBUTTON TbButtons
[] =
68 { BTN_PROPERTIES
, IDC_PROPERTIES
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
69 { BTN_SCAN_HARDWARE
, IDC_SCAN_HARDWARE
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
70 { 2, IDC_STATIC
, TBSTATE_ENABLED
, BTNS_SEP
, 0, 0 },
71 { BTN_ENABLE_DRV
, IDC_ENABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
72 { BTN_DISABLE_DRV
, IDC_DISABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
73 { BTN_UPDATE_DRV
, IDC_UPDATE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
74 { BTN_UNINSTALL_DRV
, IDC_UNINSTALL_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 }
78 /* PUBLIC METHODS **********************************************/
80 CDeviceManager::CDeviceManager(void) :
86 m_szMainWndClass
= L
"DevMgmtWndClass";
89 CDeviceManager::~CDeviceManager(void)
95 CDeviceManager::Create(_In_ HWND
/*hWndParent*/,
97 _In_opt_z_ LPCWSTR
/*lpMachineName*/,
100 CDeviceManager MainWindow
;
101 INITCOMMONCONTROLSEX icex
;
102 CAtlStringW szAppName
;
105 // Store the instances
106 g_hParentInstance
= hInst
;
107 g_hThisInstance
= GetModuleHandleW(L
"devmgr.dll");
109 // Initialize common controls
110 icex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
111 icex
.dwICC
= ICC_BAR_CLASSES
| ICC_COOL_CLASSES
;
112 InitCommonControlsEx(&icex
);
114 // Load the application name
115 if (szAppName
.LoadStringW(g_hThisInstance
, IDS_APPNAME
))
117 // Initialize the main window
118 if (MainWindow
.Initialize(szAppName
, nCmdShow
))
120 // Run the application
121 Ret
= MainWindow
.Run();
123 // Uninitialize the main window
124 MainWindow
.Uninitialize();
133 /* PRIVATE METHODS **********************************************/
136 CDeviceManager::Initialize(_In_z_ LPCTSTR lpCaption
,
139 CAtlStringW szCaption
;
140 WNDCLASSEXW wc
= {0};
142 // Store the show window value
143 m_CmdShow
= nCmdShow
;
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
),
161 // Register the window
162 if (RegisterClassExW(&wc
))
164 // Create the main window and store the object pointer
165 m_hMainWnd
= CreateWindowExW(WS_EX_WINDOWEDGE
,
168 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
179 // Return creation result
180 return !!(m_hMainWnd
);
184 CDeviceManager::Uninitialize(void)
186 // Unregister the window class
187 UnregisterClassW(m_szMainWndClass
, g_hThisInstance
);
191 CDeviceManager::Run(void)
195 // Pump the message queue
196 while (GetMessageW(&Msg
, NULL
, 0, 0 ) != 0)
198 TranslateMessage(&Msg
);
199 DispatchMessageW(&Msg
);
206 CDeviceManager::MainWndMenuHint(_In_ WORD CmdId
,
207 _In_
const MENU_HINT
*HintArray
,
208 _In_ DWORD HintsCount
,
212 const MENU_HINT
*LastHint
;
213 UINT HintId
= DefHintId
;
215 LastHint
= HintArray
+ HintsCount
;
216 while (HintArray
!= LastHint
)
218 if (HintArray
->CmdId
== CmdId
)
220 HintId
= HintArray
->HintId
;
227 StatusBarLoadString(m_hStatusBar
,
236 CDeviceManager::UpdateStatusBar(_In_
bool InMenuLoop
)
238 SendMessageW(m_hStatusBar
,
245 CDeviceManager::RefreshView(_In_ ViewType Type
)
250 // Refreshed the cached view
251 m_DeviceView
->Refresh(Type
, FALSE
, TRUE
, NULL
);
253 // Get the menu item id
256 case DevicesByType
: CheckId
= IDC_DEVBYTYPE
; break;
257 case DevicesByConnection
: CheckId
= IDC_DEVBYCONN
; break;
258 case ResourcesByType
: CheckId
= IDC_RESBYTYPE
; break;
259 case ResourcesByConnection
: CheckId
= IDC_RESBYCONN
; break;
260 default: ATLASSERT(FALSE
); break;
263 // Set the new check item
264 bSuccess
= CheckMenuRadioItem(m_hMenu
,
274 CDeviceManager::CreateToolBar(void)
276 TBADDBITMAP TbAddBitmap
;
279 DWORD dwStyles
= WS_CHILDWINDOW
| TBSTYLE_FLAT
| TBSTYLE_WRAPABLE
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
;
280 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
282 // Create the toolbar window
283 m_hToolBar
= CreateWindowExW(dwExStyles
,
292 if (m_hToolBar
== NULL
) return FALSE
;
294 // Don't show clipped buttons
295 SendMessageW(m_hToolBar
,
298 TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
300 SendMessageW(m_hToolBar
, TB_SETBITMAPSIZE
, 0, MAKELONG(16, 16));
302 // Set the struct size, the toobar needs this...
303 SendMessageW(m_hToolBar
,
308 TbAddBitmap
.hInst
= g_hThisInstance
;
309 TbAddBitmap
.nID
= IDB_TOOLBAR
;
310 Index
= SendMessageW(m_hToolBar
, TB_ADDBITMAP
, _countof(TbButtons
), (LPARAM
)&TbAddBitmap
);
312 SendMessageW(m_hToolBar
, TB_ADDBUTTONSW
, _countof(TbButtons
), (LPARAM
)TbButtons
);
313 SendMessageW(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
317 ShowWindow(m_hToolBar
, SW_SHOW
);
324 CDeviceManager::CreateStatusBar(void)
326 int StatWidths
[] = {110, -1}; // widths of status bar
329 // Create the status bar
330 m_hStatusBar
= CreateWindowExW(0,
333 WS_CHILD
| WS_VISIBLE
| SBARS_SIZEGRIP
,
336 (HMENU
)IDC_STATUSBAR
,
342 bRet
= (SendMessageW(m_hStatusBar
,
344 sizeof(StatWidths
) / sizeof(int),
345 (LPARAM
)StatWidths
) != 0);
351 void CDeviceManager::UpdateToolbar()
355 CNode
*Node
= m_DeviceView
->GetSelectedNode();
358 if (Node
->HasProperties())
360 State
= TBSTATE_ENABLED
;
364 State
= TBSTATE_HIDDEN
;
366 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_PROPERTIES
, MAKELPARAM(State
, 0));
367 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UPDATE_DRV
, MAKELPARAM(State
, 0)); //hack
368 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UNINSTALL_DRV
, MAKELPARAM(State
, 0)); // hack
372 // enable driver button
373 if (Node
->GetNodeType() == DeviceNode
&&
374 dynamic_cast<CDeviceNode
*>(Node
)->IsDisabled())
376 State
= TBSTATE_ENABLED
;
380 State
= TBSTATE_HIDDEN
;
382 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_ENABLE_DRV
, MAKELPARAM(State
, 0));
384 // disable driver button
385 if (Node
->GetNodeType() == DeviceNode
&&
386 dynamic_cast<CDeviceNode
*>(Node
)->CanDisable() &&
387 !dynamic_cast<CDeviceNode
*>(Node
)->IsDisabled())
389 State
= TBSTATE_ENABLED
;
393 State
= TBSTATE_HIDDEN
;
395 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_DISABLE_DRV
, MAKELPARAM(State
, 0));
406 CDeviceManager::StatusBarLoadString(_In_ HWND hStatusBar
,
408 _In_ HINSTANCE hInstance
,
411 CAtlStringW szMessage
;
415 if (szMessage
.LoadStringW(hInstance
, uID
))
417 // Show the string on the status bar
418 bRet
= (SendMessageW(hStatusBar
,
421 (LPARAM
)szMessage
.GetBuffer()) != 0);
428 CDeviceManager::OnCreate(_In_ HWND hwnd
)
435 // Store a handle to the main menu
436 m_hMenu
= GetMenu(m_hMainWnd
);
438 // Create the toolbar and statusbar
439 if (CreateToolBar() && CreateStatusBar())
441 // Create the device view object
442 m_DeviceView
= new CDeviceView(m_hMainWnd
);
443 if (m_DeviceView
->Initialize())
445 // Do the initial scan
446 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
451 // Display the window according to the user request
452 ShowWindow(hwnd
, m_CmdShow
);
461 CDeviceManager::OnSize(void)
463 RECT rcClient
, rcTool
, rcStatus
;
464 INT lvHeight
, iToolHeight
, iStatusHeight
;
466 // Autosize the toolbar
467 SendMessage(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
469 // Get the toolbar rect and save the height
470 GetWindowRect(m_hToolBar
, &rcTool
);
471 iToolHeight
= rcTool
.bottom
- rcTool
.top
;
473 // Resize the status bar
474 SendMessage(m_hStatusBar
, WM_SIZE
, 0, 0);
476 // Get the statusbar rect and save the height
477 GetWindowRect(m_hStatusBar
, &rcStatus
);
478 iStatusHeight
= rcStatus
.bottom
- rcStatus
.top
;
480 // Get the full client rect
481 GetClientRect(m_hMainWnd
, &rcClient
);
483 // Calculate the remaining height for the treeview
484 lvHeight
= rcClient
.bottom
- iToolHeight
- iStatusHeight
;
486 // Resize the device view
487 m_DeviceView
->OnSize(0,
496 CDeviceManager::OnNotify(_In_ LPARAM lParam
)
498 LPNMHDR NmHdr
= (LPNMHDR
)lParam
;
511 m_DeviceView
->DisplayPropertySheet();
517 Ret
= m_DeviceView
->OnRightClick(NmHdr
);
523 m_DeviceView
->DisplayPropertySheet();
527 case TTN_GETDISPINFO
:
529 LPTOOLTIPTEXT lpttt
= (LPTOOLTIPTEXT
)lParam
;
530 lpttt
->hinst
= g_hThisInstance
;
532 UINT_PTR idButton
= lpttt
->hdr
.idFrom
;
536 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_PROPERTIES
);
538 case IDC_SCAN_HARDWARE
:
539 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_SCAN
);
542 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_ENABLE
);
544 case IDC_DISABLE_DRV
:
545 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_DISABLE
);
548 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_UPDATE
);
550 case IDC_UNINSTALL_DRV
:
551 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_UNINSTALL
);
563 CDeviceManager::OnContext(_In_ LPARAM lParam
)
565 return m_DeviceView
->OnContextMenu(lParam
);
569 CDeviceManager::OnCommand(_In_ WPARAM wParam
,
570 _In_ LPARAM
/*lParam*/)
576 Msg
= LOWORD(wParam
);
581 case IDC_SCAN_HARDWARE
:
583 case IDC_DISABLE_DRV
:
585 case IDC_UNINSTALL_DRV
:
586 case IDC_ADD_HARDWARE
:
588 m_DeviceView
->OnAction(Msg
);
594 // Create a popup menu with all the actions for the selected node
595 HMENU hMenu
= CreatePopupMenu();
596 m_DeviceView
->CreateActionMenu(hMenu
, true);
598 // Calculate where to put the menu
600 GetMenuItemRect(m_hMainWnd
, m_hMenu
, 1, &rc
);
601 LONG Height
= rc
.bottom
- rc
.top
;
604 TrackPopupMenuEx(hMenu
,
617 RefreshView(DevicesByType
);
623 RefreshView(DevicesByConnection
);
629 // Get the current state
630 UINT CurCheckState
= GetMenuState(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
);
631 if (CurCheckState
== MF_CHECKED
)
633 m_DeviceView
->SetHiddenDevices(false);
634 CheckMenuItem(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
| MF_UNCHECKED
);
636 else if (CurCheckState
== MF_UNCHECKED
)
638 m_DeviceView
->SetHiddenDevices(true);
639 CheckMenuItem(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
| MF_CHECKED
);
641 // Refresh the device view
642 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
652 MessageBoxW(m_hMainWnd
,
653 L
"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
655 MB_OK
| MB_APPLMODAL
);
657 // Set focus back to the treeview
658 m_DeviceView
->SetFocus();
664 // Post a close message to the window
665 PostMessageW(m_hMainWnd
,
673 // We didn't handle it
682 CDeviceManager::OnDestroy(void)
684 // Uninitialize the device view
685 m_DeviceView
->Uninitialize();
691 // Clear the user data pointer
692 SetWindowLongPtr(m_hMainWnd
, GWLP_USERDATA
, 0);
694 // Break the message loop
701 CDeviceManager::MainWndProc(_In_ HWND hwnd
,
706 CDeviceManager
*This
;
709 // Get the object pointer from window context
710 This
= (CDeviceManager
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
713 // Check that this isn't a create message
714 if (msg
!= WM_CREATE
)
716 // Don't handle null info pointer
717 goto HandleDefaultMessage
;
725 // Get the object pointer from the create param
726 This
= (CDeviceManager
*)((LPCREATESTRUCT
)lParam
)->lpCreateParams
;
728 // Store the pointer in the window's global user data
729 SetWindowLongPtr(hwnd
, GWLP_USERDATA
, (LONG_PTR
)This
);
731 // Call the create handler
732 RetCode
= This
->OnCreate(hwnd
);
738 RetCode
= This
->OnSize();
744 RetCode
= This
->OnNotify(lParam
);
750 RetCode
= This
->OnContext(lParam
);
756 if (This
->m_hStatusBar
!= NULL
)
758 if (!This
->MainWndMenuHint(LOWORD(wParam
),
760 sizeof(MainMenuHintTable
) / sizeof(MainMenuHintTable
[0]),
763 This
->MainWndMenuHint(LOWORD(wParam
),
765 sizeof(SystemMenuHintTable
) / sizeof(SystemMenuHintTable
[0]),
775 // Handle the command message
776 RetCode
= This
->OnCommand(wParam
, lParam
);
779 // Hand it off to the default message handler
780 goto HandleDefaultMessage
;
785 case WM_ENTERMENULOOP
:
787 This
->UpdateStatusBar(true);
791 case WM_EXITMENULOOP
:
793 This
->UpdateStatusBar(false);
799 // Destroy the main window
807 // Call the destroy handler
808 RetCode
= This
->OnDestroy();
814 HandleDefaultMessage
:
815 RetCode
= DefWindowProc(hwnd
, msg
, wParam
, lParam
);
827 DeviceManager_ExecuteW(HWND hWndParent
,
829 LPCWSTR lpMachineName
,
832 CDeviceManager DevMgr
;
833 return DevMgr
.Create(hWndParent
, hInst
, lpMachineName
, nCmdShow
);