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
26 static const MENU_HINT MainMenuHintTable
[] =
29 { IDC_EXIT
, IDS_HINT_EXIT
},
32 { IDC_PROPERTIES
, IDS_HINT_PROPERTIES
},
33 { IDC_SCAN_HARDWARE
, IDS_HINT_SCAN
},
34 { IDC_ENABLE_DRV
, IDS_HINT_ENABLE
},
35 { IDC_DISABLE_DRV
, IDS_HINT_DISABLE
},
36 { IDC_UPDATE_DRV
, IDS_HINT_UPDATE
},
37 { IDC_UNINSTALL_DRV
, IDS_HINT_UNINSTALL
},
38 { IDC_ADD_HARDWARE
, IDS_HINT_ADD
},
42 { IDC_DEVBYTYPE
, IDS_HINT_DEV_BY_TYPE
},
43 { IDC_DEVBYCONN
, IDS_HINT_DEV_BY_CONN
},
44 { IDC_RESBYTYPE
, IDS_HINT_RES_BY_TYPE
},
45 { IDC_RESBYCONN
, IDS_HINT_RES_BY_TYPE
},
46 { IDC_SHOWHIDDEN
, IDS_HINT_SHOW_HIDDEN
},
48 { IDC_ABOUT
, IDS_HINT_ABOUT
}
54 static const MENU_HINT SystemMenuHintTable
[] =
56 {SC_RESTORE
, IDS_HINT_SYS_RESTORE
},
57 {SC_MOVE
, IDS_HINT_SYS_MOVE
},
58 {SC_SIZE
, IDS_HINT_SYS_SIZE
},
59 {SC_MINIMIZE
, IDS_HINT_SYS_MINIMIZE
},
60 {SC_MAXIMIZE
, IDS_HINT_SYS_MAXIMIZE
},
61 {SC_CLOSE
, IDS_HINT_SYS_CLOSE
},
64 static TBBUTTON TbButtons
[] =
66 { BTN_PROPERTIES
, IDC_PROPERTIES
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
67 { BTN_SCAN_HARDWARE
, IDC_SCAN_HARDWARE
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
68 { 2, IDC_STATIC
, TBSTATE_ENABLED
, BTNS_SEP
, 0, 0 },
69 { BTN_ENABLE_DRV
, IDC_ENABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
70 { BTN_DISABLE_DRV
, IDC_DISABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
71 { BTN_UPDATE_DRV
, IDC_UPDATE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
72 { BTN_UNINSTALL_DRV
, IDC_UNINSTALL_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 }
76 /* PUBLIC METHODS **********************************************/
78 CMainWindow::CMainWindow(void) :
79 m_ToolbarhImageList(NULL
),
85 m_szMainWndClass
= L
"DevMgmtWndClass";
88 CMainWindow::~CMainWindow(void)
90 // Destroy any previous list
91 if (m_ToolbarhImageList
) ImageList_Destroy(m_ToolbarhImageList
);
95 CMainWindow::Initialize(LPCTSTR lpCaption
,
98 CAtlStringW szCaption
;
101 // Store the show window value
102 m_CmdShow
= nCmdShow
;
104 // Setup the window class struct
105 wc
.cbSize
= sizeof(WNDCLASSEXW
);
106 wc
.lpfnWndProc
= MainWndProc
;
107 wc
.hInstance
= g_hInstance
;
108 wc
.hIcon
= LoadIcon(g_hInstance
, MAKEINTRESOURCEW(IDI_MAIN_ICON
));
109 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
110 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
111 wc
.lpszMenuName
= MAKEINTRESOURCEW(IDR_MAINMENU
);
112 wc
.lpszClassName
= m_szMainWndClass
;
113 wc
.hIconSm
= (HICON
)LoadImage(g_hInstance
,
114 MAKEINTRESOURCE(IDI_MAIN_ICON
),
120 // Register the window
121 if (RegisterClassExW(&wc
))
123 // Create the main window and store the object pointer
124 m_hMainWnd
= CreateWindowExW(WS_EX_WINDOWEDGE
,
127 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
138 // Return creation result
139 return !!(m_hMainWnd
);
143 CMainWindow::Uninitialize()
145 // Unregister the window class
146 UnregisterClassW(m_szMainWndClass
, g_hInstance
);
154 // Pump the message queue
155 while (GetMessageW(&Msg
, NULL
, 0, 0 ) != 0)
157 TranslateMessage(&Msg
);
158 DispatchMessageW(&Msg
);
165 /* PRIVATE METHODS **********************************************/
168 CMainWindow::MainWndMenuHint(WORD CmdId
,
169 const MENU_HINT
*HintArray
,
174 const MENU_HINT
*LastHint
;
175 UINT HintId
= DefHintId
;
177 LastHint
= HintArray
+ HintsCount
;
178 while (HintArray
!= LastHint
)
180 if (HintArray
->CmdId
== CmdId
)
182 HintId
= HintArray
->HintId
;
189 StatusBarLoadString(m_hStatusBar
,
198 CMainWindow::UpdateStatusBar(
202 SendMessageW(m_hStatusBar
,
209 CMainWindow::RefreshView(ViewType Type
)
214 // Refreshed the cached view
215 m_DeviceView
->Refresh(Type
, FALSE
, TRUE
, NULL
);
217 // Get the menu item id
220 case DevicesByType
: CheckId
= IDC_DEVBYTYPE
; break;
221 case DevicesByConnection
: CheckId
= IDC_DEVBYCONN
; break;
222 case ResourcesByType
: CheckId
= IDC_RESBYTYPE
; break;
223 case ResourcesByConnection
: CheckId
= IDC_RESBYCONN
; break;
224 default: ATLASSERT(FALSE
); break;
227 // Set the new check item
228 bSuccess
= CheckMenuRadioItem(m_hMenu
,
238 CMainWindow::CreateToolBar()
240 TBADDBITMAP TbAddBitmap
;
243 DWORD dwStyles
= WS_CHILDWINDOW
| TBSTYLE_FLAT
| TBSTYLE_WRAPABLE
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
;
244 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
246 // Create the toolbar window
247 m_hToolBar
= CreateWindowExW(dwExStyles
,
256 if (m_hToolBar
== NULL
) return FALSE
;
258 // Don't show clipped buttons
259 SendMessageW(m_hToolBar
,
262 TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
264 SendMessageW(m_hToolBar
, TB_SETBITMAPSIZE
, 0, MAKELONG(16, 16));
266 // Set the struct size, the toobar needs this...
267 SendMessageW(m_hToolBar
,
272 TbAddBitmap
.hInst
= g_hInstance
;
273 TbAddBitmap
.nID
= IDB_TOOLBAR
;
274 Index
= SendMessageW(m_hToolBar
, TB_ADDBITMAP
, _countof(TbButtons
), (LPARAM
)&TbAddBitmap
);
276 SendMessageW(m_hToolBar
, TB_ADDBUTTONSW
, _countof(TbButtons
), (LPARAM
)TbButtons
);
277 SendMessageW(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
281 ShowWindow(m_hToolBar
, SW_SHOW
);
288 CMainWindow::CreateStatusBar()
290 int StatWidths
[] = {110, -1}; // widths of status bar
293 // Create the status bar
294 m_hStatusBar
= CreateWindowExW(0,
297 WS_CHILD
| WS_VISIBLE
| SBARS_SIZEGRIP
,
300 (HMENU
)IDC_STATUSBAR
,
306 bRet
= (SendMessageW(m_hStatusBar
,
308 sizeof(StatWidths
) / sizeof(int),
309 (LPARAM
)StatWidths
) != 0);
315 void CMainWindow::UpdateToolbar()
319 CNode
*Node
= m_DeviceView
->GetSelectedNode();
322 if (Node
->HasProperties())
324 State
= TBSTATE_ENABLED
;
328 State
= TBSTATE_HIDDEN
;
330 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_PROPERTIES
, MAKELPARAM(State
, 0));
331 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UPDATE_DRV
, MAKELPARAM(State
, 0)); //hack
332 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UNINSTALL_DRV
, MAKELPARAM(State
, 0)); // hack
336 // enable driver button
337 if (Node
->GetNodeType() == DeviceNode
&&
338 dynamic_cast<CDeviceNode
*>(Node
)->IsDisabled())
340 State
= TBSTATE_ENABLED
;
344 State
= TBSTATE_HIDDEN
;
346 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_ENABLE_DRV
, MAKELPARAM(State
, 0));
348 // disable driver button
349 if (Node
->GetNodeType() == DeviceNode
&&
350 dynamic_cast<CDeviceNode
*>(Node
)->CanDisable() &&
351 !dynamic_cast<CDeviceNode
*>(Node
)->IsDisabled())
353 State
= TBSTATE_ENABLED
;
357 State
= TBSTATE_HIDDEN
;
359 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_DISABLE_DRV
, MAKELPARAM(State
, 0));
370 CMainWindow::StatusBarLoadString(IN HWND hStatusBar
,
372 IN HINSTANCE hInstance
,
375 CAtlStringW szMessage
;
379 if (szMessage
.LoadStringW(hInstance
, uID
))
381 // Show the string on the status bar
382 bRet
= (SendMessageW(hStatusBar
,
385 (LPARAM
)szMessage
.GetBuffer()) != 0);
392 CMainWindow::OnCreate(HWND hwnd
)
399 // Store a handle to the main menu
400 m_hMenu
= GetMenu(m_hMainWnd
);
402 // Create the toolbar and statusbar
403 if (CreateToolBar() && CreateStatusBar())
405 // Create the device view object
406 m_DeviceView
= new CDeviceView(m_hMainWnd
);
407 if (m_DeviceView
->Initialize())
409 // Do the initial scan
410 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
415 // Display the window according to the user request
416 ShowWindow(hwnd
, m_CmdShow
);
425 CMainWindow::OnSize()
427 RECT rcClient
, rcTool
, rcStatus
;
428 INT lvHeight
, iToolHeight
, iStatusHeight
;
430 // Autosize the toolbar
431 SendMessage(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
433 // Get the toolbar rect and save the height
434 GetWindowRect(m_hToolBar
, &rcTool
);
435 iToolHeight
= rcTool
.bottom
- rcTool
.top
;
437 // Resize the status bar
438 SendMessage(m_hStatusBar
, WM_SIZE
, 0, 0);
440 // Get the statusbar rect and save the height
441 GetWindowRect(m_hStatusBar
, &rcStatus
);
442 iStatusHeight
= rcStatus
.bottom
- rcStatus
.top
;
444 // Get the full client rect
445 GetClientRect(m_hMainWnd
, &rcClient
);
447 // Calculate the remaining height for the treeview
448 lvHeight
= rcClient
.bottom
- iToolHeight
- iStatusHeight
;
450 // Resize the device view
451 m_DeviceView
->OnSize(0,
460 CMainWindow::OnNotify(LPARAM lParam
)
462 LPNMHDR NmHdr
= (LPNMHDR
)lParam
;
475 m_DeviceView
->DisplayPropertySheet();
481 Ret
= m_DeviceView
->OnRightClick(NmHdr
);
487 m_DeviceView
->DisplayPropertySheet();
491 case TTN_GETDISPINFO
:
493 LPTOOLTIPTEXT lpttt
= (LPTOOLTIPTEXT
)lParam
;
495 UINT_PTR idButton
= lpttt
->hdr
.idFrom
;
499 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_PROPERTIES
);
501 case IDC_SCAN_HARDWARE
:
502 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_SCAN
);
505 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_ENABLE
);
507 case IDC_DISABLE_DRV
:
508 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_DISABLE
);
511 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_UPDATE
);
513 case IDC_UNINSTALL_DRV
:
514 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_UNINSTALL
);
525 CMainWindow::OnContext(LPARAM lParam
)
527 return m_DeviceView
->OnContextMenu(lParam
);
531 CMainWindow::OnCommand(WPARAM wParam
,
538 Msg
= LOWORD(wParam
);
543 case IDC_SCAN_HARDWARE
:
545 case IDC_DISABLE_DRV
:
547 case IDC_UNINSTALL_DRV
:
548 case IDC_ADD_HARDWARE
:
550 m_DeviceView
->OnAction(Msg
);
556 // Create a popup menu with all the actions for the selected node
557 HMENU hMenu
= CreatePopupMenu();
558 m_DeviceView
->CreateActionMenu(hMenu
, true);
560 // Calculate where to put the menu
562 GetMenuItemRect(m_hMainWnd
, m_hMenu
, 1, &rc
);
563 LONG Height
= rc
.bottom
- rc
.top
;
566 TrackPopupMenuEx(hMenu
,
579 RefreshView(DevicesByType
);
585 RefreshView(DevicesByConnection
);
591 // Get the current state
592 UINT CurCheckState
= GetMenuState(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
);
593 if (CurCheckState
== MF_CHECKED
)
595 m_DeviceView
->SetHiddenDevices(false);
596 CheckMenuItem(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
| MF_UNCHECKED
);
598 else if (CurCheckState
== MF_UNCHECKED
)
600 m_DeviceView
->SetHiddenDevices(true);
601 CheckMenuItem(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
| MF_CHECKED
);
603 // Refresh the device view
604 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
614 MessageBoxW(m_hMainWnd
,
615 L
"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
617 MB_OK
| MB_APPLMODAL
);
619 // Set focus back to the treeview
620 m_DeviceView
->SetFocus();
626 // Post a close message to the window
627 PostMessageW(m_hMainWnd
,
635 // We didn't handle it
644 CMainWindow::OnDestroy()
646 // Uninitialize the device view
647 m_DeviceView
->Uninitialize();
653 // Clear the user data pointer
654 SetWindowLongPtr(m_hMainWnd
, GWLP_USERDATA
, 0);
656 // Break the message loop
663 CMainWindow::MainWndProc(HWND hwnd
,
671 // Get the object pointer from window context
672 This
= (CMainWindow
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
675 // Check that this isn't a create message
676 if (msg
!= WM_CREATE
)
678 // Don't handle null info pointer
679 goto HandleDefaultMessage
;
687 // Get the object pointer from the create param
688 This
= (CMainWindow
*)((LPCREATESTRUCT
)lParam
)->lpCreateParams
;
690 // Store the pointer in the window's global user data
691 SetWindowLongPtr(hwnd
, GWLP_USERDATA
, (LONG_PTR
)This
);
693 // Call the create handler
694 RetCode
= This
->OnCreate(hwnd
);
700 RetCode
= This
->OnSize();
706 RetCode
= This
->OnNotify(lParam
);
712 RetCode
= This
->OnContext(lParam
);
718 if (This
->m_hStatusBar
!= NULL
)
720 if (!This
->MainWndMenuHint(LOWORD(wParam
),
722 sizeof(MainMenuHintTable
) / sizeof(MainMenuHintTable
[0]),
725 This
->MainWndMenuHint(LOWORD(wParam
),
727 sizeof(SystemMenuHintTable
) / sizeof(SystemMenuHintTable
[0]),
737 // Handle the command message
738 RetCode
= This
->OnCommand(wParam
, lParam
);
741 // Hand it off to the default message handler
742 goto HandleDefaultMessage
;
747 case WM_ENTERMENULOOP
:
749 This
->UpdateStatusBar(true);
753 case WM_EXITMENULOOP
:
755 This
->UpdateStatusBar(false);
761 // Destroy the main window
769 // Call the destroy handler
770 RetCode
= This
->OnDestroy();
776 HandleDefaultMessage
:
777 RetCode
= DefWindowProc(hwnd
, msg
, wParam
, lParam
);
786 //////// MOVE ME ////////////////
788 HINSTANCE g_hInstance
= NULL
;
789 HANDLE ProcessHeap
= NULL
;
793 DeviceManager_ExecuteW(HWND
/*hWndParent*/,
795 LPCWSTR
/*lpMachineName*/,
798 CMainWindow MainWindow
;
799 INITCOMMONCONTROLSEX icex
;
800 CAtlStringW szAppName
;
803 // Store the global values
805 ProcessHeap
= GetProcessHeap();
807 // Initialize common controls
808 icex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
809 icex
.dwICC
= ICC_BAR_CLASSES
| ICC_COOL_CLASSES
;
810 InitCommonControlsEx(&icex
);
812 // Load the application name
813 if (szAppName
.LoadStringW(g_hInstance
, IDS_APPNAME
))
815 // Initialize the main window
816 if (MainWindow
.Initialize(szAppName
, nCmdShow
))
818 // Run the application
819 Ret
= MainWindow
.Run();
821 // Uninitialize the main window
822 MainWindow
.Uninitialize();