哪个是 MFC C++ 中单选组合框的事件处理程序

Posted

技术标签:

【中文标题】哪个是 MFC C++ 中单选组合框的事件处理程序【英文标题】:Which is the event handler for Combobox for single select in MFC C++ 【发布时间】:2019-05-09 05:14:32 【问题描述】:

在选择特定组合框时启用或禁用某些文本框时遇到问题。

我尝试过使用OnCbnSelChangeLvLayers()OnCbnDropdownLvLayers()。 第一个事件处理程序的问题是我必须两次单击相同的值,并且组合框中的选择会冻结。第二个事件处理程序解决了冻结问题,但我必须单击组合框的下拉菜单才能发生事件。我还为组合框尝试了其他一些事件处理程序,但没有成功。 m_d_layers 是组合框选择的字符串变量 (1,2,3,4)

DDX:

void CThermalToolDlg::DoDataExchange(CDataExchange* pDX)

    DDX_CBString(pDX, IDC_LV_LAYERS, m_d_lvlayers);

消息映射:

BEGIN_MESSAGE_MAP(CThermalToolDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_CBN_DROPDOWN(IDC_LV_LAYERS, &CThermalToolDlg::OnCbnDropdownLvLayers)
ON_CBN_DROPDOWN(IDC_HV_LAYERS, &CThermalToolDlg::OnCbnDropdownHvLayers)
ON_CBN_DROPDOWN(IDC_LVDUCTTYPE1, &CThermalToolDlg::OnCbnDropdownLvducttype1)
ON_CBN_DROPDOWN(IDC_LVDUCTTYPE2, &CThermalToolDlg::OnCbnDropdownLvducttype2)
ON_CBN_DROPDOWN(IDC_LVDUCTTYPE3, &CThermalToolDlg::OnCbnDropdownLvducttype3)
ON_CBN_DROPDOWN(IDC_HVDUCTTYPE1, &CThermalToolDlg::OnCbnDropdownHvducttype1)
ON_CBN_DROPDOWN(IDC_HVDUCTTYPE2, &CThermalToolDlg::OnCbnDropdownHvducttype2)
ON_CBN_DROPDOWN(IDC_HVDUCTTYPE3, &CThermalToolDlg::OnCbnDropdownHvducttype3)
ON_BN_CLICKED(IDCANCEL, &CThermalToolDlg::OnBnClickedCancel)
ON_BN_CLICKED(ID_CALCULATE, &CThermalToolDlg::OnCalculate)
//ON_CBN_EDITUPDATE(IDC_LV_LAYERS,&CThermalToolDlg::OnCbnEditupdateLvLayers)
//ON_CBN_SELENDOK(IDC_LV_LAYERS, &CThermalToolDlg::OnCbnSelendokLvLayers)

END_MESSAGE_MAP()

事件处理程序:

void CThermalToolDlg::OnCbnDropdownLvLayers()

    // TODO: Add your control notification handler code here
    UpdateData();

    if (m_d_lvlayers == "1")
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(0);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(0);
            //and so on
    
    else if (m_d_lvlayers == "2")
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(1);
            //and so on

    
    else if (m_d_lvlayers == "3")
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(1);
            //and so on
    
    else
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(1);
            //and so on
    

我想在不冻结组合框的情况下单击一下即可获得所需的启用/禁用。有没有其他方法或更快的方法?

【问题讨论】:

这个问题的第一个答案怎么样:***.com/questions/698910/…? @SamiSallinen 感谢您引导我解决这个问题。它与我的问题一致,但是两个事件处理程序(SELENDOK 和 EDITUPDATE)的解决方案不起作用,并且代码总是跳转到 else 循环。我不知道我做错了什么。 您的代码很糟糕:唯一与其他所有不同的情况是“1”。话虽这么说:您需要添加一张图片,显示 IDC_LV2_CU 和 IDC_LV2_ICI 是什么控件。 @Jabberwocky 情况不同我只是没有提到所有条件。 IDC_LV2_CU 和 IDC_LV2_ICI 是几个文本框(还有更多),需要根据 4 个选择启用或禁用。这里的问题是通过单击更新类文件中组合框的值。 显示您的消息映射 (BEGIN_MESSAGE_MAP...) 以及 CThermalToolDlg::DoDataExchange 的定义。如果您有 OnCbnEditUpdate 和其他与组合框相关的处理程序,那么也显示它们的定义。通常你只需要处理ON_CBN_SELCHANGE 【参考方案1】:

这似乎是下拉列表组合框和简单组合框(不是下拉列表)的错误。 DDX_CBStringDDX_CBStringExact 未检索到正确的值以响应 ON_CBN_DROPDOWN

您可以使用自己的代码来检索正确的字符串:

void CThermalToolDlg::OnCbnDropdownLvLayers() 
 
    //UpdateData();
    CComboBox *cb = (CComboBox*)GetDlgItem(IDC_LV_LAYERS);
    if(cb)
    
        int sel = cb->GetCurSel();
        if(sel >= 0)
            cb->GetLBText(sel, m_d_lvlayers);
    
    TRACE(L"%s\n", m_d_lvlayers.GetString());

出于调试目的,注释掉除ON_CBN_DROPDOWN(IDC_LV_LAYERS...) 之外的其他消息。在继续之前,请确保您拥有正确的字符串。

不要像您在上一个问题中所做的那样致电UpdateData(FALSE)。如果没有检索到正确的字符串,这可能会导致问题。

【讨论】:

这是检索正确字符串的正确方法,但仍然在选择组合框中的值调试到 void CThermalToolDlg::OnCbnDropdownLvLayers() 中的 else 循环我应该为条件添加单独的事件处理程序吗?跨度> 我不确定根本问题。也许某处有空白。输入TRACE(_T("[%s]\n"), m_d_lvlayers.GetString())。你看到了什么调试输出? 这里的根本问题是事件处理程序。 ON_CBN_DROPDOWN 事件处理程序在进行选择之前单击下拉菜单时启动。因此,我需要在进行选择后再次单击下拉列表,以便更新值。同样,ON_CBN_SELCHANGE 必须进行两次选择,但组合框在此处冻结。 使用ON_CBN_SELENDOK而不是ON_CBN_DROPDOWN,如果是下拉列表或简单的组合框,不要调用UpdateData【参考方案2】:

感谢@BarmakShemirani,我在ON_CBN_SELENDOK 事件处理程序中使用了他的代码来检索正确的字符串,而不是UpdateData(),现在它就像一个魅力

DDX:

void CThermalToolDlg::DoDataExchange(CDataExchange* pDX)

  DDX_CBString(pDX, IDC_LV_LAYERS, m_d_lvlayers);

消息映射:

BEGIN_MESSAGE_MAP(CThermalToolDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_CBN_SELENDOK(IDC_LV_LAYERS, &CThermalToolDlg::OnCbnSelendokLvLayers)
ON_BN_CLICKED(IDCANCEL, &CThermalToolDlg::OnBnClickedCancel)
ON_BN_CLICKED(ID_CALCULATE, &CThermalToolDlg::OnCalculate)
END_MESSAGE_MAP()

事件处理程序:

void CThermalToolDlg::OnCbnSelendokLvLayers()

    // TODO: Add your control notification handler code here
    CComboBox *cb = (CComboBox*)GetDlgItem(IDC_LV_LAYERS);
    if (cb)
    
        int sel = cb->GetCurSel();
        if (sel >= 0)
            cb->GetLBText(sel, m_d_lvlayers);
    
    TRACE(_T("[%s]\n"), m_d_lvlayers.GetString());

    /*UpdateData();*/

    if (m_d_lvlayers == "1")
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(0);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(0);
        GetDlgItem(IDC_LV2_PC)->EnableWindow(0);
        GetDlgItem(IDC_LV2_RESIN)->EnableWindow(0);
        GetDlgItem(IDC_LV2_RESO)->EnableWindow(0);
        GetDlgItem(IDC_LV2_INST)->EnableWindow(0);
        GetDlgItem(IDC_LV3_CU)->EnableWindow(0);
        GetDlgItem(IDC_LV3_ICI)->EnableWindow(0);
        GetDlgItem(IDC_LV3_PC)->EnableWindow(0);
        GetDlgItem(IDC_LV3_RESIN)->EnableWindow(0);
        GetDlgItem(IDC_LV3_RESO)->EnableWindow(0);
        GetDlgItem(IDC_LV3_INST)->EnableWindow(0);
        GetDlgItem(IDC_LV4_CU)->EnableWindow(0);
        GetDlgItem(IDC_LV4_ICI)->EnableWindow(0);
        GetDlgItem(IDC_LV4_PC)->EnableWindow(0);
        GetDlgItem(IDC_LV4_RESIN)->EnableWindow(0);
        GetDlgItem(IDC_LV4_RESO)->EnableWindow(0);
        GetDlgItem(IDC_LV4_INST)->EnableWindow(0);
        GetDlgItem(IDC_LVDUCTTYPE1)->EnableWindow(0);
        GetDlgItem(IDC_LVDUCTTYPE2)->EnableWindow(0);
        GetDlgItem(IDC_LVDUCTTYPE3)->EnableWindow(0);
        GetDlgItem(IDC_LV_D_NO_12)->EnableWindow(0);
        GetDlgItem(IDC_LV_D_NO_23)->EnableWindow(0);
        GetDlgItem(IDC_LV_D_NO_34)->EnableWindow(0);
    
    else if (m_d_lvlayers == "2")
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(1);
        GetDlgItem(IDC_LV2_PC)->EnableWindow(1);
        GetDlgItem(IDC_LV2_RESIN)->EnableWindow(1);
        GetDlgItem(IDC_LV2_RESO)->EnableWindow(1);
        GetDlgItem(IDC_LV2_INST)->EnableWindow(1);
        GetDlgItem(IDC_LV3_CU)->EnableWindow(0);
        GetDlgItem(IDC_LV3_ICI)->EnableWindow(0);
        GetDlgItem(IDC_LV3_PC)->EnableWindow(0);
        GetDlgItem(IDC_LV3_RESIN)->EnableWindow(0);
        GetDlgItem(IDC_LV3_RESO)->EnableWindow(0);
        GetDlgItem(IDC_LV3_INST)->EnableWindow(0);
        GetDlgItem(IDC_LV4_CU)->EnableWindow(0);
        GetDlgItem(IDC_LV4_ICI)->EnableWindow(0);
        GetDlgItem(IDC_LV4_PC)->EnableWindow(0);
        GetDlgItem(IDC_LV4_RESIN)->EnableWindow(0);
        GetDlgItem(IDC_LV4_RESO)->EnableWindow(0);
        GetDlgItem(IDC_LV4_INST)->EnableWindow(0);
        GetDlgItem(IDC_LVDUCTTYPE1)->EnableWindow(1);
        GetDlgItem(IDC_LVDUCTTYPE2)->EnableWindow(0);
        GetDlgItem(IDC_LVDUCTTYPE3)->EnableWindow(0);
        GetDlgItem(IDC_LV_D_NO_12)->EnableWindow(1);
        GetDlgItem(IDC_LV_D_NO_23)->EnableWindow(0);
        GetDlgItem(IDC_LV_D_NO_34)->EnableWindow(0);
    
    else if (m_d_lvlayers == "3")
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(1);
        GetDlgItem(IDC_LV2_PC)->EnableWindow(1);
        GetDlgItem(IDC_LV2_RESIN)->EnableWindow(1);
        GetDlgItem(IDC_LV2_RESO)->EnableWindow(1);
        GetDlgItem(IDC_LV2_INST)->EnableWindow(1);
        GetDlgItem(IDC_LV3_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV3_ICI)->EnableWindow(1);
        GetDlgItem(IDC_LV3_PC)->EnableWindow(1);
        GetDlgItem(IDC_LV3_RESIN)->EnableWindow(1);
        GetDlgItem(IDC_LV3_RESO)->EnableWindow(1);
        GetDlgItem(IDC_LV3_INST)->EnableWindow(1);
        GetDlgItem(IDC_LV4_CU)->EnableWindow(0);
        GetDlgItem(IDC_LV4_ICI)->EnableWindow(0);
        GetDlgItem(IDC_LV4_PC)->EnableWindow(0);
        GetDlgItem(IDC_LV4_RESIN)->EnableWindow(0);
        GetDlgItem(IDC_LV4_RESO)->EnableWindow(0);
        GetDlgItem(IDC_LV4_INST)->EnableWindow(0);
        GetDlgItem(IDC_LVDUCTTYPE1)->EnableWindow(1);
        GetDlgItem(IDC_LVDUCTTYPE2)->EnableWindow(1);
        GetDlgItem(IDC_LVDUCTTYPE3)->EnableWindow(0);
        GetDlgItem(IDC_LV_D_NO_12)->EnableWindow(1);
        GetDlgItem(IDC_LV_D_NO_23)->EnableWindow(1);
        GetDlgItem(IDC_LV_D_NO_34)->EnableWindow(0);
    
    else
    
        GetDlgItem(IDC_LV2_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV2_ICI)->EnableWindow(1);
        GetDlgItem(IDC_LV2_PC)->EnableWindow(1);
        GetDlgItem(IDC_LV2_RESIN)->EnableWindow(1);
        GetDlgItem(IDC_LV2_RESO)->EnableWindow(1);
        GetDlgItem(IDC_LV2_INST)->EnableWindow(1);
        GetDlgItem(IDC_LV3_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV3_ICI)->EnableWindow(1);
        GetDlgItem(IDC_LV3_PC)->EnableWindow(1);
        GetDlgItem(IDC_LV3_RESIN)->EnableWindow(1);
        GetDlgItem(IDC_LV3_RESO)->EnableWindow(1);
        GetDlgItem(IDC_LV3_INST)->EnableWindow(1);
        GetDlgItem(IDC_LV4_CU)->EnableWindow(1);
        GetDlgItem(IDC_LV4_ICI)->EnableWindow(1);
        GetDlgItem(IDC_LV4_PC)->EnableWindow(1);
        GetDlgItem(IDC_LV4_RESIN)->EnableWindow(1);
        GetDlgItem(IDC_LV4_RESO)->EnableWindow(1);
        GetDlgItem(IDC_LV4_INST)->EnableWindow(1);
        GetDlgItem(IDC_LVDUCTTYPE1)->EnableWindow(1);
        GetDlgItem(IDC_LVDUCTTYPE2)->EnableWindow(1);
        GetDlgItem(IDC_LVDUCTTYPE3)->EnableWindow(1);
        GetDlgItem(IDC_LV_D_NO_12)->EnableWindow(1);
        GetDlgItem(IDC_LV_D_NO_23)->EnableWindow(1);
        GetDlgItem(IDC_LV_D_NO_34)->EnableWindow(1);
    

谢谢大家!

【讨论】:

以上是关于哪个是 MFC C++ 中单选组合框的事件处理程序的主要内容,如果未能解决你的问题,请参考以下文章

如何获取 win32 c++ 应用程序中单选按钮的状态?

C ++ MFC更改单选框的背景颜色

java中如何判断是哪个单选框被选中了?

嵌套表单中单选按钮的 OnChange 事件

在java中性别是单选按钮,如何把性别添加到数据库中

MFC 在代码中增加单选按钮