MFC MDI 设计用户首选项对话框 GUI 布局功能 [英] MFC MDI Designing user preferences dialog GUI layout functionality

查看:27
本文介绍了MFC MDI 设计用户首选项对话框 GUI 布局功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这种情况下,我没有卡住";但正在寻找有关如何执行有意义且易于构建的 GUI 布局机制的指导".我正在使用一个在视觉上匹配"的 TreeControlWinamp 的选项/首选项对话框,用于所有设置和程序选项.

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

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

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

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

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

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

这是初始化代码:

BOOL CSettingsDlg::OnInitDialog(){CDialog::OnInitDialog();//TODO: 在此处添加额外的初始化HTREEITEM hParent、hToolbars、hColorScheme、hTabStyles、hPowerUser、hResetApp;//HTREEITEM hCompany, hLevel, hLevelNext;//在核心示例中使用,此处不需要hParent = m_TreeCtrl.InsertItem((LPreferences"), TVI_ROOT);hToolbars = m_TreeCtrl.InsertItem((LToolbars"), hParent);hColorScheme = m_TreeCtrl.InsertItem((LColor Scheme"), hParent);hTabStyles = m_TreeCtrl.InsertItem((LTab Styles"), hParent);hPowerUser = m_TreeCtrl.InsertItem((LPower User"), hParent);hResetApp= m_TreeCtrl.InsertItem((L重置所有选项"), hParent);m_TreeCtrl.Expand(hParent, TVE_EXPAND);m_TreeCtrl.SelectItem(hParent);GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T(Preferences Settings"));返回真;//除非您将焦点设置为控件,否则返回 TRUE//例外:OCX 属性页应该返回 FALSE}

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

void CSettingsDlg::OnTvnSelchangedTree1(NMHDR *pNMHDR, LRESULT *pResult){//LPNMTREEVIEW pNMTreeView = reinterpret_cast(pNMHDR);//SetDlgItemInt(IDC_TXT_TREE1, m_TreeCtrl.GetItemData(pNMTreeView->itemNew.hItem));//*pResult = 0;HTREEITEM sel = m_TreeCtrl.GetSelectedItem();C点;CString str;GetCursorPos(&point);m_TreeCtrl.ScreenToClient(&point);UINT 标志 = 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);//只是为了验证.}如果(str ==首选项"){this->SetWindowText(_T(Preferences Settings"));GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T(Preferences Settings"));}if (str ==工具栏"){this->SetWindowText(_T(工具栏设置"));GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T(工具栏设置"));}if (str ==配色方案"){this->SetWindowText(_T(Color Scheme"));GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T(Color Scheme Settings"));}if (str ==标签样式"){this->SetWindowText(_T(Tab Styles Settings"));GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T(Tab Styles Settings"));}if (str ==高级用户"){this->SetWindowText(_T(高级用户设置"));GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T(高级用户设置"));}if (str == "重置所有选项"){this->SetWindowText(_T(重置所有设置"));GetDlgItem(IDC_SETTINGS_CAPTION)->SetWindowText(_T(重置所有设置"));}*pResult = 0;}

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

例如一些控件将是:

配色方案节点:5个用于主题更改的复选框工具栏节点:停靠或浮动的单选按钮高级用户节点:在程序操作中禁用用户警告的复选框选项卡样式节点:用于选择平面、3d 等的单选按钮.

当用户选择"时无论它将它写入注册表,然后我调用该函数来读取数据等等...

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

解决方案

虽然我真的不能说Winamp"的作者是如何解决这个问题的.软件实现了他们的用户界面,我建议您考虑使用

但是,新的(ish)

In this instance I am not "stuck" but looking for some 'guidance' on how to perform a GUI layout mechanism that makes sense and easy to construct. I am using a TreeControl that visually "matches" Winamp's options/preferences dialog for all the settings and program options.

TO BE CLEAR: This is not something I've ever attempted and looking for user input to help me get across the finish line.

I have 6 items in the 'tree' (the 'parent') and 5 'subitems'. I have it fully constructed and I can get the data from whatever node is selected (which I'll post below images).

I am using a "do.Modal dialog" and, when I click on the tree node, I want the right side of the dialog to update to the needed controls for that node function. The execution of controls through "show" and "hide" to me seems pretty easy. The issue I have is the how to do the visual "static" controls in the resource editor when each "node paged" controls may or may not sit on top of each other visually during design time. During run time, when each node is selected on the nodes controls will be active but during design time, I may have controls sitting on top of each other and will be a logistical nightmare trying to sort out their positions etc.

How do I resolve that aspect of building it? I think of it as a select: 'node' show: 'option page controls' so I get the logic; I'm just wondering if I should have separate "popup" pages and call those … or deal with the controls directly. Does that makes sense?

I've done some searching on how to do this, but the examples are all over the place and I figured asking here makes the most sense. I'm sure there are multiple ways to do this, I'm just looking for the shortest path and easiest to maintain and possibly expand on the options in the future.

The examples of the dialog and the source code I'm using:

Here is the initialization code:

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
}

Here is the dialog framework that I'm starting from scratch with just to arrive here:

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;

}

So as shown, you can see that I have the ability to change the static caption to the "active" page node that is selected from the tree. I'm looking to solve the best way to handle the GUI elements that will go on the right side....

Some controls for example will be:

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.

and when the user "selects" whatever it writes it to the registry and then I call the function to read the data blah blah blah...

So that is where I'm at. Does anyone have any suggestions on a course of action, so I don't paint myself into a corner?

解决方案

Although I can't actually speak for how the authors of the "Winamp" software implemented their UI, I would suggest that you consider using a property sheet for your case, where each set of controls can be implemented as separate property pages, each of which will be defined (both in the resource script and in the C++ code) in ways very similar to individual modal dialog boxes.

The 'classic' property sheet has a horizontal row of tabs (normally, at the top of the sheet) to select each page, as shown in the sample below. Indeed, some sources/platforms refer to a property sheet as a "tabbed dialog".

However, the new(ish) CMFCPropertySheet class allows you to replace that tab control with one of several other options, which will show as separate 'panes' (on the left-hand side of the sheet). To use one of these alternative styles, call the SetLook() member function in your constructor override with the CMFCPropertySheet::PropSheetLook_Tree enum value. The example shown in the link is not exactly what you have shown in your question, but the CMFCPropertySheet and CMFCPropertyPage classes allow many, many customizations to their appearance and style.

I have never actually used the PropSheetLook_Tree style, but the image below shows "one I made earlier" with the PropSheetLook_OutlookBar style.

这篇关于MFC MDI 设计用户首选项对话框 GUI 布局功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆