MFC中一个容易被忽视的问题

   MFC对话框模式的程序经常有这样一种业务需求:

      对话框初始化 --> 取得数据 --> 将数据显示到对话框的控件中

   该流程有一个潜在的问题,看下面的代码:
BOOL CTestDlg::OnInitDialog()
{
    CDialog::OnInitDialog();
    
// TODO: Add extra initialization here

    
// Get data here
    char* szData = GetData();

    
// Set Ctrl value here
    GetDlgItem(IDC_SOMEEDITCTRL)->SetWindowText(szData);

    
return TRUE;
}

   这样的代码编译出來的程序运行起来有时会CRUSH,有时不会,调试起来很让人头痛。
   错误出在“GetDlgItem(IDC_SOMEEDITCTRL)->SetWindowText(szData);”这一句,这行代码是在对话框初始化时调用的,此时对话框资源有可能还没有创建起来,因此GetDlgItem(IDC_SOMEEDITCTRL)有可能得到的就是空指针,也有可能得到的是非空却被判断为非窗口的指针。遇上这两种情况,程序当然就CRUSH掉了。
   这样精简的代码当然很容易看出问题来,但是如果程序规模大了,资源多了,又有嵌套调用等等,发生这样的错误就很难检查出來。

   解决的方法有很多,一定要确保在InitDialog结束之后再对控件资源进行操作。最简单的方法是在InitDialog结束的时候PostMessage,然后在消息处理里面处理资源操作。


posted on 2007-12-12 10:48 迷宫の未来 阅读(2034) 评论(11)  编辑 收藏 引用

评论

# re: MFC中一个容易被忽视的问题 2007-12-12 13:01 LOGOS

不错。这个问题确实比较容易被忽视  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-12 15:49 agaric

既然是MFC,基本上都会映射成一个成员变量来操作吧,就不会这么麻烦咯  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-12 16:44 不懂

有这种问题??

没遇到过,是你们使用的有问题吧,如果MFC有这种不确定性的问题,早就应该发现了吧。  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-13 13:18 vc

'有时会CRUSH'?能给个代码能crush的吗?有兴趣深入看一下  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-14 13:53 追梦时代

@vc
我做的是一个控制面板程序,之前会CRUSH掉的部分代码如下:
BOOL CStockF10SetDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// TODO: Add extra initialization here
//Init contrl data
.......
//获得注册表的值
if(GetRegValues())
{
//更新没有值绑定的控件的显示
SetCtrlState();
//更新有值绑定的控件的显示
UpdateData(FALSE);
}
else
{
MessageBox("Get regedit values error!");
}
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}


void CStockF10SetDlg::SetCtrlState()
{
//EnableForceSend
......
szTemp.Format("%02ld",gethour(m_nUpdateTime));
//将m_nUpdateTime这个时间值的小时部分显示到控件
GetDlgItem(IDC_UPDATETIMEH)->SetWindowText(szTemp);
szTemp.Format("%02ld",getminute(m_nUpdateTime));
//将m_nUpdateTime这个时间值的分钟部分显示到控件
GetDlgItem(IDC_UPDATETIMEM)->SetWindowText(szTemp);
}


由于这个时间值我把它放在小时和分钟两个控件中显示,所以没有绑定成员变量,直接通过资源号来显示数据的。代码运行到SetWindowText这里会CRUSH掉。   回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-15 22:03 Zero Lee

提到的问题,确实很有意思,没遇到过。前不久做的一个项目中,写的代码与“追梦时代”的操作差不多,在VS2003.net和VS2005下不管哪种模式都没有出现这种问题啊。  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-18 10:25 力为

GetDlgItem(IDC_UPDATETIMEH)->SetWindowText(szTemp);
这种写法本身就得挨批~  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-25 22:05 秦歌

这种情况不好说  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2007-12-28 14:56 123

@力为
94  回复  更多评论   

# re: MFC中一个容易被忽视的问题[未登录] 2007-12-29 11:32

这行代码是在对话框初始化时调用的,此时对话框资源有可能还没有创建起来,
---------------------------
收到 WM_INITDIALOG, 则对话框和子窗口已经创建起来
执行CDialog::OnInitDialog()之后, 则控件和变量已经关联起来(如果有的话)
这个是肯定的

至于楼主为什么会CRUSH,,,,,,奇怪....
除非GetDlgItem(IDC_SOMEEDITCTRL) 中的ID对应的控件不存在

  回复  更多评论   

# re: MFC中一个容易被忽视的问题 2008-11-16 12:57 vane

至于楼主为什么会CRUSH,,,,,,奇怪....
除非GetDlgItem(IDC_SOMEEDITCTRL) 中的ID对应的控件不存在
控件没创建好,返回的是一个空指针GetDlgItem返回值是一个CWnd*
我们可以这样CWnd *pWnd = GetDlgItem(IDC_SOMEEDITCTRL);
if(pWnd->GetSafeHwnd())
{
..................
}

这就不会造成崩溃 但是,有可能那个控件没数据  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2007年12月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

导航

统计

常用链接

留言簿(10)

随笔档案

文章档案

最新随笔

搜索

积分与排名

最新随笔

最新评论

阅读排行榜

评论排行榜