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_UPDATE_DRV
, NULL
},
33 { IDC_DISABLE_DRV
, NULL
},
34 { IDC_UNINSTALL_DRV
, NULL
},
35 { IDC_SCAN_HARDWARE
, IDS_HINT_REFRESH
},
36 { IDC_ADD_HARDWARE
, NULL
},
37 { IDC_PROPERTIES
, IDS_HINT_PROP
},
40 { IDC_DEVBYTYPE
, IDS_HINT_DEV_BY_TYPE
},
41 { IDC_DEVBYCONN
, IDS_HINT_DEV_BY_CONN
},
42 { IDC_RESBYTYPE
, IDS_HINT_RES_BY_TYPE
},
43 { IDC_RESBYCONN
, IDS_HINT_RES_BY_TYPE
},
45 { IDC_ABOUT
, IDS_HINT_ABOUT
}
50 static const MENU_HINT SystemMenuHintTable
[] =
52 {SC_RESTORE
, IDS_HINT_SYS_RESTORE
},
53 {SC_MOVE
, IDS_HINT_SYS_MOVE
},
54 {SC_SIZE
, IDS_HINT_SYS_SIZE
},
55 {SC_MINIMIZE
, IDS_HINT_SYS_MINIMIZE
},
56 {SC_MAXIMIZE
, IDS_HINT_SYS_MAXIMIZE
},
57 {SC_CLOSE
, IDS_HINT_SYS_CLOSE
},
60 static TBBUTTON TbButtons
[] =
62 { BTN_PROPERTIES
, IDC_PROPERTIES
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
63 { BTN_SCAN_HARDWARE
, IDC_SCAN_HARDWARE
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
64 { 2, IDC_STATIC
, TBSTATE_ENABLED
, BTNS_SEP
, 0, 0 },
65 { BTN_ENABLE_DRV
, IDC_ENABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
66 { BTN_DISABLE_DRV
, IDC_DISABLE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
67 { BTN_UPDATE_DRV
, IDC_UPDATE_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 },
68 { BTN_UNINSTALL_DRV
, IDC_UNINSTALL_DRV
, TBSTATE_ENABLED
, BTNS_BUTTON
, 0, 0 }
72 /* PUBLIC METHODS **********************************************/
74 CMainWindow::CMainWindow(void) :
75 m_ToolbarhImageList(NULL
),
81 m_szMainWndClass
= L
"DevMgmtWndClass";
84 CMainWindow::~CMainWindow(void)
86 // Destroy any previous list
87 if (m_ToolbarhImageList
) ImageList_Destroy(m_ToolbarhImageList
);
91 CMainWindow::Initialize(LPCTSTR lpCaption
,
94 CAtlStringW szCaption
;
97 // Store the show window value
100 // Setup the window class struct
101 wc
.cbSize
= sizeof(WNDCLASSEXW
);
102 wc
.lpfnWndProc
= MainWndProc
;
103 wc
.hInstance
= g_hInstance
;
104 wc
.hIcon
= LoadIcon(g_hInstance
, MAKEINTRESOURCEW(IDI_MAIN_ICON
));
105 wc
.hCursor
= LoadCursor(NULL
, IDC_ARROW
);
106 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
107 wc
.lpszMenuName
= MAKEINTRESOURCEW(IDR_MAINMENU
);
108 wc
.lpszClassName
= m_szMainWndClass
;
109 wc
.hIconSm
= (HICON
)LoadImage(g_hInstance
,
110 MAKEINTRESOURCE(IDI_MAIN_ICON
),
116 // Register the window
117 if (RegisterClassExW(&wc
))
119 // Create the main window and store the object pointer
120 m_hMainWnd
= CreateWindowExW(WS_EX_WINDOWEDGE
,
123 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
134 // Return creation result
135 return !!(m_hMainWnd
);
139 CMainWindow::Uninitialize()
141 // Unregister the window class
142 UnregisterClassW(m_szMainWndClass
, g_hInstance
);
150 // Pump the message queue
151 while (GetMessageW(&Msg
, NULL
, 0, 0 ) != 0)
153 TranslateMessage(&Msg
);
154 DispatchMessageW(&Msg
);
161 /* PRIVATE METHODS **********************************************/
164 CMainWindow::MainWndMenuHint(WORD CmdId
,
165 const MENU_HINT
*HintArray
,
170 const MENU_HINT
*LastHint
;
171 UINT HintId
= DefHintId
;
173 LastHint
= HintArray
+ HintsCount
;
174 while (HintArray
!= LastHint
)
176 if (HintArray
->CmdId
== CmdId
)
178 HintId
= HintArray
->HintId
;
185 StatusBarLoadString(m_hStatusBar
,
194 CMainWindow::RefreshView(ViewType Type
)
199 // Refreshed the cached view
200 m_DeviceView
->Refresh(Type
, FALSE
, TRUE
);
202 // Get the menu item id
205 case DevicesByType
: CheckId
= IDC_DEVBYTYPE
; break;
206 case DevicesByConnection
: CheckId
= IDC_DEVBYCONN
; break;
207 case ResourcesByType
: CheckId
= IDC_RESBYTYPE
; break;
208 case ResourcesByConnection
: CheckId
= IDC_RESBYCONN
; break;
209 default: ATLASSERT(FALSE
); break;
212 // Set the new check item
213 bSuccess
= CheckMenuRadioItem(m_hMenu
,
223 CMainWindow::ScanForHardwareChanges()
225 // Refresh the cache and and display
226 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
233 CMainWindow::CreateToolBar()
235 TBADDBITMAP TbAddBitmap
;
238 DWORD dwStyles
= WS_CHILDWINDOW
| TBSTYLE_FLAT
| TBSTYLE_WRAPABLE
| TBSTYLE_TOOLTIPS
| CCS_NODIVIDER
;
239 DWORD dwExStyles
= WS_EX_LEFT
| WS_EX_LTRREADING
| WS_EX_RIGHTSCROLLBAR
;
241 // Create the toolbar window
242 m_hToolBar
= CreateWindowExW(dwExStyles
,
251 if (m_hToolBar
== NULL
) return FALSE
;
253 // Don't show clipped buttons
254 SendMessageW(m_hToolBar
,
257 TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
259 SendMessageW(m_hToolBar
, TB_SETBITMAPSIZE
, 0, MAKELONG(16, 16));
261 // Set the struct size, the toobar needs this...
262 SendMessageW(m_hToolBar
,
267 TbAddBitmap
.hInst
= g_hInstance
;
268 TbAddBitmap
.nID
= IDB_TOOLBAR
;
269 Index
= SendMessageW(m_hToolBar
, TB_ADDBITMAP
, _countof(TbButtons
), (LPARAM
)&TbAddBitmap
);
271 SendMessageW(m_hToolBar
, TB_ADDBUTTONSW
, _countof(TbButtons
), (LPARAM
)TbButtons
);
272 SendMessageW(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
276 ShowWindow(m_hToolBar
, SW_SHOW
);
283 CMainWindow::CreateStatusBar()
285 int StatWidths
[] = {110, -1}; // widths of status bar
288 // Create the status bar
289 m_hStatusBar
= CreateWindowExW(0,
292 WS_CHILD
| WS_VISIBLE
| SBARS_SIZEGRIP
,
295 (HMENU
)IDC_STATUSBAR
,
301 bRet
= (SendMessageW(m_hStatusBar
,
303 sizeof(StatWidths
) / sizeof(int),
304 (LPARAM
)StatWidths
) != 0);
310 void CMainWindow::UpdateUiContext(_In_ LPTV_ITEMW TvItem
)
315 if (m_DeviceView
->HasProperties(TvItem
))
317 State
= TBSTATE_ENABLED
;
321 State
= TBSTATE_HIDDEN
;
323 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_PROPERTIES
, MAKELPARAM(State
, 0));
324 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UPDATE_DRV
, MAKELPARAM(State
, 0)); //hack
325 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_UNINSTALL_DRV
, MAKELPARAM(State
, 0)); // hack
327 // enable driver button
328 if (m_DeviceView
->IsDisabled(TvItem
))
330 State
= TBSTATE_ENABLED
;
334 State
= TBSTATE_HIDDEN
;
336 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_ENABLE_DRV
, MAKELPARAM(State
, 0));
338 // disable driver button
339 if (m_DeviceView
->CanDisable(TvItem
) && !m_DeviceView
->IsDisabled(TvItem
))
341 State
= TBSTATE_ENABLED
;
345 State
= TBSTATE_HIDDEN
;
347 SendMessageW(m_hToolBar
, TB_SETSTATE
, IDC_DISABLE_DRV
, MAKELPARAM(State
, 0));
358 CMainWindow::StatusBarLoadString(IN HWND hStatusBar
,
360 IN HINSTANCE hInstance
,
363 CAtlStringW szMessage
;
367 if (szMessage
.LoadStringW(hInstance
, uID
))
369 // Show the string on the status bar
370 bRet
= (SendMessageW(hStatusBar
,
373 (LPARAM
)szMessage
.GetBuffer()) != 0);
380 CMainWindow::OnCreate(HWND hwnd
)
387 // Store a handle to the main menu
388 m_hMenu
= GetMenu(m_hMainWnd
);
390 // Create the toolbar and statusbar
391 if (CreateToolBar() && CreateStatusBar())
393 // Create the device view object
394 m_DeviceView
= new CDeviceView(m_hMainWnd
);
395 if (m_DeviceView
->Initialize())
397 // Do the initial scan
398 ScanForHardwareChanges();
400 // Display the window according to the user request
401 ShowWindow(hwnd
, m_CmdShow
);
410 CMainWindow::OnSize()
412 RECT rcClient
, rcTool
, rcStatus
;
413 INT lvHeight
, iToolHeight
, iStatusHeight
;
415 // Autosize the toolbar
416 SendMessage(m_hToolBar
, TB_AUTOSIZE
, 0, 0);
418 // Get the toolbar rect and save the height
419 GetWindowRect(m_hToolBar
, &rcTool
);
420 iToolHeight
= rcTool
.bottom
- rcTool
.top
;
422 // Resize the status bar
423 SendMessage(m_hStatusBar
, WM_SIZE
, 0, 0);
425 // Get the statusbar rect and save the height
426 GetWindowRect(m_hStatusBar
, &rcStatus
);
427 iStatusHeight
= rcStatus
.bottom
- rcStatus
.top
;
429 // Get the full client rect
430 GetClientRect(m_hMainWnd
, &rcClient
);
432 // Calculate the remaining height for the treeview
433 lvHeight
= rcClient
.bottom
- iToolHeight
- iStatusHeight
;
435 // Resize the device view
436 m_DeviceView
->OnSize(0,
445 CMainWindow::OnNotify(LPARAM lParam
)
447 LPNMHDR NmHdr
= (LPNMHDR
)lParam
;
454 LPNMTREEVIEW NmTreeView
= (LPNMTREEVIEW
)lParam
;
455 UpdateUiContext(&NmTreeView
->itemNew
);
461 LPNMTREEVIEW NmTreeView
= (LPNMTREEVIEW
)lParam
;
462 m_DeviceView
->DisplayPropertySheet();
468 Ret
= m_DeviceView
->OnRightClick(NmHdr
);
474 m_DeviceView
->DisplayPropertySheet();
483 CMainWindow::OnContext(LPARAM lParam
)
485 return m_DeviceView
->OnContextMenu(lParam
);
489 CMainWindow::OnCommand(WPARAM wParam
,
496 Msg
= LOWORD(wParam
);
502 m_DeviceView
->DisplayPropertySheet();
506 case IDC_SCAN_HARDWARE
:
508 ScanForHardwareChanges();
514 RefreshView(DevicesByType
);
520 RefreshView(DevicesByConnection
);
526 UINT CurCheckState
, NewCheckState
;
528 // Get the current state
529 CurCheckState
= GetMenuState(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
);
531 if (CurCheckState
== MF_CHECKED
)
533 // Inform the device view of the change
534 m_DeviceView
->SetHiddenDevices(false);
535 NewCheckState
= MF_UNCHECKED
;
537 else if (CurCheckState
== MF_UNCHECKED
)
539 m_DeviceView
->SetHiddenDevices(true);
540 NewCheckState
= MF_CHECKED
;
548 // Set the new check state
549 CheckMenuItem(m_hMenu
, IDC_SHOWHIDDEN
, MF_BYCOMMAND
| NewCheckState
);
551 // Refresh the device view
552 m_DeviceView
->Refresh(m_DeviceView
->GetCurrentView(),
561 MessageBoxW(m_hMainWnd
,
562 L
"ReactOS Device Manager\r\nCopyright Ged Murphy 2015",
564 MB_OK
| MB_APPLMODAL
);
566 // Set focus back to the treeview
567 m_DeviceView
->SetFocus();
573 // Post a close message to the window
574 PostMessageW(m_hMainWnd
,
582 // We didn't handle it
591 CMainWindow::OnDestroy()
593 // Uninitialize the device view
594 m_DeviceView
->Uninitialize();
600 // Clear the user data pointer
601 SetWindowLongPtr(m_hMainWnd
, GWLP_USERDATA
, 0);
603 // Break the message loop
610 CMainWindow::MainWndProc(HWND hwnd
,
618 // Get the object pointer from window context
619 pThis
= (CMainWindow
*)GetWindowLongPtr(hwnd
, GWLP_USERDATA
);
622 // Check that this isn't a create message
623 if (msg
!= WM_CREATE
)
625 // Don't handle null info pointer
626 goto HandleDefaultMessage
;
634 // Get the object pointer from the create param
635 pThis
= (CMainWindow
*)((LPCREATESTRUCT
)lParam
)->lpCreateParams
;
637 // Store the pointer in the window's global user data
638 SetWindowLongPtr(hwnd
, GWLP_USERDATA
, (LONG_PTR
)pThis
);
640 // Call the create handler
641 RetCode
= pThis
->OnCreate(hwnd
);
647 RetCode
= pThis
->OnSize();
653 RetCode
= pThis
->OnNotify(lParam
);
659 RetCode
= pThis
->OnContext(lParam
);
665 if (pThis
->m_hStatusBar
!= NULL
)
667 if (!pThis
->MainWndMenuHint(LOWORD(wParam
),
669 sizeof(MainMenuHintTable
) / sizeof(MainMenuHintTable
[0]),
672 pThis
->MainWndMenuHint(LOWORD(wParam
),
674 sizeof(SystemMenuHintTable
) / sizeof(SystemMenuHintTable
[0]),
684 // Handle the command message
685 RetCode
= pThis
->OnCommand(wParam
, lParam
);
688 // Hand it off to the default message handler
689 goto HandleDefaultMessage
;
695 // Destroy the main window
702 // Call the destroy handler
703 RetCode
= pThis
->OnDestroy();
709 HandleDefaultMessage
:
710 RetCode
= DefWindowProc(hwnd
, msg
, wParam
, lParam
);
719 //////// MOVE ME ////////////////
721 HINSTANCE g_hInstance
= NULL
;
722 HANDLE ProcessHeap
= NULL
;
726 DeviceManager_ExecuteW(HWND hWndParent
,
728 LPCWSTR lpMachineName
,
731 CMainWindow MainWindow
;
732 INITCOMMONCONTROLSEX icex
;
733 CAtlStringW szAppName
;
736 // Store the global values
738 ProcessHeap
= GetProcessHeap();
740 // Initialize common controls
741 icex
.dwSize
= sizeof(INITCOMMONCONTROLSEX
);
742 icex
.dwICC
= ICC_BAR_CLASSES
| ICC_COOL_CLASSES
;
743 InitCommonControlsEx(&icex
);
745 // Load the application name
746 if (szAppName
.LoadStringW(g_hInstance
, IDS_APPNAME
))
748 // Initialize the main window
749 if (MainWindow
.Initialize(szAppName
, nCmdShow
))
751 // Run the application
752 Ret
= MainWindow
.Run();
754 // Uninitialize the main window
755 MainWindow
.Uninitialize();