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
}
55 #define IDS_HINT_BLANK 20000
56 #define IDS_HINT_PROPERTIES 20001
57 #define IDS_HINT_SCAN 20002
58 #define IDS_HINT_ENABLE 20003
59 #define IDS_HINT_DISABLE 20004
60 #define IDS_HINT_UPDATE 20005
61 #define IDS_HINT_UNINSTALL 20006
62 #define IDS_HINT_ADD 20007
63 #define IDS_HINT_ABOUT 20008
64 #define IDS_HINT_EXIT 20009
67 static const MENU_HINT SystemMenuHintTable
[] =
69 {SC_RESTORE
, IDS_HINT_SYS_RESTORE
},
70 {SC_MOVE
, IDS_HINT_SYS_MOVE
},
71 {SC_SIZE
, IDS_HINT_SYS_SIZE
},
72 {SC_MINIMIZE
, IDS_HINT_SYS_MINIMIZE
},
73 {SC_MAXIMIZE
, IDS_HINT_SYS_MAXIMIZE
},
74 {SC_CLOSE
, IDS_HINT_SYS_CLOSE
},
77 static TBBUTTON TbButtons
[] =
79 { BTN_PROPERTIES
, IDC_PROPERTIES
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
80 { BTN_SCAN_HARDWARE
, IDC_SCAN_HARDWARE
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
81 { 2, IDC_STATIC
, TBSTATE_ENABLED
, BTNS_SEP
, 0, 0 },
82 { BTN_ENABLE_DRV
, IDC_ENABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
83 { BTN_DISABLE_DRV
, IDC_DISABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
84 { BTN_UPDATE_DRV
, IDC_UPDATE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
85 { BTN_UNINSTALL_DRV
, IDC_UNINSTALL_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 }
89 /* PUBLIC METHODS **********************************************/
91 CMainWindow::CMainWindow(void) :
92 m_ToolbarhImageList(NULL
),
98 m_szMainWndClass
= L
"DevMgmtWndClass";
101 CMainWindow::~CMainWindow(void)
103 // Destroy any previous list
104 if (m_ToolbarhImageList
) ImageList_Destroy(m_ToolbarhImageList
);
108 CMainWindow::Initialize(LPCTSTR lpCaption
,
111 CAtlStringW szCaption
;
112 WNDCLASSEXW wc
= {0};
114 // Store the show window value
115 m_CmdShow
= nCmdShow
;
117 // Setup the window class struct
118 wc
.cbSize
= sizeof(WNDCLASSEXW
);
119 wc
.lpfnWndProc
= MainWndProc
;
120 wc
.hInstance
= g_hInstance
;
121 wc
.hIcon
= LoadIcon(g_hInstance
, MAKEINTRESOURCEW(IDI_MAIN_ICON
));
122 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
123 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
124 wc
.lpszMenuName
= MAKEINTRESOURCEW(IDR_MAINMENU
);
125 wc
.lpszClassName
= m_szMainWndClass
;
126 wc
.hIconSm
= (HICON
)LoadImage(g_hInstance
,
127 MAKEINTRESOURCE(IDI_MAIN_ICON
),
133 // Register the window
134 if (RegisterClassExW(&wc
))
136 // Create the main window and store the object pointer
137 m_hMainWnd
= CreateWindowExW(WS_EX_WINDOWEDGE
,
140 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
151 // Return creation result
152 return !!(m_hMainWnd
);
156 CMainWindow::Uninitialize()
158 // Unregister the window class
159 UnregisterClassW(m_szMainWndClass
, g_hInstance
);
167 // Pump the message queue
168 while (GetMessageW(&Msg
, NULL
, 0, 0 ) != 0)
170 TranslateMessage(&Msg
);
171 DispatchMessageW(&Msg
);
178 /* PRIVATE METHODS **********************************************/
181 CMainWindow::MainWndMenuHint(WORD CmdId
,
182 const MENU_HINT
*HintArray
,
187 const MENU_HINT
*LastHint
;
188 UINT HintId
= DefHintId
;
190 LastHint
= HintArray
+ HintsCount
;
191 while (HintArray
!= LastHint
)
193 if (HintArray
->CmdId
== CmdId
)
195 HintId
= HintArray
->HintId
;
202 StatusBarLoadString(m_hStatusBar
,
211 CMainWindow::UpdateStatusBar(
215 SendMessageW(m_hStatusBar
,
222 CMainWindow::RefreshView(ViewType Type
)
227 // Refreshed the cached view
228 m_DeviceView
->Refresh(Type
, FALSE
, TRUE
);
230 // Get the menu item id
233 case DevicesByType
: CheckId
= IDC_DEVBYTYPE
; break;
234 case DevicesByConnection
: CheckId
= IDC_DEVBYCONN
; break;
235 case ResourcesByType
: CheckId
= IDC_RESBYTYPE
; break;
236 case ResourcesByConnection
: CheckId
= IDC_RESBYCONN
; break;
237 default: ATLASSERT(FALSE
); break;
240 // Set the new check item
241 bSuccess
= CheckMenuRadioItem(m_hMenu
,
251 CMainWindow::ScanForHardwareChanges()
253 // Refresh the cache and and display
254 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
261 CMainWindow::CreateToolBar()
263 TBADDBITMAP TbAddBitmap
;
266 DWORD dwStyles
= WS_CHILDWINDOW
| TBSTYLE_FLAT
| TBSTYLE_WRAPABLE
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
;
267 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
269 // Create the toolbar window
270 m_hToolBar
= CreateWindowExW(dwExStyles
,
279 if (m_hToolBar
== NULL
) return FALSE
;
281 // Don't show clipped buttons
282 SendMessageW(m_hToolBar
,
285 TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
287 SendMessageW(m_hToolBar
, TB_SETBITMAPSIZE
, 0, MAKELONG(16, 16));
289 // Set the struct size, the toobar needs this...
290 SendMessageW(m_hToolBar
,
295 TbAddBitmap
.hInst
= g_hInstance
;
296 TbAddBitmap
.nID
= IDB_TOOLBAR
;
297 Index
= SendMessageW(m_hToolBar
, TB_ADDBITMAP
, _countof(TbButtons
), (LPARAM
)&TbAddBitmap
);
299 SendMessageW(m_hToolBar
, TB_ADDBUTTONSW
, _countof(TbButtons
), (LPARAM
)TbButtons
);
300 SendMessageW(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
304 ShowWindow(m_hToolBar
, SW_SHOW
);
311 CMainWindow::CreateStatusBar()
313 int StatWidths
[] = {110, -1}; // widths of status bar
316 // Create the status bar
317 m_hStatusBar
= CreateWindowExW(0,
320 WS_CHILD
| WS_VISIBLE
| SBARS_SIZEGRIP
,
323 (HMENU
)IDC_STATUSBAR
,
329 bRet
= (SendMessageW(m_hStatusBar
,
331 sizeof(StatWidths
) / sizeof(int),
332 (LPARAM
)StatWidths
) != 0);
338 void CMainWindow::UpdateUiContext(_In_ LPTV_ITEMW TvItem
)
343 if (m_DeviceView
->HasProperties(TvItem
))
345 State
= TBSTATE_ENABLED
;
349 State
= TBSTATE_HIDDEN
;
351 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_PROPERTIES
, MAKELPARAM(State
, 0));
352 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UPDATE_DRV
, MAKELPARAM(State
, 0)); //hack
353 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UNINSTALL_DRV
, MAKELPARAM(State
, 0)); // hack
355 // enable driver button
356 if (m_DeviceView
->IsDisabled(TvItem
))
358 State
= TBSTATE_ENABLED
;
362 State
= TBSTATE_HIDDEN
;
364 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_ENABLE_DRV
, MAKELPARAM(State
, 0));
366 // disable driver button
367 if (m_DeviceView
->CanDisable(TvItem
) && !m_DeviceView
->IsDisabled(TvItem
))
369 State
= TBSTATE_ENABLED
;
373 State
= TBSTATE_HIDDEN
;
375 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_DISABLE_DRV
, MAKELPARAM(State
, 0));
386 CMainWindow::StatusBarLoadString(IN HWND hStatusBar
,
388 IN HINSTANCE hInstance
,
391 CAtlStringW szMessage
;
395 if (szMessage
.LoadStringW(hInstance
, uID
))
397 // Show the string on the status bar
398 bRet
= (SendMessageW(hStatusBar
,
401 (LPARAM
)szMessage
.GetBuffer()) != 0);
408 CMainWindow::OnCreate(HWND hwnd
)
415 // Store a handle to the main menu
416 m_hMenu
= GetMenu(m_hMainWnd
);
418 // Create the toolbar and statusbar
419 if (CreateToolBar() && CreateStatusBar())
421 // Create the device view object
422 m_DeviceView
= new CDeviceView(m_hMainWnd
);
423 if (m_DeviceView
->Initialize())
425 // Do the initial scan
426 ScanForHardwareChanges();
428 // Display the window according to the user request
429 ShowWindow(hwnd
, m_CmdShow
);
438 CMainWindow::OnSize()
440 RECT rcClient
, rcTool
, rcStatus
;
441 INT lvHeight
, iToolHeight
, iStatusHeight
;
443 // Autosize the toolbar
444 SendMessage(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
446 // Get the toolbar rect and save the height
447 GetWindowRect(m_hToolBar
, &rcTool
);
448 iToolHeight
= rcTool
.bottom
- rcTool
.top
;
450 // Resize the status bar
451 SendMessage(m_hStatusBar
, WM_SIZE
, 0, 0);
453 // Get the statusbar rect and save the height
454 GetWindowRect(m_hStatusBar
, &rcStatus
);
455 iStatusHeight
= rcStatus
.bottom
- rcStatus
.top
;
457 // Get the full client rect
458 GetClientRect(m_hMainWnd
, &rcClient
);
460 // Calculate the remaining height for the treeview
461 lvHeight
= rcClient
.bottom
- iToolHeight
- iStatusHeight
;
463 // Resize the device view
464 m_DeviceView
->OnSize(0,
473 CMainWindow::OnNotify(LPARAM lParam
)
475 LPNMHDR NmHdr
= (LPNMHDR
)lParam
;
482 LPNMTREEVIEW NmTreeView
= (LPNMTREEVIEW
)lParam
;
483 UpdateUiContext(&NmTreeView
->itemNew
);
489 LPNMTREEVIEW NmTreeView
= (LPNMTREEVIEW
)lParam
;
490 m_DeviceView
->DisplayPropertySheet();
496 Ret
= m_DeviceView
->OnRightClick(NmHdr
);
502 m_DeviceView
->DisplayPropertySheet();
506 case TTN_GETDISPINFO
:
508 LPTOOLTIPTEXT lpttt
= (LPTOOLTIPTEXT
)lParam
;
510 UINT_PTR idButton
= (UINT
)lpttt
->hdr
.idFrom
;
514 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_PROPERTIES
);
516 case IDC_SCAN_HARDWARE
:
517 lpttt
->lpszText
= MAKEINTRESOURCEW(IDS_TOOLTIP_SCAN
);
520 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_ENABLE
);
522 case IDC_DISABLE_DRV
:
523 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_DIABLE
);
526 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_UPDATE
);
528 case IDC_UNINSTALL_DRV
:
529 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_UNINSTALL
);
540 CMainWindow::OnContext(LPARAM lParam
)
542 return m_DeviceView
->OnContextMenu(lParam
);
546 CMainWindow::OnCommand(WPARAM wParam
,
553 Msg
= LOWORD(wParam
);
559 m_DeviceView
->DisplayPropertySheet();
563 case IDC_SCAN_HARDWARE
:
565 ScanForHardwareChanges();
571 MessageBox(m_hMainWnd
, L
"Not yet implemented", L
"Enable Driver", MB_OK
);
575 case IDC_DISABLE_DRV
:
577 MessageBox(m_hMainWnd
, L
"Not yet implemented", L
"Disable Driver", MB_OK
);
583 MessageBox(m_hMainWnd
, L
"Not yet implemented", L
"Update Driver", MB_OK
);
587 case IDC_UNINSTALL_DRV
:
589 MessageBox(m_hMainWnd
, L
"Not yet implemented", L
"Uninstall Driver", MB_OK
);
593 case IDC_ADD_HARDWARE
:
595 MessageBox(m_hMainWnd
, L
"Not yet implemented", L
"Add Hardware", MB_OK
);
601 RefreshView(DevicesByType
);
607 RefreshView(DevicesByConnection
);
613 // Get the current state
614 UINT CurCheckState
= GetMenuState(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
);
615 if (CurCheckState
== MF_CHECKED
)
617 m_DeviceView
->SetHiddenDevices(false);
618 CheckMenuItem(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
| MF_UNCHECKED
);
620 else if (CurCheckState
== MF_UNCHECKED
)
622 m_DeviceView
->SetHiddenDevices(true);
623 CheckMenuItem(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
| MF_CHECKED
);
625 // Refresh the device view
626 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
635 MessageBoxW(m_hMainWnd
,
636 L
"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
638 MB_OK
| MB_APPLMODAL
);
640 // Set focus back to the treeview
641 m_DeviceView
->SetFocus();
647 // Post a close message to the window
648 PostMessageW(m_hMainWnd
,
656 // We didn't handle it
665 CMainWindow::OnDestroy()
667 // Uninitialize the device view
668 m_DeviceView
->Uninitialize();
674 // Clear the user data pointer
675 SetWindowLongPtr(m_hMainWnd
, GWLP_USERDATA
, 0);
677 // Break the message loop
684 CMainWindow::MainWndProc(HWND hwnd
,
692 // Get the object pointer from window context
693 This
= (CMainWindow
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
696 // Check that this isn't a create message
697 if (msg
!= WM_CREATE
)
699 // Don't handle null info pointer
700 goto HandleDefaultMessage
;
708 // Get the object pointer from the create param
709 This
= (CMainWindow
*)((LPCREATESTRUCT
)lParam
)->lpCreateParams
;
711 // Store the pointer in the window's global user data
712 SetWindowLongPtr(hwnd
, GWLP_USERDATA
, (LONG_PTR
)This
);
714 // Call the create handler
715 RetCode
= This
->OnCreate(hwnd
);
721 RetCode
= This
->OnSize();
727 RetCode
= This
->OnNotify(lParam
);
733 RetCode
= This
->OnContext(lParam
);
739 if (This
->m_hStatusBar
!= NULL
)
741 if (!This
->MainWndMenuHint(LOWORD(wParam
),
743 sizeof(MainMenuHintTable
) / sizeof(MainMenuHintTable
[0]),
746 This
->MainWndMenuHint(LOWORD(wParam
),
748 sizeof(SystemMenuHintTable
) / sizeof(SystemMenuHintTable
[0]),
758 // Handle the command message
759 RetCode
= This
->OnCommand(wParam
, lParam
);
762 // Hand it off to the default message handler
763 goto HandleDefaultMessage
;
768 case WM_ENTERMENULOOP
:
770 This
->UpdateStatusBar(true);
774 case WM_EXITMENULOOP
:
776 This
->UpdateStatusBar(false);
782 // Destroy the main window
790 // Call the destroy handler
791 RetCode
= This
->OnDestroy();
797 HandleDefaultMessage
:
798 RetCode
= DefWindowProc(hwnd
, msg
, wParam
, lParam
);
807 //////// MOVE ME ////////////////
809 HINSTANCE g_hInstance
= NULL
;
810 HANDLE ProcessHeap
= NULL
;
814 DeviceManager_ExecuteW(HWND hWndParent
,
816 LPCWSTR lpMachineName
,
819 CMainWindow MainWindow
;
820 INITCOMMONCONTROLSEX icex
;
821 CAtlStringW szAppName
;
824 // Store the global values
826 ProcessHeap
= GetProcessHeap();
828 // Initialize common controls
829 icex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
830 icex
.dwICC
= ICC_BAR_CLASSES
| ICC_COOL_CLASSES
;
831 InitCommonControlsEx(&icex
);
833 // Load the application name
834 if (szAppName
.LoadStringW(g_hInstance
, IDS_APPNAME
))
836 // Initialize the main window
837 if (MainWindow
.Initialize(szAppName
, nCmdShow
))
839 // Run the application
840 Ret
= MainWindow
.Run();
842 // Uninitialize the main window
843 MainWindow
.Uninitialize();