mfc框架,MFC 框架技术简单研讨

引:
这篇博客是根据昨天的我们团队技术研讨会,我所讲的部分的内容(这句话读起来好纠结啊),由幻灯片改变而成的。因为我们团队在界面设计上缺陷很大,而我想对强一些(当然是我们团队之中了,我们都是大学生,所以我也强不到哪儿去)。为什么不直接讲MFC技术,而要简单讲框架。原因如下:个人认为MFC难学难用在于你不了解MFC的架构,如果你稍微有一些了解的话,用起来也就没那么复杂了。框架类型的东西往往如此,为程序员隐藏了太多的细节,通常都是知其然而不知其所以然。我准备了好长时间,但是讲解效果不好。意料之外,情理之中。一来看框架就要看源码,一个框架源码的复杂程度可想而知;二来大家都关心一些实用的技术,表面性东西,比如怎么实现窗口透明之类的技术,而不愿意花费时间在框架性东西上。这是一件很悲剧的事情……,我们园子里有大牛,当然我相信有很多学生,我想告诉大家的是学技术要专一要往深里学,不要浮躁,踏踏实实的。废话都多了……
我要写一点声明,上面废话可以不看,声明一定要看。
(1)博客参考了侯俊杰老师的《深入浅出MFC》,我用的是Visual Studio 2008,在源码上有一些不同。我学习了他分析问题的方法,在一些我自己搞不定的问题上,我摘了他书的原话。
(2)除本文之外,其他链接跳转文章是我直接从wps doc中直接复制过去,难免有一些失真。我本想一点一点校正格式,但是由于文章比较长,所以格式上会有一些混乱。这一点请大家见谅。
(3)小弟才疏学浅。如果看到本文的您是高手的话,您一定会发现文章的很多错误,希望您给我指出来。言辞表达不正,也欢迎您斧正。
(4)文章由幻灯片改编,衔接可能不流畅。
(4)本文为独酌逸醉原创,如果您需要转载的话,一定要标明文章参考了侯俊杰先生的《深入浅出MFC》,我个人事小。
正文:

第一讲 Win32 App 和 MFC Framework

Win32 App 程序生与死: (1)注册窗口 (2)创建窗口 (3)显示并更新窗口 (4)消息循环( WM_QUIT 结束循环) (5)退出
实例代码:
#include ATOM RegisterWndClass( HINSTANCE hInstance , LPCWSTR className); LRESULT CALLBACK WindowProc(HWND ,UINT, WPARAM, LPARAM); /* WinMain parameters: * hInstance : A handle to the current instance of the application. * hPrevInstance : A handle to the previous instance of the application. * This parameter is always NULL. ... * lpCmdLine : The command line for the application, excluding(不包括) the program name. * To retrieve(获取) the entire(全部) command line, use the GetCommandLine function. * nCmdShow : Controls how the window is to be shown. eg. SW_HIDE, SW_MAXIMIZE * * return value: If the function succeeds, terminating when it receives a WM_QUIT message, * it should return the exit value contained in that message's wParam parameter. * If the function terminates before entering the message loop, * it should return zero. */ int CALLBACK WinMain( __in HINSTANCE hInstance, __in HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nCmdShow ) { // (1)注册窗口 LPCWSTR className = TEXT("FirstWnd"); if (!RegisterWndClass(hInstance, className)) { ::MessageBox(NULL, TEXT("Register class failed"), TEXT("Error"), MB_OK | MB_ICONEXCLAMATION); return 0; } // (2)创建窗口 HWND hWnd; // 窗口句柄 hWnd = CreateWindow( className, // 窗口类名称 TEXT("A simple Win32 Application"), // 窗口标题 WS_OVERLAPPEDWINDOW, // 窗口风格 100, // 窗口位置的 x 坐标 , CW_USEDEFAULT 100, // 窗口位置的 y 坐标 , CW_USEDEFAULT 400, // 窗口的宽度 , CW_USEDEFAULT 300, // 窗口的高度 , CW_USEDEFAULT NULL, // 父窗口句柄 NULL, // 菜单句柄 hInstance, // 应用程序句柄 NULL); // 窗口创建数据指针, WM_CREATE lParam if (!hWnd) { ::MessageBox(NULL, TEXT("Register class failed"), TEXT("Error"), MB_OK | MB_ICONEXCLAMATION); return 0; } // (3)显示并更新窗口 ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // (4)进入消息循环 MSG msg; // 如果 msg 消息为 WM_QUIT , GetMessage 返回为 0 ,退出循环 while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // 程序结束 return msg.wParam; } // 注册窗口 ATOM RegisterWndClass( HINSTANCE hInstance , LPCWSTR className) { WNDCLASS wc; wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; // wc.lpfnWndProc = (WNDPROC)WindowProc; // A pointer to the window procedure. wc.cbClsExtra = 0; // wc.cbWndExtra = 0; // wc.hInstance = hInstance; // wc.hIcon = LoadIcon( hInstance, IDI_APPLICATION ); // A handle to the class icon. wc.hCursor = LoadCursor( NULL, IDC_ARROW ); // A handle to the class cursor. wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); // A handle to the class background brush. wc.lpszMenuName = NULL; // The resource name of the class menu, wc.lpszClassName = className; // A pointer to a null-terminated string or is an atom. return RegisterClass( &wc ); } // 窗口过程 LRESULT CALLBACK WindowProc( __in HWND hWnd, // A handle to the window. __in UINT uMsg, // The message. __in WPARAM wParam, // Additional message information __in LPARAM lParam // Additional message information ) { HDC hDC; PAINTSTRUCT ps; switch (uMsg) { case WM_PAINT: hDC = BeginPaint(hWnd, &ps); RECT rc; rc.bottom = 100; rc.left = 100; rc.right = 300; rc.top = 400; ::SetTextColor(hDC, RGB(255, 0, 0)); SetBkMode(hDC, TRANSPARENT); ::TextOut(hDC, 30, 30, TEXT("This is my first Win32 App !"), strlen("This is my first Win32 App !")); EndPaint(hWnd, &ps); break; case WM_DESTROY: MessageBox(NULL, TEXT("Window will be closed"), TEXT("Message"), MB_OK); PostQuitMessage(0); break; case WM_LBUTTONDOWN: MessageBox(NULL, TEXT("left button down"), TEXT("Message"), MB_OK); break; default: break; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }
思考:
1. Console App 入口点 是 main ; Win32 App 入口点是 WinMain ;那么 MFC 入口点在哪里 ? 2. 相对简洁的 Win32 App ,复杂的 MFC Framework 强大在哪里 ? 3. 大量的虚函数、复杂的宏,或者说 MFC Framework 背着我们用户做了哪些事情 ?

第二讲 MFC 六大关键技术

2.1 MFC 程序的初始化过程 2.2 RTTI(运行时类型识别) 2.3 Dynamic Creation(动态创建)
C++动态创建对象的困难在于,无法在程序执行期间,根据动态获得的一个类名称,要求程序产生一个对象。 在 RTTI 中,CRuntimeClass 对象记录了类的 CreateObject 函数,在程序执行期间获得类名称,遍历链表找到名称匹配项,调用 CreateObject ,产生新对象。
C++ 动态类型相关 (1) typeid 运算子 (2)宏 [ RTTI ] (3)模板实参演绎 [STL iterator_traits] C++在动态对象创建上一直是一个缺陷,据我说知,C# 有一项技术支持(反射)。 2.4 Persistence(永久保存)机制
Persistence:将对象永久保留下来(写入文件),Persistence 机制,也就是Serialize(数据读写)。
Persistence 简介
(1) MFC 提供 CObList 、CDWordArray 等类来支持 Persistence 。 (2) MFC 利用 DECLARE_SERIAL/IMPLIMENT_SERIAL 两个宏来实现 Persistence 机制。 (3)个人觉得,Persistence 只不过限定了一种文件格式来存储。普通程序员也可以很快设定一种文件格式来存储,不用受框架的限制,灵活性高且调试方便。 2.5 Message Mapping(消息映射)与Command Routing(命令传递)
Windows 程序本质系事借着消息来维持脉动(消息驱动),并以 WM_ 开头的常量开表示。 消息循着 Application Framework 规定的路线,游走于各个对象之间,直到找到它的归宿(消息处理函数)。找不到的话,Framework 最终把它交给 :DefWindowProc 函数处理。
MFC 消息分类
命令消息(WM_COMMAND):“使用者命令程序做些操作”。凡是 UI 对象产生的消息都是这种命令消息,可能来自菜单或者加速键或工具栏按钮,并且都以 WM_COMMAND 呈现。SDK 程序主要靠 wParam 识别之,MFC 程序则主要靠菜单项的识别码( menu ID)识别——其实两者是一样的。 凡是派生自 CCmdTarget 的类,都由资格接受命令消息。
标准消息:除 WM_COMMAND 之外,任何以 WM_ 开头的都算这一类,均可接受此消息。 Control Notification:由控件产生,为的是向父类窗口通知某种情况。例如当你在 ListBox 上选择其中一个项目,ListBox 就会产生 LBN_SELCHANGE 传送给父窗口。这类消息是以 WM_COMMAND 形式呈现。

第三讲 MFC 多线程技术简介

MFC 线程分类:Work Thread,UI Thread 区别:Work Thread 没有消息循环 UI Thread 有自己的消息和队列循环 Work Thread:通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等 UI Thread:一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。
4.1 Work Thread的创建
CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc, LPVOID pParam, nPriority=THREAD_PRIORITY_NORMAL, UINT nStackSize=0, DWORD dwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL); 线程函数类型: UINT ExecutingFunction(LPVOID pParam);
4.2 UI Thread的创建
CWinThread* AfxBeginThread(CRuntimeClass* pThreadClass, int nPriority=THREAD_PRIORITY_NORMAL, UINT nStackSize=0, DWORD dwCreateFlags=0, LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL); 具体请看:多线程编程之二——MFC中的多线程开发

第五讲 MFC 常用技术

略(幻灯片中讲了一些,但是比较杂碎,就不在这里列出来了……)
<本文完>
2011-09-20
Tags:  简单的mfc mfc技术内幕 简单mfc程序 mfc插件框架 mfc框架

延伸阅读

最新评论

发表评论