0

I am having trouble in enabling or disabling certain text boxes on selection of a particular combobox.

I have tried using OnCbnSelChangeLvLayers() & OnCbnDropdownLvLayers(). The problem with the first event handler is I have to click on the same value twice and the selection in the combobox frezees. The second event handler solves the problem of freezing but I have to click on the dropdown of combobox in order for the event to occur. I also tried a few other event handlers for combobox but was not successful. m_d_layers is the string variable for the combobox selection (1,2,3,4)

DDX:

void CThermalToolDlg::DoDataExchange(CDataExchange* pDX)
{
    DDX_CBString(pDX, IDC_LV_LAYERS, m_d_lvlayers);
}

Message Map:

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()

Event Handler:

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
    }
}

I want to obtain the desired enabling/disabling in a single click without freezing of the combobox. Is there any other way or faster method for the same?

  • how about the 1st answer to this question: https://stackoverflow.com/questions/698910/catching-when-user-selects-an-item-from-a-ccombobox ? – Sami Sallinen May 09 '19 at 05:22
  • @SamiSallinen Thanks for guiding me towards the question. It aligns with my question, however the solution of the two event handlers (SELENDOK & EDITUPDATE) is not working and the code jumps to else loop always. I dont know what I may be doing wrong. –  May 09 '19 at 05:41
  • 1
    Your code is terrible: the only case that is different from all others is the case "1". That being said: you need to add a picture that show what controls IDC_LV2_CU and IDC_LV2_ICI are. – Jabberwocky May 09 '19 at 07:36
  • @Jabberwocky The cases are different I have just not mentioned all the conditions. IDC_LV2_CU and IDC_LV2_ICI are few of the textboxes (there are many more) which need to be enabled or disabled according to 4 selections. The issue here is updating the value of combobox in the class file in a single click. –  May 09 '19 at 10:09
  • 1
    Show your message map (`BEGIN_MESSAGE_MAP...`) as well as the definition for `CThermalToolDlg::DoDataExchange`. If you have `OnCbnEditUpdate` and other combobox related handler then show their definition as well. Usually you just need to handle `ON_CBN_SELCHANGE` – Barmak Shemirani May 09 '19 at 21:58
  • @BarmakShemirani Edited my code. I havent used `OnCbnEditUpdate` in my code apart from where solution was mentioned by @SamiSallinen in the first comment –  May 10 '19 at 07:52

2 Answers2

0

This seems to be a bug for drop-list combobox and simple combobox (not drop-down). DDX_CBString or DDX_CBStringExact do not retrieve the right value in response to ON_CBN_DROPDOWN.

You can use your own code to retrieve the correct string:

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());
}

For debugging purposes, comment out other messages except ON_CBN_DROPDOWN(IDC_LV_LAYERS...). Make sure you have the correct string before proceeding any further.

Do not call UpdateData(FALSE) as you have done in your previous question. This can cause problems specially if the correct string is not being retrieved.

Barmak Shemirani
  • 30,904
  • 6
  • 40
  • 77
  • This is a correct method to retrieve the correct string, but still on the selection of a value in combobox debugs to the else loop in `void CThermalToolDlg::OnCbnDropdownLvLayers()` Should I add a seperate event handler for conditions? –  May 13 '19 at 10:09
  • I am not sure about the underlying problem. Maybe there is a blank space somewhere. Put `TRACE(_T("[%s]\n"), m_d_lvlayers.GetString())`. What debug output do you see? – Barmak Shemirani May 13 '19 at 11:45
  • The underlying problem here is the event handler. `ON_CBN_DROPDOWN` event handler starts when the dropdown is clicked before making the selection. Hence I need to click on the dropdown once again after making the selection so that the value is updated. Similarly for `ON_CBN_SELCHANGE` the selection has to be made twice, but the combobox freezes here. –  May 14 '19 at 03:58
  • 1
    Use `ON_CBN_SELENDOK` instead of `ON_CBN_DROPDOWN`, and don't call `UpdateData` if it's a drop-list or simple combobox. – Barmak Shemirani May 14 '19 at 04:10
0

Thanks to @BarmakShemirani I used his code of retrieving the correct string instead of UpdateData() in ON_CBN_SELENDOK event handler and now it works like a charm

DDX:

void CThermalToolDlg::DoDataExchange(CDataExchange* pDX)
{
  DDX_CBString(pDX, IDC_LV_LAYERS, m_d_lvlayers);
}

Message Map:

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()

Event Handler:

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);
    }
}

Thanks everyone!