博文
MFC学习之--消息映射的定义和实现(2007-07-29 22:55:00)
摘要:MFC处理的三类消息
根据处理函数和处理过程的不同,MFC主要处理三类消息:
Windows消息,前缀以“WM_”打头,WM_COMMAND例外。Windows消息直接送给MFC窗口过程处理,窗口过程调用对应的消息处理函数。一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC窗口类的成员函数。
控制通知消息,是控制子窗口送给父窗口的WM_COMMAND通知消息。窗口过程调用对应的消息处理函数。一般,由窗口对象来处理这类消息,也就是说,这类消息处理函数一般是MFC窗口类的成员函数。
需要指出的是,Win32使用新的WM_NOFITY来处理复杂的通知消息。WM_COMMAND类型的通知消息仅仅能传递一个控制窗口句柄(lparam)、控制窗ID和通知代码(wparam)。WM_NOTIFY能传递任意复杂的信息。
命令消息,这是来自菜单、工具条按钮、加速键等用户接口对象的WM_COMMAND通知消息,属于应用程序自己定义的消息。通过消息映射机制,MFC框架把命令按一定的路径分发给多种类型的对象(具备消息处理能力)处理,如文档、窗口、应用程序、文档模板等对象。能处理消息映射的类必须从CCmdTarget类派生。
在讨论了消息的分类之后,应该是讨论各类消息如何处理的时候了。但是,要知道怎么处理消息,首先要知道如何映射消息。
MFC消息映射的实现方法
MFC使用ClassWizard帮助实现消息映射,它在源码中添加一些消息映射的内容,并声明和实现消息处理函数。现在来分析这些被添加的内容。
在类的定义(头文件)里,它增加了消息处理函数声明,并添加一行声明消息映射的宏DECLARE_MESSAGE_MAP。
在类的实现(实现文件)里,实现消息处理函数,并使用IMPLEMENT_MESSAGE_MAP宏实现消息映射。一般情况下,这些声明和实现是由MFC的ClassWizard自动来维护的。看一个例子:
在AppWizard产生的应用程序类的源码中,应用程序类的定义(头文件)包含了类似如下的代码:
//{{AFX_MSG(CTttApp)
afx_msg void OnAppAbout();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
应用程序类的实现文件中......
MFC学习之--MFC和Win32(2007-07-25 23:22:00)
摘要:MFC Object和Windows Object的关系
MFC中最重要的封装是对Win32 API的封装,因此,理解Windows Object和MFC Object (C++对象,一个C++类的实例)之间的关系是理解MFC的关键之一。所谓Windows Object(Windows对象)是Win32下用句柄表示的Windows操作系统对象;所谓MFC Object (MFC对象)是C++对象,是一个C++类的实例,这里(本书范围内)MFC Object是有特定含义的,指封装Windows Object的C++ Object,并非指任意的C++ Object。
MFC Object 和Windows Object是不一样的,但两者紧密联系。以窗口对象为例:
一个MFC窗口对象是一个C++ CWnd类(或派生类)的实例,是程序直接创建的。在程序执行中它随着窗口类构造函数的调用而生成,随着析构函数的调用而消失。而Windows窗口则是Windows系统的一个内部数据结构的实例,由一个“窗口句柄”标识,Windows系统创建它并给它分配系统资源。Windows窗口在MFC窗口对象创建之后,由CWnd类的Create成员函数创建,“窗口句柄”保存在窗口对象的m_hWnd成员变量中。Windows窗口可以被一个程序销毁,也可以被用户的动作销毁。
下面,对MFC Object和Windows Object作一个比较。有些论断对设备描述表(MFC类是CDC,句柄是HDC)可能不适用,但具体涉及到时会指出。
从数据结构上比较
MFC Object是相应C++类的实例,这些类是MFC或者程序员定义的;
Windows Object是Windows系统的内部结构,通过一个句柄来引用;
MFC给这些类定义了一个成员变量来保存MFC Object对应的Windows Object的句柄。对于设备描述表CDC类,将保存两个HDC句柄。
从层次上讲比较
MFC Object是高层的,Windows Object是低层的;
MFC Object封装了Windows Object的大部分或全部功能,MFC Object的使用者不需要直接应用Windows Object的HANDLE(句柄)使用Win32 API,代替它的是引用相应的MFC Object的成员函数。
......
MFC的一点感悟(2007-07-24 12:15:00)
摘要: 学习MFC的时间不长,但是感觉开始学习的方法不对,只知道随便摆摆几个控件然后想怎么把个控件弄漂亮点(不停的在网上下别人写的控件,但是看不懂),而忽视了基础的重要性,比如说MFC和API之间的关系,消息映射机制的实现,Windows窗口对象和CWnd的C++对象之间的联系等等。
这样学习的结果可想而知,只懂皮毛,只会用ClassWizard弄点简单的小程序,遇到稍微需要自己写代码的地方就不知从何写起了。因此曾一度决定放弃MFC的,觉得这种编程方式太麻烦了,尤其是写UI时,自我觉得还是对JAVA,QT那种写界面的方式好接受点,知道自己写了哪些东西以及怎么写的。
前几天在网上发现一在线教程,感觉写得还蛮好的,比起那些各式各样的VC的书讲得好多了,尤其是当我看完消息映射后,发现这个对我真是受益匪浅,再结合源码看看,有些以前难以理解的东西现在觉得有点眉目了,还开始感叹写MFC那些人的技术之精,能写出如此庞大(看到网上有些人觉得MFC太臃肿,我暂时可能还没有发现这个的能力),效率又高的库真是不简单,觉得学习C++面向对象的思想,MFC源码是个不错的东东。
想把自己现在对MFC的一些基础部分整理一个小的系列文章,:-),当然绝大部分内容都是网上的,我可能只是修改一些错误的地方,可惜现在时间不是很多,尽力了,也算是对自己学习MFC的一点点初级的总结吧!......
创造你自己的控件--子分类的艺术(2007-07-20 20:57:00)
摘要:第一次翻译哦,呵呵,原文地址为:http://www.codeproject.com/miscctrl/subclassdemo.asp
创造你自己的控件-子分类的艺术
By Chris Maunder.
介绍
作为一个程序员有许多普通的windows控件可以用在应用程序的外观上。许多的控件的从列表到按钮再到进程条都是可以现成的用。尽管如此,在如此多的控件中我们还是会碰到那些标准的控件不够用的时候。欢迎进入子分类控件的艺术。
子分类一个windows控件不像子分类一个C++类。子分类一个控件意味这你用你自己的消息处理函数取代了改控件的一些或者所有的消息处理函数。你可以有效的截获改控件的消息并使它按照你的意愿行事,而非windows的默认方式。这可以让改控件实现大多数而非全部的你想得到的行为,并且使它表现得很完美。有两种类型的子分类,局部子分类和全局子分类。局部子分类就是子分类一个实体,全局子分类就是将一个特定类型的控件全部子分成你的类型。
记住一个从CWnd类派生的类对象和一个与它相联的窗口(hwnd)的区别是很重要的。CWnd的派生类对象包含一个成员变量指向hwnd,而且包含那些通过hwnd作为参数的处理消息的函数(比如,WM_PAINT, WM_MOUSEMOVE)。当你子分类一个控件通过你的C++对象时,你就是将相应的hwnd连接到你的C++对象上并把改控件将激发的消息回调函数改成你的。
子分类是很容易的。首先,你创建一个处理了你感兴趣的所以消息的类,然后将该类来子分一个已经存在的控件使它按照你的新类的行事。某中方面上改控件已经变成了你所拥有的了。在这个例子中我们将子分一个按钮控件并且使它做一些它从来都没能够做的事。
一个新类
子分一个控件我们需要创建一个新类改类应该处理了所有我们感兴趣的消息。由于我们很懒,最好是使我们处理的消息最少,而且最好的方式是从你将要子分的控件派生你的新类,我们这里选择的是CButton。
我们设想的是使按钮在鼠标每次经过时显示出高亮的黄色。奇怪的事已经产生了。首先我们通过向导创建一个从CButton派生的新类CMyButton。
&nbs......
VC6.0中如何改变对话框的背景颜色(转载)(2007-04-25 17:15:00)
摘要:---- 方法一:调用CWinApp类的成员函数SetDialogBkColor来实现。
---- 其中函数的第一个参数指定了背景颜色,第二个参数指定了文本颜色。下面的例子是将应用程序对话框设置为蓝色背景和红色文本,步骤如下:
---- ① 新建一个基于Dialog的MFC AppWizard应用程序ExampleDlg。
---- ② 在CExampleDlgApp ::InitInstance()中添加如下代码:
BOOL CExampleDlgApp: : InitInstance ( )
{
...
CExampleDlgDlg dlg;
m_pMainWnd = &dlg;
//先于DoModal()调用,将对话框设置为蓝色背景、红色文本
SetDialogBkColor(RGB(0,0,255),RGB(255,0,0));
int nResponse = dlg.DoModal();
...
}
---- 编译并运行,此时对话框的背景色和文本色已发生了改变。值得注意的是:在调用DoModal()之前必须先调用SetDialogBkColor,且此方法是将改变应用程序中所有的对话框颜色,并不能针对某一个指定的对话框。
---- 方法二:重载OnPaint(),即WM_PAINT消息。有关代码如下(以上例工程为准):
void CExampleDlgDlg::OnPaint()
{
if (IsIconic())
...
else
{
CRect rect;
CPaintDC dc(this);
GetClientRect(rect);
......
最简单的MFC程序(2007-01-22 17:23:00)
摘要:#include <afxwin.h>
//定义一个CWinApp的派生类
class CMinApp:public CWinApp
{
public:
virtual BOOL InitInstance();
};
//重载CWinApp成员函数InitInstance()
BOOL CMinApp::InitInstance() //应用程序初始化
{
CFrameWnd* pFrame=new CFrameWnd; //动态生成主窗口类对象
pFrame->Create(0,_T("A Minimal MFC Program")); //创建主窗口
pFrame->ShowWindow(SW_SHOWMAXIMIZED); //显示主窗口
pFrame->UpdateWindow(); //刷新主窗口
AfxGetApp()->m_pMainWnd=pFrame; //指定应用程序主窗口
re......