MFC MDI 设计用户首选项对话框 GUI 布局功能

问题描述

在这种情况下,我不是“卡住”,而是寻找有关如何执行有意义且易于构建的 GUI 布局机制的“指导”。我使用的 TreeControl 可以在视觉上“匹配”Winamp 的所有设置和程序选项的选项/首选项对话框。

要清楚:这不是我曾经尝试过并寻找用户输入来帮助我越过终点线的事情。

我在“树”(“父”)中有 6 个项目和 5 个“子项目”。我已经完全构建好了,我可以从选择的任何节点获取数据(我将在图片下方发布)。

我正在使用“do.Modal 对话框”,当我单击树节点时,我希望对话框的右侧更新为该节点功能所需的控件。通过“显示”和“隐藏”来执行控制对我来说似乎很容易。我遇到的问题是,当每个“节点分页”控件在 design time 期间可能会或可能不会在视觉上彼此重叠时,如何在资源编辑器中执行可视化“静态”控件。在运行时,当在节点上选择每个节点时,控件将处于活动状态,但在设计时,我可能会将控件放在彼此的顶部,并且试图理清它们的位置等将成为后勤噩梦。

我如何解决构建它的那个方面?我认为它是一个选择:'节点'显示:'选项页面控件'所以我得到了逻辑;我只是想知道我是否应该有单独的“弹出”页面调用它们……或者直接处理控件。有意义吗?

我已经对如何执行此操作进行了一些搜索,但示例随处可见,我认为在这里提问最有意义。我确信有多种方法可以做到这一点,我只是在寻找最短路径和最容易维护的方法,并可能在未来扩展选项。

我正在使用的对话框示例和源代码

My Settings Dialog

Winamp's User Preferences Dialog

这是初始化代码

BOOL CSettingsDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Todo:  Add extra initialization here

    HTREEITEM hParent,hToolbars,hColorScheme,hTabStyles,hPowerUser,hResetApp;
                
    //HTREEITEM hCompany,hLevel,hLevelNext; // Used in core example,not needed here

    hParent = m_TreeCtrl.InsertItem((L"Preferences"),TVI_ROOT);
    hToolbars = m_TreeCtrl.InsertItem((L"Toolbars"),hParent);
    hColorScheme = m_TreeCtrl.InsertItem((L"Color Scheme"),hParent);
    hTabStyles = m_TreeCtrl.InsertItem((L"Tab Styles"),hParent);
    hPowerUser = m_TreeCtrl.InsertItem((L"Power User"),hParent);   
    hResetApp= m_TreeCtrl.InsertItem((L"Reset All Options"),hParent);
    
    m_TreeCtrl.Expand(hParent,TVE_EXPAND);
    m_TreeCtrl.SelectItem(hParent);
    GetDlgitem(IDC_SETTINGS_CAPTION)->SetwindowText(_T("Preferences Settings"));

    return TRUE;  // return TRUE unless you set the focus to a control
                  // EXCEPTION: OCX Property Pages should return FALSE
}

这是我从头开始的对话框架,只是为了到达这里:

void CSettingsDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR,LRESULT *pResult)
{

    //LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
    //SetDlgitemInt(IDC_TXT_TREE1,m_TreeCtrl.GetItemData(pNMTreeView->itemNew.hItem));
    //*pResult = 0;

    HTREEITEM sel = m_TreeCtrl.GetSelectedItem();
    CPoint point;
    CString str;
    GetCursorPos(&point);
    m_TreeCtrl.ScreenToClient(&point);
    UINT flags = 0;
    HTREEITEM hitItem = m_TreeCtrl.HitTest(point,&flags);
    if (hitItem && sel != hitItem)
    {
        sel = hitItem;
        m_TreeCtrl.SelectItem(sel);     
        str = m_TreeCtrl.GetItemText(sel);
        //MessageBox((LPCTSTR)str);  // Just to verify.  
    }

    if (str == "Preferences")
    {
        this->SetwindowText(_T("Preferences Settings"));
        GetDlgitem(IDC_SETTINGS_CAPTION)->SetwindowText(_T("Preferences Settings"));
    }

    if (str == "Toolbars")
    {
        this->SetwindowText(_T("Toolbars Settings"));
        GetDlgitem(IDC_SETTINGS_CAPTION)->SetwindowText(_T("Toolbars Settings"));
    }

    if (str == "Color Scheme")
    {
        this->SetwindowText(_T("Color Scheme"));
        GetDlgitem(IDC_SETTINGS_CAPTION)->SetwindowText(_T("Color Scheme Settings"));
    }

    if (str == "Tab Styles")
    {
        this->SetwindowText(_T("Tab Styles Settings"));
        GetDlgitem(IDC_SETTINGS_CAPTION)->SetwindowText(_T("Tab Styles Settings"));
    }

    if (str == "Power User")
    {
        this->SetwindowText(_T("Power User Settings"));
        GetDlgitem(IDC_SETTINGS_CAPTION)->SetwindowText(_T("Power User Settings"));
    }

    if (str == "Reset All Options")
    {
        this->SetwindowText(_T("Reset All Settings"));
        GetDlgitem(IDC_SETTINGS_CAPTION)->SetwindowText(_T("Reset All Settings"));
    }
    
    *pResult = 0;

}

如图所示,您可以看到我能够将静态标题更改为从树中选择的“活动”页面节点。我正在寻求解决处理将在右侧显示的 GUI 元素的最佳方法....

例如一些控件将是:

Color scheme Node: 5 check Boxes for theme changing

Toolbars Node: Radio button for Docked or Floating

Power User Node: CheckBox to disable user warning within program operation

Tab Styles Node: Radio buttons to select flat,3d,whatever.

用户“选择”将其写入注册表的任何内容时,然后我调用函数来读取数据等等......

这就是我所在的位置。有没有人对行动方案有任何建议,所以我不会把自己逼到墙角?

解决方法

虽然我实际上不能说“Winamp”软件的作者是如何实现他们的用户界面的,但我建议您考虑在您的情况下使用 property sheet,其中每组控件都可以实现为单独的属性页,每个属性页都将以非常类似于单个模式对话框的方式定义(在资源脚本和 C++ 代码中)。

“经典”属性表具有一排水平选项卡(通常位于表的顶部),用于选择每个页面,如下面的示例所示。事实上,一些来源/平台将属性表称为“选项卡式对话框”。

enter image description here

但是,新的(ish)CMFCPropertySheet class 允许您用其他几个选项之一替换该选项卡控件,这些选项将显示为单独的“窗格”(在工作表的左侧)。要使用这些替代样式之一,请使用 CMFCPropertySheet::PropSheetLook_Tree 枚举值调用构造函数覆盖中的 SetLook() member functionexample shown in the link 不是完全您在问题中显示的内容,但 CMFCPropertySheetCMFCPropertyPage 类允许对其外观和样式进行许多自定义。

我从未真正使用过 PropSheetLook_Tree 样式,但下图显示了“我之前制作的一个”样式为 PropSheetLook_OutlookBar 的样式。

enter image description here