CListCtrl::InsertColumn出错

本文介绍了一个关于在CPropertyPage构造函数中调用CListCtrl::InsertColumn方法导致运行时出现DebugAssertionFailed的问题及解决方法。作者通过调试发现错误原因是控件尚未创建,最终将InsertColumn方法移至OnInitDialog()中成功解决问题。

今天在写一个获取磁盘信息的小程序,通过list控件显示各磁盘信息。我在属性页(CPropertyPage)的构造函数中,调用list控件的InsertColumn方法,编译链接都通过了,但运行时冒出了一个Debug Assertion Failed!提示

 

 

 

我就改用调试方式运行,再弹出该对话框时,选择重试,最后程序中断指向了

_AFXCMN_INLINE int CListCtrl::InsertColumn(int nCol, const LVCOLUMN* pColumn)
 { ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, LVM_INSERTCOLUMN, nCol, (LPARAM)pColumn); }

其中,m_hWnd为0x00000000

监视(watch)窗口的 @err,hr(即,GetLastError)为

 @err,hr 0x00000578 无效的窗口句柄。  unsigned long

 

起初,我没在意m_hWnd和@err,hr的值,只是看到出错点是CListCtrl::InsertColumn就上网查。不过网上有关调用CListCtrl::InsertColumn出错的文章很少!但有个帖子模模糊糊提到了可能是窗体类还没创建引起的错误。后来我再用调试运行执行程序,执行来到刚刚出错的地方,发现SendMessage的m_hWnd为0x00000000,说明此时list控件还没有创建。

我是在属性页(CPropertyPage)的构造函数中调用InsertColumn的,CPropertyPage为窗体,继承于CDialog。程序执行到CPropertyPage构造函数时,属性页还没创建完成,其中的控件也还没创建完成,在调用InsertColumn时,向list控件发送一个LVM_INSERTCOLUMN消息,但由于list控件还没有创建,才会引起无效的窗口句柄错误!将InsertColumn方法放在CPropertyPage::OnInitDialog()中调用,问题就解决了!

 

要是刚开始我注意了m_hWnd或 @err,hr的值,问题很快就能解决!看来要好好改改思维习惯了

 

@err,hr是我从《Windows核心编程》学到的一个技巧,它的功能等同于GetLastError,但使用起来比GetLastError方便多了!只要程序调试时在监视(watch)窗口,加上一项@err,hr,就能查看到每一步调试运行时的Error Code,并且有对Error Code的文本描述。而不需要在程序中加入GetLastError代码来获取Error Code,再用Error Lookup工具将Error Code转换成相应的文本描述!不过@err,hr不是每个IDE都支持的,我试过vc++6.0 sp6用不了,vs2005就可以!

二元“=”: 没有找到接受“CString”类型的右操作数的运算符(或没有可接受的转换) 空初始值设定项对于带有未指定绑定的数组无效 “_AFXDLL”: 宏重定义 'CWinApp::Enable3dControls': CWinApp::Enable3dControls is no longer needed. You should remove this call. “CListCtrl::InsertColumn: 没有重载函数可以转换所有参数类型 “CListCtrl::InsertColumn: 没有重载函数可以转换所有参数类型 “CListCtrl::InsertColumn: 没有重载函数可以转换所有参数类型 “CListCtrl::InsertColumn: 没有重载函数可以转换所有参数类型 “CListCtrl::InsertColumn: 没有重载函数可以转换所有参数类型 “CListCtrl::InsertColumn: 没有重载函数可以转换所有参数类型 “BOOL CListCtrl::SetItemText(int,int,LPCTSTR)”: 无法将参数 3 从“const char [3]”转换为“LPCTSTR” “BOOL CListCtrl::SetItemText(int,int,LPCTSTR)”: 无法将参数 3 从“const char [3]”转换为“LPCTSTR” 二元“=”: 没有找到接受“CString”类型的右操作数的运算符(或没有可接受的转换) 二元“=”: 没有找到接受“CString”类型的右操作数的运算符(或没有可接受的转换) 二元“=”: 没有找到接受“CString”类型的右操作数的运算符(或没有可接受的转换) 二元“=”: 没有找到接受“CString”类型的右操作数的运算符(或没有可接受的转换) 二元“=”: 没有找到接受“CString”类型的右操作数的运算符(或没有可接受的转换) “int CWnd::MessageBoxW(LPCTSTR,LPCTSTR,UINT)”: 无法将参数 1 从“const char [15]”转换为“LPCTSTR” “int CWnd::MessageBoxW(LPCTSTR,LPCTSTR,UINT)”: 无法将参数 1 从“const char [15]”转换为“LPCTSTR” “int CWnd::MessageBoxW(LPCTSTR,LPCTSTR,UINT)”: 无法将参数 1 从“const char [15]”转换为“LPCTSTR”
03-24
<think>好的,用户遇到了MFC/C++的编译错误,涉及CString、CListCtrl、MessageBoxW等方法调用的问题。我需要一步步分析错误原因并提供解决方案。 首先,常见的错误类型是参数类型不匹配,比如将const char*传递给需要LPCTSTR或const wchar_t*的地方。这可能是因为项目使用了Unicode字符集,而代码中使用了ANSI字符串。例如,CListCtrlInsertColumn和SetItemText方法需要LPCTSTR类型的参数,而如果直接传递字符串字面量如"姓名",会导致错误,因为"姓名"是const char*,而LPCTSTR在Unicode下是wchar_t*。 接下来,用户提到的Enable3dControls过时的问题。查阅资料后发现,在较新的MFC版本中,这个函数可能已被废弃,需要移除或替换。同时,_AFXDLL宏重定义可能源于头文件重复包含或项目配置问题,需要检查包含顺序和预处理器定义。 解决方案方面,首先处理字符串转换问题。使用_T()或_TEXT()宏包裹字符串字面量,将它们转换为适合当前字符集的LPCTSTR。例如,将"姓名"改为_T("姓名")。对于CString的格式化,应使用CString::Format方法,并确保格式字符串使用正确的类型,如%ls用于宽字符。 关于CListCtrl的方法参数,检查InsertColumn和SetItemText的调用,确保所有字符串参数正确转换为LPCTSTR。例如,SetItemText的参数可能需要使用(LPCTSTR)strText进行强制转换,或者直接传递CString对象,因为CString有隐式转换操作符。 对于Enable3dControls,建议直接注释掉相关代码,因为新版本MFC不再需要它。_AFXDLL宏的问题可能需要检查项目设置,确保正确使用MFC库,并避免手动定义该宏。 此外,处理MessageBoxW的调用时,确保字符串参数为宽字符。例如,使用L"标题"或CString的AllocSysString方法。 最后,检查所有涉及字符串处理的地方,统一使用TCHAR类型和相关的宏,以确保代码在Unicode和多字节字符集下的兼容性。例如,使用_tcscpy代替strcpy,_stprintf代替sprintf等。 总结步骤:调整字符串字面量使用_T宏,正确使用CString的Format方法,强制转换或隐式转换CString到LPCTSTR,更新过时函数,检查项目字符集设置,确保使用正确的字符类型处理函数。同时,提供示例代码帮助用户理解修改方式,并提醒注意事项如字符集设置和宽字符处理。</think>### MFC/C++编译错误解决方案 针对MFC中涉及$CString$、$CListCtrl$、$MessageBoxW$等类的编译错误,以下是分步解决方案: --- #### **1. 字符串类型转换问题** **错误示例**:`error C2664: 不能将参数1从"const char *"转换为"LPCTSTR"` **原因**:MFC默认使用Unicode字符集(`LPCTSTR`对应`const wchar_t*`),但代码中使用了ANSI字符串(`const char*`)[^1][^4]。 **解决方案**: - 使用`_T()`或`_TEXT()`宏包裹字符串字面量: ```cpp // 错误写法 m_list.InsertColumn(0, "姓名", LVCFMT_LEFT, 100); // 正确写法 m_list.InsertColumn(0, _T("姓名"), LVCFMT_LEFT, 100); ``` - 若需动态生成字符串,使用`CString::Format`并显式转换类型: ```cpp CString str; str.Format(_T("%d"), 123); // 使用_T包裹格式字符串 MessageBox(str, _T("提示"), MB_OK); ``` --- #### **2. CListCtrl方法参数类型不匹配** **错误示例**:`SetItemText`或`InsertColumn`参数类型错误 **原因**:`CListCtrl`方法要求`LPCTSTR`类型参数,但传递了`CString`或`char*`[^2][^3]。 **解决方案**: - 显式转换`CString`为`LPCTSTR`: ```cpp CString strItem = _T("内容"); m_list.SetItemText(0, 0, (LPCTSTR)strItem); // 强制类型转换 ``` - 或直接利用`CString`隐式转换特性: ```cpp m_list.InsertColumn(1, strHeader, LVCFMT_LEFT, 80); // CString自动转为LPCTSTR ``` --- #### **3. MessageBoxW的宽字符支持** **错误示例**:`MessageBoxW`参数类型不匹配 **原因**:`MessageBoxW`是Unicode版本,要求`LPCWSTR`(宽字符)参数。 **解决方案**: - 使用`L`前缀定义宽字符字符串: ```cpp MessageBoxW(NULL, L"这是一个Unicode消息", L"标题", MB_OK); ``` - 或通过`CString`转换: ```cpp CString strMsg = _T("消息内容"); MessageBoxW(NULL, strMsg.AllocSysString(), L"标题", MB_OK); ``` --- #### **4. 废弃函数与宏定义问题** **错误示例**:`Enable3dControls`已过时、`_AFXDLL`宏冲突 **解决方案**: - **移除废弃函数**: ```cpp // 删除或注释以下代码 Enable3dControls(); Enable3dControlsStatic(); ``` - **避免宏重定义**: - 检查项目属性中的预处理器定义,移除手动添加的`_AFXDLL`[^3]。 - 确保包含头文件顺序正确(如`stdafx.h`在首位)。 --- #### **5. 文件操作兼容性问题** **错误示例**:`fopen`参数类型不匹配 **原因**:`fopen`要求`const char*`,但传递了`LPCTSTR`(Unicode下为`wchar_t*`)[^4][^5]。 **解决方案**: - 使用`_tfopen`替代`fopen`(兼容多字符集): ```cpp FILE* pFile = _tfopen(_T("data.txt"), _T("r")); // 自动适配ANSI/Unicode ``` --- ### **示例修正代码** ```cpp // 初始化列表控件 CListCtrl m_list; m_list.InsertColumn(0, _T("姓名"), LVCFMT_LEFT, 100); m_list.InsertColumn(1, _T("年龄"), LVCFMT_LEFT, 80); // 添加数据 CString strName = _T("张三"); CString strAge; strAge.Format(_T("%d"), 25); m_list.InsertItem(0, strName); m_list.SetItemText(0, 1, strAge); // 弹窗提示 MessageBox(_T("操作成功"), _T("提示"), MB_OK); ``` --- ### **注意事项** 1. **字符集设置**:在项目属性中确认字符集为**Unicode**或**多字节**,保持代码一致性。 2. **类型安全**:优先使用`CString`代替`char*`或`wchar_t*`,避免强制转换。 3. **宽字符处理**:涉及API调用时,显式使用`L`前缀或`_T`宏。 ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值