MFC中解决回车和ESC关闭的问题,重载OnOk(),OnCancel()函数的正确做法_mfc onok函数_Phenixyf的博客-程序员资料

技术标签: VC++ 常用类、方法、函数、关键字  VC++  VC++ 基本概念与应用  

本文参考了如下文章:

http://msdn.microsoft.com/en-us/library/66b3y2ab(VS.71).aspx

http://topic.csdn.net/u/20100918/16/5a8bb22b-80bc-4e9f-8392-a3f876e91e05.html

http://blog.csdn.net/zdl1016/article/details/2799823(推荐)


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

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以及各种正常的方式关闭对话框。

      所以一般这么做:

  1. //CXXXDlg.h中  
  2. protect://public也没错  
  3. virtual void OnOk();  
  4. virtual void OnCancel();  
  5.   
  6. //CXXXDlg.cpp中  
  7.   
  8. void CXXXDlg::OnOk()//啥也不做就OK了  
  9. {  
  10.   
  11. }  
  12. void CXXXDlg::OnCancel()//同上  
  13.   
  14. {  
  15.   
  16. }  
//CXXXDlg.h中
protect://public也没错
virtual void OnOk();
virtual void OnCancel();

//CXXXDlg.cpp中

void CXXXDlg::OnOk()//啥也不做就OK了
{

}
void CXXXDlg::OnCancel()//同上

{

}

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

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

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

  1. void CDlgDrawTool::OnCancel()   //回车按钮处理  
  2. {  
  3. }  
  4. void CDlgDrawTool::OnOK()   //ESC按钮不处理  
  5. {  
  6. }  
  7. void CDlgDrawTool::OnClose()    //X按钮处理  
  8. {  
  9.     // TODO: Add your message handler code here and/or call default  
  10.     EndDialog(IDCANCEL);    //关闭窗口  
  11.     CDialog::OnClose();  
  12. }  
void CDlgDrawTool::OnCancel()	//回车按钮处理
{
}
void CDlgDrawTool::OnOK()	//ESC按钮不处理
{
}
void CDlgDrawTool::OnClose()	//X按钮处理
{
	// TODO: Add your message handler code here and/or call default
	EndDialog(IDCANCEL);	//关闭窗口
	CDialog::OnClose();
}


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

 

http://blog.csdn.net/bbdxf/article/details/7395201

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/phenixyf/article/details/41897055

智能推荐

哔哩哔哩 B站视频引用到自己的网站的方法_视频放b站再引用_咫尺云天的博客-程序员资料

先上个例子&lt;iframe height=100% width=100% src="//player.bilibili.com/player.html?bvid=BV1LC4y1s7gd&amp;page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"&gt; &lt;...

编译和移植qt-embedded-linux-opensource-src-4.5.3_qt embedded qlinuxfb_lhembed的博客-程序员资料

最初的动机是不想使用qtopia来开发qt界面,在网上搜索到qt/embedded也是可以解决的。在网上搜索了好多关于这方面的内容,我找了一个亲身实践的来讲吧。开发平台:Ubuntu 9.10目标平台:hfrk s3c2410交叉工具:arm-linux 版本4.1.2qt版本:qt-embedded-linux-opensource-src-4.5.3 下载地址:ftp://ftp.qt.nokia.com/qt/source/qt-embedded-linux-opensource-src-4.5.3.

如何进行WebShpere MQ 运行故障的定位分析和排除_mq状态异常,如何查看原因_Watson4Lin的博客-程序员资料

任何一种软件,都会存在一定的系统管理工作,WebSphere MQ也不例外,在使用WebSphere MQ(以下简称MQ)时,我们可能会由于配置的原因或者由于系统的原因,也可能由于MQ本身的原因,而遇到MQ运行过程中的一些故障和问题,如何能够快速地定位这些问题,分析问题发生的原因,进而快速地解决问题,恢复系统正常运行呢?这需要一定的经验积累和技巧,本文将对这方面给出一些简单的提示和方法。其实,

三次握手-四次挥手_半关闭状态在第几次挥手_玖先生的博客-程序员资料

1.TCP​ TCP 是一种面向连接的单播的,可靠的,流式传输协议,位于网络模型的传输层,为应用程序间提供数据传输。2.TCP 连接的建立和终止1.服务器调用socket,bind ,listen 完成初始化,服务器做好准备等待外部的TCP连接的到来,这种方式为被动打开,这个时候服务器处于LISTEN状态,等待客户端的连接请求。2.客户端通过connect发起主动打开,向服务器发出连接请求,发送请求标识位SYN=1,同时发送初始化序号seq=x.SYN报文不允许携带数据,消耗一个序号。

基于SVM和KNN的手写数字的识别(分类)——小试牛刀篇_zhulf0804的博客-程序员资料

数据下载地址:http://download.csdn.net/detail/zhulf0804/9719836这里采用的是k近邻算法(KNN)实现的手写数字识别。python实现代码:# -*- coding: utf-8 -*-import osimport numpy as npdef img2vector(filename, label): #图像数据转为向量

随便推点

链表面试题(一)_不负韶华-z的博客-程序员资料

本文所有的函数都是在上一篇单链表的基础上建立的。1、从尾到头打印链表分析:如下图所示,单链表为1、2、3、4、NULL,题目要求从尾到头打印,即打印的效果为4、3、2、1、NULL。我们可以用递归和循环来实现这一功能。 递归:递归的结束条件为pNodet为空,代码比较简单。循环:可以定义两个指针,一个用来遍历链表,一个用来结束循环。如图所示,用pNode来遍历链表,让pNode从...

免费下载PPT的网站_一个努力小白的博客-程序员资料

免费得PPT下载网站一、officeplusofficeplus,这个是微软官方的模板库哦,并且网站除了PPT模板,还有word的模板网站:http://www.officeplus.cn/Template/Home.shtml二、51PPT模板网这是一个有口皆碑的PPT网站了,虽然网站设计一般,但是模版下载确实比较方便。只要点击某篇模板,找到“下载地址”,即可下载。网址:http://www.51pptmoban.com/三、第一PPT第一PP是国内最早一批提供P

mysql 获取单个科目的平均分_weixin_30745553的博客-程序员资料

mysql&gt; select * from test;+----+----------+-------+-----------+| id | name | score | subject |+----+----------+-------+-----------+| 1 | xiaoming | 89 | shuxue || ...

精心挑选的100多种机器学习数据集_linweidong的博客-程序员资料

毫无疑问,每个人都知道,学习数据科学和机器学习的唯一最佳方法是通过执行各种项目来学习它们。老实说,您周围有很多现实世界的机器学习数据集,即使您不必完成全面的数据科学或机器学习课程,也可以选择练习基础数据科学和机器学习技能。但是是的,数据科学和机器学习项目绝对没有其他选择。大多数数据科学和机器学习初学者做错的事情是,他们只是专注于学习许多理论概念,而等待太长时间才能启动专注于该概念的实际实现的机器学习/数据科学项目。毫无疑问,从理论上讲清楚您的机器学习概念总会很好,但是如果没有获得相关的实际经验,您就无法期望

结构体数组定义时初始化_结构体数组初始化_同名公众号 - 人生代码的博客-程序员资料

结构体数组的初始化与前面讲的数值型数组的初始化是一模一样的,数值类型数组初始化的方法需要注意的是在结构体数组的初始化中同样适用,因为不管是不是数值型数组还是结构体数组都是数组。#include&lt;stdio.h&gt;#include&lt;string.h&gt;struct STU{ char name[20]; int age; char sex; char num[20...

kafka分区策略、ISR以及ack机制、故障处理机制、消费方式、分区分配策略_sghuu的博客-程序员资料

分区原因:1.分区的原因(1)方便在集群中扩展,每个partition可以通过调整以适应它所在的机器,而一个topic又可以有多个partition组成,因此整个集群就可以适应任意大小的数据了。(2)可以提高并发,因此可以以partition为单位读写2.partition的三种分区原则(1)指明partition的情况下,直接将指明的值直接作为partition的值(2)没有指明pa...

推荐文章

热门文章

相关标签