MFC中CListBox调用GetCurSel求和结果异常问题求助
问题说明
学习C++ MFC开发时,需要实现获取两个ListBox控件选中项对应数值、相加后输出结果的功能,代码运行后输出异常值659998896,而非预期结果2,原代码如下:
BOOL CEngravingCalculatorDlg::OnInitDialog(){ CListBox* emplistbox1 = static_cast<CListBox*>(GetDlgItem(IDC_LIST1)); emplistbox1->AddString(L"1"); emplistbox1->SetCurSel(0); CListBox* emplistbox3 = static_cast<CListBox*>(GetDlgItem(IDC_LIST3)); emplistbox3->AddString(L"1"); emplistbox3->SetCurSel(0); } void CEngravingCalculatorDlg::OnBnClickedButton1() { CListBox* emplistbox1 = static_cast<CListBox*>(GetDlgItem(IDC_LIST1)); CListBox* emplistbox3 = static_cast<CListBox*>(GetDlgItem(IDC_LIST3)); int num1 = emplistbox1->GetCurSel(); int num2 = emplistbox3->GetCurSel(); int equal = num1 + num2; CString str; str.Format(_T("%d", equal)); GetDlgItem(IDC_Display)->SetWindowTextW(str); }
错误原因
代码存在两个核心问题:
- 接口理解错误:
CListBox::GetCurSel()返回值是当前选中项的索引(从0开始计数),不是选中项的文本内容,更不是文本对应的数值。就算代码运行正常,两个列表默认选中第一项(索引0),拿到的值是0+0=0,根本不可能得到1+1=2的预期结果。 - 初始化逻辑缺失导致未定义行为:原
OnInitDialog函数没有调用基类的OnInitDialog方法,也没有返回MFC要求的TRUE值,对话框控件没有完成MFC对象绑定和子类化,此时强制把GetDlgItem返回的临时CWnd*转成CListBox*调用成员函数,会读取错误内存地址,返回垃圾值,这就是异常大数659998896的来源。
修复方案
按照MFC的正确逻辑调整代码:
- 对话框初始化时先调用基类初始化方法,最后返回
TRUE保证控件正常创建。 - 先通过
GetCurSel()获取选中项的索引,判断索引有效性(不等于LB_ERR),避免未选中项时出错。 - 用获取到的索引调用
GetText()拿到列表项的文本内容,再转换成整数做计算。 - 最后把计算结果格式化成字符串输出。
修复后的完整代码:
BOOL CEngravingCalculatorDlg::OnInitDialog(){ // 必须先调用基类初始化,完成控件绑定 CDialogEx::OnInitDialog(); CListBox* emplistbox1 = static_cast<CListBox*>(GetDlgItem(IDC_LIST1)); emplistbox1->AddString(L"1"); emplistbox1->SetCurSel(0); CListBox* emplistbox3 = static_cast<CListBox*>(GetDlgItem(IDC_LIST3)); emplistbox3->AddString(L"1"); emplistbox3->SetCurSel(0); // 必须返回TRUE,MFC对话框初始化要求 return TRUE; } void CEngravingCalculatorDlg::OnBnClickedButton1() { CListBox* emplistbox1 = static_cast<CListBox*>(GetDlgItem(IDC_LIST1)); CListBox* emplistbox3 = static_cast<CListBox*>(GetDlgItem(IDC_LIST3)); // 获取选中项索引 int selIndex1 = emplistbox1->GetCurSel(); int selIndex2 = emplistbox3->GetCurSel(); // 校验选中状态 if (selIndex1 == LB_ERR || selIndex2 == LB_ERR) { GetDlgItem(IDC_Display)->SetWindowTextW(L"请先选中两个列表的选项"); return; } // 根据索引获取项的文本内容 CString strVal1, strVal2; emplistbox1->GetText(selIndex1, strVal1); emplistbox3->GetText(selIndex2, strVal2); // 文本转整数后计算 int num1 = _wtoi(strVal1); int num2 = _wtoi(strVal2); int res = num1 + num2; CString strShow; strShow.Format(_T("%d"), res); GetDlgItem(IDC_Display)->SetWindowTextW(strShow); }
注意事项
- MFC对话框的
OnInitDialog生命周期函数必须优先调用基类实现,否则所有控件相关操作都可能出现异常。 GetCurSel调用失败时会返回LB_ERR(值为-1),实际开发中必须做返回值校验,避免空选时程序逻辑出错。- 如果列表项内容不是纯数字,转整数前需要做合法性判断,避免
_wtoi转换失败得到错误值。
内容的提问来源于stack exchange,提问作者Unknown
相关产品推荐
相关产品推荐

