[MMC_NEW] Move the root of the snap-in tree to the main window

- Fix File/New command. This command closes all views, deletes the snap-in
  tree, creates a new root folder snap-in and finally creates a new root view.
- Implement the Windows/New Window command. This command just creates a new
  root view.
- Update the main window title.
- Adjust the options dialog accordingly.

Hint: Running mmc_new might fail on ReactOS because of the missing folder
      snap-in. I will add some dummy/test snap-in skeletons including the
      folder snap-in next.
This commit is contained in:
Eric Kohl
2026-09-13 12:05:00 +02:00
parent d3c8e2733c
commit 752f620e9a
7 changed files with 167 additions and 33 deletions

View File

@@ -4,13 +4,16 @@
* PURPOSE: Single 'console' window
* COPYRIGHT: Copyright 2006-2007 Thomas Weidenmueller
* Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2026 Eric Kohl (eric.kohl@reactos.org)
*/
#include "precomp.h"
CConsoleWnd::CConsoleWnd(CMainWnd *MainWnd)
CConsoleWnd::CConsoleWnd(CMainWnd *MainWnd, CSnapin *RootNode)
{
m_MainWnd = MainWnd;
m_ViewRootNode = RootNode;
m_ViewSelectedNode = RootNode;
m_pfnSuperWindowProc = DefMDIChildProc;
if (!m_thunk.Init(NULL, NULL))
@@ -61,6 +64,8 @@
m_ViewId = m_MainWnd->RegisterView(this);
UpdateTreeView();
LPMDICREATESTRUCT mdicreate = reinterpret_cast<LPMDICREATESTRUCT>(reinterpret_cast<LPCREATESTRUCT>(lParam)->lpCreateParams);
if (mdicreate->lParam)
PostMessage(WM_SYSCOMMAND, SC_MAXIMIZE, 0);
@@ -101,6 +106,41 @@
return TRUE;
}
VOID CConsoleWnd::AddTreeViewItemRecursive(HTREEITEM hParentTreeItem, CSnapin *Node)
{
HTREEITEM hTreeItem;
hTreeItem = m_TreeView.AddItem(hParentTreeItem,
(LPWSTR)Node->DisplayName().GetString(),
Node->GetCacheEntry()->NormalImageIndex(),
Node->GetCacheEntry()->OpenImageIndex(),
(LPARAM)Node);
if (hTreeItem)
{
#if 0
int snapinCount = Node->GetNodeCount();
for (int i = 0; i < snapinCount; i++)
{
CSnapinNode *ChildNode = Node->GetNode(i);
if (ChildNode)
AddTreeViewItemRecursive(hTreeItem, ChildNode);
}
if (snapinCount > 0)
m_TreeView.Expand(hTreeItem, TVE_EXPAND);
if (Node == m_SelectedNode)
m_TreeView.SelectItem(hTreeItem);
#endif
}
}
VOID CConsoleWnd::UpdateTreeView()
{
m_TreeView.DeleteItem(TVI_ROOT);
AddTreeViewItemRecursive(TVI_ROOT, m_ViewRootNode);
}
BOOL CConsoleWnd::IsTreeViewVisible()
{
return m_bTreeViewVisible;

View File

@@ -4,6 +4,7 @@
* PURPOSE: Single 'console' window
* COPYRIGHT: Copyright 2006-2007 Thomas Weidenmueller
* Copyright 2017 Mark Jansen (mark.jansen@reactos.org)
* Copyright 2026 Eric Kohl (eric.kohl@reactos.org)
*/
#pragma once
@@ -33,6 +34,9 @@ private:
BOOL m_bStatusBarVisible;
BOOL m_bDescriptionBarVisible;
CSnapin *m_ViewRootNode;
CSnapin *m_ViewSelectedNode;
public:
CAtlString m_Filename;
@@ -76,9 +80,11 @@ public:
private:
VOID UpdateLayout();
VOID AddTreeViewItemRecursive(HTREEITEM hParentTreeItem, CSnapin *Node);
VOID UpdateTreeView();
public:
CConsoleWnd(CMainWnd *MainWnd);
CConsoleWnd(CMainWnd *MainWnd, CSnapin *RootNode);
~CConsoleWnd();
LRESULT OnCreate(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled);

View File

@@ -24,11 +24,11 @@ static TBBUTTON TbButtons[] =
};
CMainWnd::CMainWnd()
: m_NewConsoleCount(0)
, m_nConsoleCount(0)
: m_nConsoleNumber(0)
, m_ConsoleMode(AuthorMode)
, m_bToolBarVisible(true)
, m_NextViewId(1)
, m_RootNode(NULL)
{
m_FrameThunk.Init(XDefFrameProc, this);
m_pfnSuperWindowProc = m_FrameThunk.GetWNDPROC();
@@ -73,8 +73,6 @@ CMainWnd::OnCreate(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
RECT rect;
m_bStandardMenusVisible = TRUE;
UpdateMenu();
SetWindowTextW(L"ReactOS Management Console");
/* Create and initialize the Toolbar */
m_bToolBarVisible = TRUE;
@@ -119,7 +117,7 @@ CMainWnd::OnSize(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
LRESULT
CMainWnd::OnCloseChild(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
m_nConsoleCount--;
UpdateTitle();
UpdateMenu();
return 0;
}
@@ -140,13 +138,42 @@ CMainWnd::OnClose(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
}
LRESULT
CMainWnd::OnNewMDIChild(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
CMainWnd::OnFileNew(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
MDICREATESTRUCT mcs;
HWND hChild;
CAtlString title;
CreateNewConsoleTitle(title);
mcs.szTitle = title.GetString();
CAtlString rootName(MAKEINTRESOURCE(IDS_CONSOLEROOT));
// CAtlString nodeGuid(L"{C96401CC-0E17-11D3-885B-00C04F72C717}");
/* Close all views */
POSITION pos = m_ViewList.GetHeadPosition();
while (pos)
{
CConsoleWnd *console = (CConsoleWnd*)m_ViewList.GetNext(pos);
console->SendMessage(WM_CLOSE, 0, 0);
}
/* Delete the snapin tree */
delete m_RootNode;
m_RootNode = NULL;
/* Create a new snapin root node */
CSnapinCacheEntry *CacheEntry = GetSnapinCacheEntryByGuid((PWSTR)L"{C96401CC-0E17-11D3-885B-00C04F72C717}");
if (!CacheEntry)
{
DPRINT1("No folder cache entry!\n");
return 0;
}
m_RootNode = new CSnapin(CacheEntry, rootName.GetString());
if (!CacheEntry)
{
DPRINT1("No root folder!\n");
return 0;
}
/* Create a new view */
mcs.szTitle = rootName.GetString();
mcs.szClass = CConsoleWnd::GetWndClassName();
mcs.hOwner = _AtlBaseModule.GetModuleInstance();
mcs.x = mcs.cx = CW_USEDEFAULT;
@@ -156,18 +183,23 @@ CMainWnd::OnNewMDIChild(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled
HWND hWndOld = (HWND)m_MDIClient.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
mcs.lParam = bMaximized || !hWndOld;
/* This object registers itself in the _AtlWinModule to be assigned to the next window created */
CConsoleWnd* child = new CConsoleWnd(this);
CConsoleWnd* child = new CConsoleWnd(this, m_RootNode);
/* Ask for a new MDI Child window */
hChild = (HWND)m_MDIClient.SendMessage(WM_MDICREATE, 0, (LONG_PTR)&mcs);
if (hChild)
{
m_nConsoleCount++;
m_nConsoleNumber++;
}
else
{
delete child;
delete m_RootNode;
m_RootNode = NULL;
}
UpdateTitle();
UpdateMenu();
return 1;
}
@@ -261,6 +293,34 @@ CMainWnd::OnViewCustomize(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandl
return 0;
}
LRESULT
CMainWnd::OnWindowsNew(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
MDICREATESTRUCT mcs;
HWND hChild;
mcs.szTitle = m_RootNode->DisplayName().GetString();
mcs.szClass = CConsoleWnd::GetWndClassName();
mcs.hOwner = _AtlBaseModule.GetModuleInstance();
mcs.x = mcs.cx = CW_USEDEFAULT;
mcs.y = mcs.cy = CW_USEDEFAULT;
mcs.style = MDIS_ALLCHILDSTYLES;
BOOL bMaximized = FALSE;
HWND hWndOld = (HWND)m_MDIClient.SendMessage(WM_MDIGETACTIVE, 0, (LPARAM)&bMaximized);
mcs.lParam = bMaximized || !hWndOld;
/* This object registers itself in the _AtlWinModule to be assigned to the next window created */
CConsoleWnd* child = new CConsoleWnd(this, m_RootNode);
/* Ask for a new MDI Child window */
hChild = (HWND)m_MDIClient.SendMessage(WM_MDICREATE, 0, (LONG_PTR)&mcs);
if (!hChild)
{
delete child;
}
UpdateMenu();
return 0;
}
LRESULT
CMainWnd::OnWindowsCascade(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
{
@@ -334,6 +394,17 @@ CMainWnd::OnMDIForward(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
return 0;
}
CAtlString *CMainWnd::GetConsoleTitle()
{
return &m_ConsoleTitle;
}
void CMainWnd::SetConsoleTitle(CAtlString consoleTitle)
{
m_ConsoleTitle = consoleTitle;
SetWindowTextW(consoleTitle.GetString());
}
BOOL
CMainWnd::IsToolBarVisible()
{
@@ -437,13 +508,13 @@ CMainWnd::UpdateViews()
POSITION pos;
pos = m_ViewList.GetHeadPosition();
do
while (pos)
{
console = (CConsoleWnd*)m_ViewList.GetNext(pos);
if (console)
console->UpdateView();
} while (pos != NULL);
}
}
void

View File

@@ -24,8 +24,8 @@ class CMainWnd :
private:
CWndProcThunk m_FrameThunk;
int m_NewConsoleCount;
int m_nConsoleCount;
int m_nConsoleNumber;
CAtlString m_ConsoleTitle;
HMENU m_hMenuConsoleSmall;
HMENU m_hMenuConsoleLarge;
CONSOLE_MODE m_ConsoleMode;
@@ -42,6 +42,8 @@ private:
CAtlList<CConsoleWnd*> m_ViewList;
int m_NextViewId;
CSnapin *m_RootNode;
public:
CWindow m_MDIClient;
@@ -54,7 +56,7 @@ public:
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_USER_CLOSE_CHILD, OnCloseChild)
COMMAND_ID_HANDLER(IDM_FILE_NEW, OnNewMDIChild)
COMMAND_ID_HANDLER(IDM_FILE_NEW, OnFileNew)
COMMAND_ID_HANDLER(IDM_FILE_SAVE, OnFileSave)
COMMAND_ID_HANDLER(IDM_FILE_SAVEAS, OnFileSaveAs)
COMMAND_ID_HANDLER(IDM_FILE_ADD, OnFileAdd)
@@ -63,6 +65,7 @@ public:
COMMAND_ID_HANDLER(IDM_VIEW_CUSTOMIZE, OnViewCustomize)
COMMAND_ID_HANDLER(IDM_WINDOWS_NEW, OnWindowsNew)
COMMAND_ID_HANDLER(IDM_WINDOWS_CASCADE, OnWindowsCascade)
COMMAND_ID_HANDLER(IDM_WINDOWS_TILE, OnWindowsTile)
COMMAND_ID_HANDLER(IDM_WINDOWS_ARRANGE, OnWindowsArrange)
@@ -113,12 +116,21 @@ private:
void UpdateMenu()
{
if (m_nConsoleCount == 0)
if (m_ViewList.IsEmpty())
SetMenu(m_hMenuConsoleSmall);
else
SetMenu(m_hMenuConsoleLarge);
}
void UpdateTitle()
{
if (m_ViewList.IsEmpty())
m_ConsoleTitle.LoadString(IDS_APPTITLE);
else
CreateNewConsoleTitle(m_ConsoleTitle);
SetWindowTextW(m_ConsoleTitle.GetString());
}
CConsoleWnd* GetActiveChildInfo()
{
HWND hWndMDIChild;
@@ -132,7 +144,7 @@ private:
void CreateNewConsoleTitle(CAtlString& str)
{
DWORD_PTR args[1] = { (DWORD_PTR)(++m_NewConsoleCount) };
DWORD_PTR args[1] = { (DWORD_PTR)(m_nConsoleNumber) };
str.LoadString(IDS_CONSOLETITLE);
LPTSTR lpTarget = NULL;
@@ -157,13 +169,14 @@ public:
LRESULT OnDestroy(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnClose(UINT nMessage, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnNewMDIChild(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnFileNew(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnFileSave(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnFileSaveAs(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnFileAdd(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnFileOptions(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnFileExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnViewCustomize(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnWindowsNew(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnWindowsCascade(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnWindowsTile(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
LRESULT OnWindowsArrange(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled);
@@ -178,6 +191,8 @@ private:
void UpdateViews();
public:
CAtlString *GetConsoleTitle();
void SetConsoleTitle(CAtlString consoleTitle);
BOOL IsToolBarVisible();
VOID SetToolBarVisible(BOOL bVisible);
BOOL AreStandardMenusVisible();

View File

@@ -63,9 +63,7 @@ public:
// m_ConsoleIcon.SetIcon();
CAtlString consoleTitle;
m_Console->GetWindowText(consoleTitle);
m_ConsoleName.SetWindowText(consoleTitle);
m_ConsoleName.SetWindowText(m_MainWnd->GetConsoleTitle()->GetString());
m_ConsoleSymbol.EnableWindow(FALSE);
@@ -111,7 +109,7 @@ public:
{
CAtlString consoleTitle;
m_ConsoleName.GetWindowText(consoleTitle);
m_Console->SetWindowText(consoleTitle);
m_MainWnd->SetConsoleTitle(consoleTitle);
m_MainWnd->SetConsoleMode(m_consoleMode);
EndDialog(IDOK);

View File

@@ -133,6 +133,8 @@ BEGIN
IDS_VENDOR "Vendor"
IDS_ABOUTTITLE "About"
IDS_CONSOLEROOT "Console Root"
IDS_AUTHORMODE "Author mode"
IDS_USERMODE_FULL "User mode - full access"
IDS_USERMODE_MULTIPLE "User mode - limited access, multiple window"

View File

@@ -88,15 +88,17 @@
#define IDC_CONSOLECUSTOM 3207
#define IDS_AUTHORMODE 5000
#define IDS_USERMODE_FULL 5001
#define IDS_USERMODE_MULTIPLE 5002
#define IDS_USERMODE_SINGLE 5003
#define IDS_CONSOLEROOT 5010
#define IDS_AUTHORMODE_DESC 5004
#define IDS_USERMODE_FULL_DESC 5005
#define IDS_USERMODE_MULTIPLE_DESC 5006
#define IDS_USERMODE_SINGLE_DESC 5007
#define IDS_AUTHORMODE 5100
#define IDS_USERMODE_FULL 5101
#define IDS_USERMODE_MULTIPLE 5102
#define IDS_USERMODE_SINGLE 5103
#define IDS_AUTHORMODE_DESC 5104
#define IDS_USERMODE_FULL_DESC 5105
#define IDS_USERMODE_MULTIPLE_DESC 5106
#define IDS_USERMODE_SINGLE_DESC 5107