现在的位置: 首页 > 综合 > 正文

22、深入浅出MFC学习笔记,MFC解剖相关

2012年07月03日 ⁄ 综合 ⁄ 共 3099字 ⁄ 字号 评论关闭

1、需要的函数库

Windows C Runtime函数库

DLL Import函数库

MFC 函数库[1,P264]

2、传统SDK程序中WinMain所完成的工作现在由CWinApp的三个函数完成:

virtual BOOL InitApplication();//内部管理初始化工作

virtual BOOL InitInstance();//创建窗口

virtual int Run();//分发消息

WinMain只是扮演驾驭它们的角色。

CFrameWnd取代WndProc的地位。

一般CMyWinApp要改写CWinApp中的InitInstance,而不改写InitApplicationRun

3、在创建窗口时,改变图标和鼠标光标形状的介绍,可以参见[1,P289]

4、奇怪的窗口类名称 Afx:b:14ae:6:3e8f[1,P290]

spy++ 这类工具观察窗口类名称, 却发现窗口类名称变成这幅奇怪模样, 原来是 Application Framework 玩了一些把戏, 它把这些窗口类名称转换为 Afx:x:y:z:w 的形式, 成为独一无二的窗口类的名称:

x: 窗口风格(window style) hex

y: 窗口鼠标光标的 hex

z: 窗口后台颜色的 hex

w: 窗口图标(icon)hex

5MFC来龙去脉整理

程序的诞生

Application object 产生, 内存于是获得配置,初值亦设立了。

AfxWinMain执行AfxWinInit,后者又调有AfxInitThread,把消息队列尽量加

大到96

AfxWinMain执行InitApplication。这是CWinApp的虚拟函数,我们通常不改写它

AfxWinMain执行InitInstance。这是CWinApp的虚拟函数,我们必须改写它

CMyWinApp:: InitInstance new”了一个CMyFrameWnd对象

CmyFrameWnd构造函数调用Create,产生主窗口。我们在Create参数中指定的窗口类是NULL,于是MFC根据窗口种类,自行为我们注册一个名为“AfxFrameOrView42d”的窗口类。

回到InitInstance中继续执行ShowWindow,显示窗口

执行UpdateWindow,于是发出WM-PAINT

回到AfxWinMain,执行Run,进入消息循环。

程序开始运行:

程序获得WM-PAINT消息(由CWinApp::Run中的::GetMessage循环)

WM-PAINT经由::DispatchMessage送到窗口函数CWnd::DefWindowProc中。

CWnd::DefWindowProc将消息传递到消息映射表格

传递过程中发现有相符项目,于是调用项目中对应的函数。此函数是利用BEGIN_MESSAGE_MAPEND_MESSAGE_MAP之间的宏设立起来的。

标准消息的处理程序亦有标准命名,例如WM-PAINT必由OnPaint处理

程序的死亡:

使用者单击File/Close,于是发出WM-CLOSE

CMyFrameWnd并没有设置WM-CLOSE处理程序,于是交给默认的处理程序

默认函数对于WM-CLOSE的处理方式是调用::DestroyWindow,并因而发出WM-DESTROY

默认的WM-DESTROY处理方式是调用::PostQuitMessage,因此发出WM-QUIT

CWinApp::Run收到WM-QUIT后会结束内部之消息循环,然后调用ExitInstance,这是CWinApp的一个虚拟函数;如果 CMyWinApp改写了ExitInstance,那么CWinApp::Run所调用的就是CMyWinApp::ExitInstance,否则就是CWinApp::ExitInstance

最后回到AfxWinMain,执行AfxWinTerm,结束程序

6Callback函数

凡是由程序员设计而却由Windows 系统调用的函数,统称为callback 函数。这些函数都有一定的类型,以配合Windows的调用动作。

要把某个函数用作callback 函数,就必须告诉C++ 编译器,不要放this 指针作为该函数的最后一个参数[5]

两个方法可以做到这一点:

1)不要使用类的成员函数(也就是说,要使用全域函数)做为callback 函数。

2)使用static 成员函数。也就是在函数前面加上static 修饰词。

为什么要这样呢?

因为callback 函数是给Windows调用用的,Windows 并不经由任何对象调用这个函数,也就无法传递this 指针给callback 函数,于是导致堆栈中有一个随机变量会成为this 指针,而其结果当然是程序的崩溃了。

内存中只会有一份类成员函数,但却可能有许多份类成员变量(每个对象拥有一份)。

示例 LineDDA的使用

The LineDDA function determines which pixels should be highlighted for a line

defined by the specified starting and ending points. 这个函数以Bresenham算法计算出通过两点之间直线中的每一个屏幕像素坐标;每计算出一个坐标,就通知由LindDDA第五个参数所指定的callback函数。

示例代码

class CMyFrameWnd : public CFrameWnd
{
....
private:
DECLARE_MESSAGE_MAP()     // Declare Message Map
static VOID CALLBACK LineDDACallback(int,int,LPARAM);
};

.cpp

void CMyFrameWnd::OnPaint()
{
CPaintDC dc(this);
CRect rect;
GetClientRect(rect);
dc.SetTextAlign(TA_BOTTOM | TA_CENTER);
::LineDDA(rect.right/2, 0, rect.right/2, rect.bottom/2,
(LINEDDAPROC) LineDDACallback, (LPARAM) (LPVOID) &dc);
}
//--------------------------------------------------------------------
VOID CALLBACK CMyFrameWnd::LineDDACallback(int x, int y, LPARAM lpdc)
{
static char szText[] = "Hello, MFC";
((CDC*)lpdc)->TextOut(x, y, szText, sizeof(szText)-1);
for(int i=1; i<50000; i++);  //延迟
}

空闲时间的处理,通用对话框[1,P300]

参考

[1] 深入浅出MFC

[2] MFC Technical Notes

http://msdn.microsoft.com/en-us/library/h6h0eact%28VS.80%29.aspx

[3] http://blog.163.com/zhoumhan_0351/blog/static/3995422720103401415721/

[4] http://blog.163.com/zhoumhan_0351/blog/static/3995422720103411551637/

[5] http://www.cnblogs.com/mydomain/archive/2011/02/25/1965310.html

抱歉!评论已关闭.