MFC模式对话框ESCAPE和ENTER退出问题 mfc打开文件对话框

在Windows开发中弹出对话框是一种常用的输入/输出手段,同时编辑好的对话框可以保存在资源文件中。VisualC++提供了对话框编辑工具,利用编辑工具可以方便的添加各种控件到对话框中,而且利用ClassWizard可以方便的生成新的对话框类和映射消息。

首先资源列表中按下右键,可以在弹出菜单中选择“插入对话框”。然后再打开该对话框进行编辑,你会在屏幕上看到一个控件板。你可以将所需要添加的控件拖到对话框上,或是先选中后再在对话框上用鼠标画出所占的区域。
对于有模式对话框使用DoModal()产生,对于无模式对话框使用Create()产生。相关实例代码如下;
void CMy51_s1View::OnCreateDlg()
{//产生无模式对话框
CTestDlg *dlg=new CTestDlg;
dlg->Create(IDD_TEST_DLG);
dlg->ShowWindow(SW_SHOW);
}

void CMy51_s1View::OnDoModal()
{//产生有模式对话框
CTestDlg dlg;
int iRet=dlg.DoModal();
TRACE("dlg return %d/n",iRet);
}

如果你在调试这个程序时你会发现程序在退出后会有内存泄漏,这是因为没有释放无模式对话框所使用的内存。

关于在使用对话框时Enter键和Escape键的处理:在使用对话框是你会发现当你按下Enter键或Escape键都会退出对话框,这是因为Enter键会引起CDialog::OnOK()的调用,而Escape键会引起CDialog::OnCancel()的调用。而这两个调用都会引起对话框的退出。在MFC中这两个成员函数都是虚拟函数,所以我们需要进行重载,如果我们不希望退出对话框那么我们可以在函数中什么都不做,如果需要进行检查则可以添加检查代码,然后调用父类的OnOK()或OnCancel()。相关代码如下;

void CTestDlg::OnOK()
{
AfxMessageBox("你选择确定");
CDialog::OnOK();
}

void CTestDlg::OnCancel()
{
AfxMessageBox("你选择取消");
CDialog::OnCancel();
}

2 创建有模式对话框

使用有模式对话框时在对话框弹出后调用函数不会立即返回,而是等到对话框销毁后才会返回(请注意在对话框弹出后其他窗口的消息依然会被传递)。所以在使用对话框时其他窗口都不能接收用户输入。创建有模式对话框的方法是调用CDialog::DoModal()。下面的代码演示了这种用法:

CYourView::OnOpenDlg()
{
CYourDlg dlg;
int iRet=dlg.DoModal();
}

CDialog::DoModal()的返回值为IDOK,IDCANCEL。表明操作者在对话框上选择“确认”或是“取消”。由于在对话框销毁前DoModal不会返回,所以可以使用局部变量来引用对象。在退出函数体后对象同时也会被销毁。而对于无模式对话框则不能这样使用,下节3创建无模式对话框中会详细讲解。

你需要根据DoModal()的返回值来决定你下一步的动作,而得到返回值也是使用有模式对话框的一个很大原因。

使用有模式对话框需要注意一些问题,比如说不要在一些反复出现的事件处理过程中生成有模式对话框,比如说在定时器中产生有模式对话框,因为在上一个对话框还未退出时,定时器消息又会引起下一个对话框的弹出。

同样的在你的对话框类中为了向调用者返回不同的值可以调用CDialog::OnOK()或是CDialog::OnCancel()以返回IDOK或IDCANCEL,如果你希望返回其他的值,你需要调用
CDialog::EndDialog( int nResult);其中nResult会作为DoModal()调用的返回值。
MFC模式对话框ESCAPE和ENTER退出问题 mfc打开文件对话框

下面的代码演示了如何使用自己的函数来退出对话框:

void CMy52_s1View::OnLButtonDown(UINT nFlags, CPointpoint)
{//创建对话框并得到返回值
CView::OnLButtonDown(nFlags, point);
CTestDlg dlg;
int iRet=dlg.DoModal();
CString szOut;
szOut.Format("return value %d",iRet);
AfxMessageBox(szOut);
}
//重载OnOK,OnCancel
void CTestDlg::OnOK()
{//什么也不做
}
void CTestDlg::OnCancel()
{//什么也不做
}
//在对话框中对三个按钮消息进行映射
void CTestDlg::OnExit1()
{
CDialog::OnOK();
}
void CTestDlg::OnExit2()
{
CDialog::OnCancel();
}
void CTestDlg::OnExit3()
{
CDialog::EndDialog(0XFF);
}

由于重载了OnOK和OnCancel所以在对话框中按下Enter键或Escape键时都不会退出,只有按下三个按钮中的其中一个才会返回。点击窗口右上角红色x按钮回产生OnClose事件,可以在这里实现退出。

此外在对话框被生成是会自动调用BOOLCDialog::OnInitDialog(),你如果需要在对话框显示前对其中的控件进行初始化,你需要重载这个函数,并在其中填入相关的初始化代码。利用ClassWizard可以方便的产生一些默认代码,首先打开ClassWizard,选择相应的对话框类,在右边的消息列表中选择WM_INITDIALOG并双击,如图,ClassWizard会自动产生相关代码,代码如下:

BOOL CTestDlg::OnInitDialog()
{

CDialog::OnInitDialog();

return TRUE;
}



其实大家都明白,想要解决这个问题,其实有两种思路:

1、处理PreTranslateMessage函数,将消息为ESC和ENTER的都过滤掉,如直接返回或替换为WM_RETURN等。但是这个不太推荐。

2、重载OnOk(),OnCancel()函数,(这是根本的重点的解决办法)

对于很熟悉VC的同学来说不难,但是初入门的在网上看到的都是如何如何的办法,没有将新手最迫切的问题解决了:如何重载?

首先,MFC创建的Dialog在按下默认的确定(OK)和取消(CANCEL)按钮时都点用了父窗口的OnOk()和OnCancel()函数,他们的区别:

第一,OnOK()和OnCancel()是CDialog基类的成员函数,而OnClose()和OnDestroy()是CWnd基类的成员函数,即WM消息响应函数。从应用程序结构的角度,拿对话框来说,红色的X对应的是CWnd,而处于对话框中的“确定”、“取消”按钮则对应了CDialog。

第二,OnClose()和OnDestroy()

在单视图程序中,根据<<深入浅出MFC>>所讲,程序退出时执行的操作顺序为(从点X按钮开始)
(1)用户点击X退出按钮,发送了WM_CLOSE消息----->响应OnClose()
(2)在WM_CLOSE消息的处理函数中,调用DestroyWindow()----->销毁与指定CWnd窗口对象关联的窗口,但未销毁CWnd对象
(3)在DestroyWindow()中发送了WM_DESTROY消息----->窗口销毁后响应OnDestroy()
(4)在WM_DESTROY消息中调用PostQuitMessage(),发送WM_QUIT消息,结束消息循环

可以看到,程序的退出过程,是先响应OnClose(),然后响应OnDestroy(),在响应OnDestroy()之前,窗口对象已经被销毁。OnDestroy()到底干了什么呢?它就像一个teller,先通知CWnd对象告诉它即将被销毁,尔后OnDestroy的真正运行是在CWnd对象已经从屏幕上清除以后被调用的。

第三,OnOK()、OnCancel()()、OnClose()、OnDestroy()

CDialog::OnOK首先调用UpdateData(TRUE)将数据传给对话框成员变量,然后调用CDialog::EndDialog关闭对话框;
CDialog::OnCancel只调用CDialog::EndDialog关闭对话框;
OnClose()是响应WM_CLOSE的.一定程度上可以说CDialog::EndDialog()和OnClose()完成类似的工作,但处理的机制不一样,前者是CDialog的对象机制,后者是WM的消息映射机制。

CDialog::EndDialog()-------->OnDestroy()

OnClose()-------->OnDestroy()

EndDialog()和OnClose()属于“同级别”的,所以我们在按下OK按钮的时候,程序是不会执行OnClose()的,但两种机制都必须经过OnDestroy()

对于按键:

按esc只会调用OnCancel()

按alt+f4会先调用OnClose()后调用OnCancel()
按X或关闭按扭时会先调用OnClose()后调用OnCancel()


**********************************************************************************


重载OnOK,OnCancel函数,下面的这种方式不是很正确:

protected:
virtual void OnCancel();
virtual void OnOK();


void CDialog::OnOK()
{
// TODO: 在此添加专用代码和/或调用基类

//CDialog::OnOK();
}
.....

**********************************************************

其实也没啥太大的错误,最大的错误是重载了CDialog的OnOk,OnCancel方法,这样的话是对于父窗口的正常使用有潜在的危险,并且经实践有时候并不能够达到原有的目的。最正确的方法是重载CXXXDlg(即我们需要处理的窗口)的对应方法,这样就很完美了。

一般来说,我们需要不但需要重载OnOk(),OnCancel(),而且需要重新相应WM_CLOSE消息,其中WM_CLOSE消息相应很重要,如果不这么做你就不能通过X以及各种正常的方式关闭对话框。

所以一般这么做:

[cpp]viewplaincopy
  1. //CXXXDlg.h中
  2. protect://public也没错
  3. virtualvoidOnOk();
  4. virtualvoidOnCancel();
  5. //CXXXDlg.cpp中
  6. voidCXXXDlg::OnOk()//啥也不做就OK了
  7. {
  8. }
  9. voidCXXXDlg::OnCancel()//同上
  10. {
  11. }

然后Add window message Handle,选则WM_CLOSE消息,添加并编辑,在消息响应中函数中添加

Enddialog(IDCANCEL);//参数可以自己根据需要填写

如,我的项目名叫CDlgDrawTool,代码如下:

[cpp]viewplaincopy
  1. voidCDlgDrawTool::OnCancel()//回车按钮处理
  2. {
  3. }
  4. voidCDlgDrawTool::OnOK()//ESC按钮不处理
  5. {
  6. }
  7. voidCDlgDrawTool::OnClose()//X按钮处理
  8. {
  9. //TODO:Addyourmessagehandlercodehereand/orcalldefault
  10. EndDialog(IDCANCEL);//关闭窗口
  11. CDialog::OnClose();
  12. }


这样,你的对话框就可以正常使用了!




  

爱华网本文地址 » http://www.413yy.cn/a/25101010/21735.html

更多阅读

安卓手机recovery模式刷入教程 安卓退出recovery模式

安卓手机recovery模式刷入教程——简介Recovery类似于电脑上的小型winPE系统,或者说类似于品牌机的一键还原恢复系统。Recovery的使用原理就和电脑上的GHOST软件一样,起系统备份与还原作用,当然也可以升级内核、刷补丁等。解锁了HBOOT

Game Center如何关闭、登入和注销退出 注销game center账户

Game Center如何关闭、登入和注销退出——简介Game Center是苹果中的游戏中心,用户可以在这里和其他玩家进行比拼和交流,完成游戏中的成就,和全球的玩家一起排名,和朋友一起玩游戏,现在就教大家怎样关闭Game Center和登入,注销退出的方法

FC5和FC6使用问题 fc问题

FC5和FC6使用问题 boogline,2012-02-22 18:57:07程序中,在通讯设置中,设置了IS0_on_TCP的连接方式,LADDR 的地址分别是PLC1——W#16#0120 和 PLC2——W#16#0140,ID是1 。两个PLC程序块中也分别添加了SFC58 和 SFC 59PLC1中的程序段如下:C

声明:《MFC模式对话框ESCAPE和ENTER退出问题 mfc打开文件对话框》为网友江畔旧时月分享!如侵犯到您的合法权益请联系我们删除