从全局函数访问对话框控件时IsDlgButtonChecked始终为true的问题
问题解决与说明
复选框状态判断错误的原因及修复
错误根源
你代码里CMeetSetup MeetSetup;是新建了一个CMeetSetup类的实例,这个实例和当前显示的对话框完全无关,它的m_hWnd是未初始化的无效句柄。调用IsDlgButtonChecked时传入无效句柄,返回值是未定义的,所以才会出现无论复选框是否勾选都返回true的情况。正确的实现方式
- 你需要拿到当前正在显示的对话框实例的指针或句柄,而不是新建一个实例。
- 方法一:如果线程是从对话框类内部启动的,可以把对话框的
this指针作为参数传递给线程函数。比如启动线程时:
然后在线程函数里:AfxBeginThread(YourGlobalThreadFunc, this);UINT YourGlobalThreadFunc(LPVOID pParam) { CMeetSetup* pDlg = static_cast<CMeetSetup*>(pParam); if (pDlg->IsDlgButtonChecked(IDC_LANE1) == BST_CHECKED) { // 复选框被勾选的逻辑 } return 0; } - 方法二:如果无法直接传递指针,也可以通过对话框的类名或标题查找窗口句柄(不推荐,容易出错):
HWND hDlg = FindWindow(_T("#32770"), _T("你的对话框标题")); if (hDlg != NULL && IsDlgButtonChecked(hDlg, IDC_LANE1) == BST_CHECKED) { // 逻辑处理 } - 注意:MFC的窗口对象和句柄是绑定的,跨线程访问窗口时,最好用
SendMessage或PostMessage来发送消息,让对话框自己处理状态判断,避免直接跨线程访问窗口控件(MFC不是线程安全的)。比如给对话框发送自定义消息,对话框收到消息后自己判断复选框状态并处理。
关于线程是否必须为全局的问题
线程函数不需要是全局的,你可以把它定义为对话框类的静态成员函数,这样既可以访问类的静态成员,也能通过传入的对话框指针访问非静态成员。示例:
class CMeetSetup : public CDialogEx { public: static UINT ThreadFunc(LPVOID pParam); // ...其他成员 }; UINT CMeetSetup::ThreadFunc(LPVOID pParam) { CMeetSetup* pDlg = static_cast<CMeetSetup*>(pParam); // 这里可以访问pDlg的成员 return 0; } // 启动线程时 AfxBeginThread(&CMeetSetup::ThreadFunc, this);
内容的提问来源于stack exchange,提问作者user2325432
相关产品推荐
相关产品推荐

