【问题标题】:MFC MDI Designing user preferences dialog GUI layout functionalityMFC MDI 设计用户首选项对话框 GUI 布局功能
【发布时间】:2021-07-15 00:33:18
【问题描述】:

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

要明确:这不是我曾经尝试过的事情,我从未尝试过寻找用户输入来帮助我越过终点线。

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

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

如何解决构建它的这方面问题?我认为它是一个 select: 'node' show: 'option page controls' 所以我明白了逻辑;我只是想知道我是否应该有单独的“弹出”页面并调用它们……或者直接处理控件。这有意义吗?

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

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

这里是初始化代码:

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.

当用户“选择”它写入注册表的任何内容时,我调用该函数来读取数据等等等等……

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

【问题讨论】:

标签: c++ user-interface visual-studio-2017 mfc mdi


【解决方案1】:

虽然我实际上无法说明“Winamp”软件的作者如何实现他们的 UI,但我建议您考虑使用 property sheet 来处理您的案例,其中每组控件都可以单独实现 属性页,每个属性页的定义(在资源脚本和 C++ 代码中)都以与单个模式对话框非常相似的方式进行定义。

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

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

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

【讨论】:

  • 感谢 Adrian 的详细反馈,example shown in the link 是一个不错的选择,并且接近我想要的。由于原始代码(不是我的)根本没有此功能,因此我试图找到框架代码来构建您显示的链接对话框。 VS2017 中是否有可以构建它的向导,或者我是否正在尝试重写我必须支持的新对话框类型?如果我可以从某个模板/示例中工作(如果有一个模板/示例)并且我可以对其进行调整,那将会很有帮助。感谢您提供任何补充信息。
  • 我现在找不到 VS 向导,但这里有一个教程可能会有所帮助:functionx.com/visualc/dialogboxes/mfcpspp.htm
  • 我开始了全新的教程。在第一次编译之前一切都很好。 VS 在用于属性页的enum 上有多个错误。 enum { IDD = IDD_CAREERS }; enum { IDD = IDD_COMPUTERSCIENCE }; ...其中有5个...都是C2065。我按照 tut 逐字逐句减去他们说的 Access the Careers.h file and change it as follows 应该是 Careers.cpp 的一件事。我被困在那里,因为我无法弄清楚到底出了什么问题。
  • @Kittmaster 不知道为什么 VS 不为你做这件事,但你应该将 #include "Resource.h" (或非常相似的东西)添加到你的预编译头文件(pch.h 文件,或者可能是 stdafx .h 在 2019 年之前的 VS 中)。
  • 我不得不手动添加Stdafx.h,因为教程没有提到它,但希望它在那里......我记得看到resource.h,我会仔细检查早晨。 pch.h 存在,但我会再次确认。
猜你喜欢
  • 1970-01-01
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-30
  • 1970-01-01
相关资源
最近更新 更多