C程序设计从Win32到MFC.doc_第1页
C程序设计从Win32到MFC.doc_第2页
C程序设计从Win32到MFC.doc_第3页
C程序设计从Win32到MFC.doc_第4页
C程序设计从Win32到MFC.doc_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

从Win32过渡到MFC一、 开发自己的Win32类库MFC是微软对Win32代码进行封装的一套庞大的类库,如果直接讲解,由于不了解其内部结构和开发思想,学习起来将是非常难于理解的。为了了解MFC是如何封装的,今天我们先来开发一个我们自己的Win32类库。所谓类库,是指一套可以重用的代码,是为了方便以后的开发,将大量固定的、重复的、有规律的代码包装起来,供以后开发时直接调用,而不用再次重写这部分代码;这样就可以将我们的主要精力投入到真正需要花费时间的业务及其逻辑上面,而不再去关心和编写那些千篇一律的程序结构的代码了。在前面的课程中,我们发现WinMain工程中就有许多固定模式的代码,我们现在就来将其转换成我们自己的类库,我们称之为Win32Lib。WinMain工程的源代码如下:#include #include /声明窗口回调函数LRESULT CALLBACK WinProc(HWND hwnd,/ 窗口句柄UINT uMsg,/ 消息IDWPARAM wParam,/ 第1个消息参数LPARAM lParam/ 第2个消息参数);/程序入口int WINAPI WinMain(HINSTANCE hInstance,/ 当前实例句柄HINSTANCE hPrevInstance,/ 前一实例句柄LPSTR lpCmdLine,/ 命令行参数int nCmdShow/ 窗口显示方式)/1. 注册窗口WNDCLASS wndcls;/定义并填充窗口类wndcls.cbClsExtra = 0;wndcls.cbWndExtra = 0;wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);wndcls.hInstance = hInstance;wndcls.lpfnWndProc = WinProc;/重点:指定窗口消息的处理函数wndcls.lpszClassName = Itjob2010;wndcls.lpszMenuName = NULL;wndcls.style = CS_HREDRAW | CS_VREDRAW;RegisterClass(&wndcls);/注册窗口 /2. 创建窗口HWND hWnd;hWnd = CreateWindow(wndcls.lpszClassName,/窗口类名称一个简单的Win32程序,/窗口标题WS_OVERLAPPEDWINDOW,/窗口风格,定义为普通型0,/窗口位置的x坐标0,/窗口位置的y坐标600,/窗口的宽度400,/窗口的高度NULL,/父窗口句柄NULL,/菜单句柄hInstance,/应用程序实例句柄NULL);/窗口创建数据指针/3. 显示窗口ShowWindow(hWnd, SW_SHOWNORMAL);/4. 更新窗口UpdateWindow(hWnd);/5. 消息循环MSG msg;while (GetMessage(&msg, NULL, 0, 0)TranslateMessage(&msg);/把虚键消息翻译成字符消息(WM_CHAR),/再把WM_CHAR消息放到消息队列中去DispatchMessage(&msg);/指示操作系统把这条消息发送到窗口/过程WinProc进行处理return 0;/窗口回调函数,由操作系统调用,程序员/不要调用,但程序员需要编写其实现代码LRESULT CALLBACK WinProc(HWND hwnd,/ 窗口句柄UINT uMsg,/ 消息IDWPARAM wParam,/ 第1个消息参数LPARAM lParam/ 第2个消息参数)switch (uMsg)case WM_CHAR:char szChar20;sprintf(szChar, 你按下了%c键, (char)wParam);MessageBox(hwnd, szChar, WM_CHAR, 0);break;case WM_LBUTTONDOWN:HDC hdc;hdc = GetDC(hwnd);TextOut(hdc, 0, 50, 计算机编程语言培训, strlen(计算机编程语言培训);ReleaseDC(hwnd, hdc);break;case WM_PAINT:HDC hDC;PAINTSTRUCT ps;hDC = BeginPaint(hwnd, &ps);TextOut(hDC, 0, 0, Hello, World!, strlen(Hello, World!);EndPaint(hwnd, &ps);break;case WM_DESTROY:PostQuitMessage(0);break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);return 0;在上述代码中,我们发现,主函数WinMain()中的代码在编写任何一个Win32工程时几乎都是上述固定的步骤,即注册窗口类,创建窗口,显示窗口,更新窗口,消息循环。窗口回调函数WinProc()中的代码虽然各有不同,但也有共同的规律,即都是一个case语句对应一段处理某个消息的代码。首先我们将这些switch-case语句中的代码转换成函数的形式。为了统一,我们使这些函数都具有一样的函数原型。即:LRESULT OnChar(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);LRESULT OnLButtonDown (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);LRESULT OnPaint (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);LRESULT OnDestroy (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);转换后的部分代码如下:switch (uMsg)case WM_CHAR:OnChar(hWnd, wMsg, wParam, lParam);break;case WM_LBUTTONDOWN:OnLButtonDown (hWnd, wMsg, wParam, lParam);break;case WM_PAINT:OnPaint (hWnd, wMsg, wParam, lParam);break;case WM_DESTROY:OnDestroy (hWnd, wMsg, wParam, lParam);break;default:return DefWindowProc(hwnd, uMsg, wParam, lParam);转换后的代码就更加具有规律性了,如下表所示:消息(code)消息响应函数(Fxn)WM_CHAROnChar(hWnd, wMsg, wParam, lParam)WM_LBUTTONDOWNOnLButtonDown (hWnd, wMsg, wParam, lParam)WM_PAINTOnPaint (hWnd, wMsg, wParam, lParam)WM_DESTROYOnDestroy (hWnd, wMsg, wParam, lParam)从前面C/C+的课程中,我们知道,具有相同原型的一系列函数,可以使用typedef语句将他们定义成统一的函数指针形式,如下:typedef LRESULT (*FXN)( HWND, UINT, WPARAM, LPARAM);再定义一个返回元素个数的宏,后面的代码会用到:#define dim(x) (sizeof(x) / sizeof(x0)然后定义一个结构,用于表示上述的表格中的2类数据:struct tagMESSAGEMAP UINT Code;/消息FXN Fxn;/响应函数;再用该结构类型定义一个消息映射数组MessageMaps,并赋初值如下:tagMESSAGEMAP MessageMaps = WM_CHAR, OnChar, WM_LBUTTONDOWN,OnLButtonDown, WM_PAINT,OnPaint, WM_DESTROY,OnDestroy, ;接下来,我们将switch-case语句改造成for循环语句,改造完成后的WinProc函数如下:/主窗口回调函数LRESULT CALLBACK WinProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)/ 如果当前消息是我们关心的、定义在数组中的消息,则处理之for (int i = 0; i dim(MessageMaps); i+)if (wMsg = MessageMaps i.Code)FXN iFxn = MessageMaps i.Fxn;LRESULT lResult = iFxn (hWnd, wMsg, wParam, lParam);if (lResult = 0)return 0;/ 否则,将消息交给系统去处理return DefWindowProc(hWnd, wMsg, wParam, lParam);经过上面的改造之后,我们以后再要添加新的消息和消息响应函数,就只需要在数组MessageMaps中添加相应的消息代码,定义相应的消息响应函数及其实现代码就可以了。这样就将我们的精力真正转移到了我们所关心的业务上面来了,而再也不用去关心程序的结构了。改造后的全部代码如下:#include #include /返回元素的个数#define dim(x)(sizeof(x) / sizeof(x0)/定义函数指针typedef LRESULT(*FXN)(HWND, UINT, WPARAM, LPARAM);/消息映射结构struct tagMESSAGEMAPUINT Code;/消息FXN Fxn;/响应函数; /主窗口回调函数LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);/声明消息响应函数LRESULT OnChar(HWND, UINT, WPARAM, LPARAM);LRESULT OnLButtonDown(HWND, UINT, WPARAM, LPARAM);LRESULT OnPaint(HWND, UINT, WPARAM, LPARAM);LRESULT OnDestroy(HWND, UINT, WPARAM, LPARAM);LRESULT OnTimer(HWND, UINT, WPARAM, LPARAM);/消息映射数组tagMESSAGEMAP MessageMaps = WM_CHAR, OnChar, WM_LBUTTONDOWN, OnLButtonDown, WM_PAINT, OnPaint, WM_DESTROY, OnDestroy, WM_TIMER, OnTimer, ;/入口函数int WINAPI WinMain(HINSTANCE hInstance,/ handle to current instanceHINSTANCE hPrevInstance,/ handle to previous instanceLPSTR lpCmdLine,/ command lineint nCmdShow)/ show stateWNDCLASS wndcls;wndcls.cbClsExtra = 0;wndcls.cbWndExtra = 0;wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);wndcls.hInstance = hInstance;wndcls.lpfnWndProc = WinProc;wndcls.lpszClassName = ItJob2010;wndcls.lpszMenuName = NULL;wndcls.style = CS_HREDRAW | CS_VREDRAW;RegisterClass(&wndcls);HWND hWnd;hWnd = :CreateWindow(wndcls.lpszClassName, 培训中心, WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, NULL, NULL, hInstance, NULL);ShowWindow(hWnd, SW_SHOWNORMAL);UpdateWindow(hWnd);:SetTimer(hWnd, 123, 1000, NULL);MSG msg;while (GetMessage(&msg, NULL, 0, 0)TranslateMessage(&msg);DispatchMessage(&msg);return 0;/主窗口回调函数LRESULT CALLBACK WinProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)/ 如果当前消息是我们关心的、定义在数组中的消息,则处理之for (int i = 0; i 1000#pragma once#endif / _MSC_VER 1000/返回元素的个数#define dim(x)(sizeof(x) / sizeof(x0)/定义函数指针typedef LRESULT(*FXN)(HWND, UINT, WPARAM, LPARAM);/消息映射结构struct tagMESSAGEMAPUINT Code;/消息FXN Fxn;/响应函数;class CMyWndpublic:HINSTANCE m_hInstance;HWND m_hWnd;public:BOOL UpdateWindow();BOOL ShowWindow();BOOL Create();CMyWnd();virtual CMyWnd();/主窗口回调函数static LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);/声明消息响应函数static LRESULT OnChar(HWND, UINT, WPARAM, LPARAM);static LRESULT OnLButtonDown(HWND, UINT, WPARAM, LPARAM);static LRESULT OnPaint(HWND, UINT, WPARAM, LPARAM);static LRESULT OnDestroy(HWND, UINT, WPARAM, LPARAM);static LRESULT OnTimer(HWND, UINT, WPARAM, LPARAM);/消息映射数组tagMESSAGEMAP MessageMaps = WM_CHAR,CMyWnd:OnChar, WM_LBUTTONDOWN,CMyWnd:OnLButtonDown, WM_PAINT,CMyWnd:OnPaint, WM_DESTROY,CMyWnd:OnDestroy, WM_TIMER,CMyWnd:OnTimer, ;class CMyApp public:CMyWnd* m_pMainWnd;public:CMyApp();virtual CMyApp();BOOL InitInstance();BOOL Run();#endif / !defined(AFX_WIN32LIB_H_510E6511_F3DB_4E80_B512_INCLUDED _)完成后的Win32Lib.cpp内容如下:#include #include #include Win32Class.hCMyApp theApp;/入口函数int WINAPI WinMain(HINSTANCE hInstance,/ handle to current instanceHINSTANCE hPrevInstance,/ handle to previous instanceLPSTR lpCmdLine,/ command lineint nCmdShow)/ show statereturn 0;/ CMyWnd Class/CMyWnd:CMyWnd()m_hWnd = NULL;m_hInstance = NULL;BOOL CMyWnd:Create()WNDCLASS wndcls;wndcls.cbClsExtra = 0;wndcls.cbWndExtra = 0;wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);wndcls.hInstance = m_hInstance;wndcls.lpfnWndProc = WinProc;wndcls.lpszClassName = ItJob2010;wndcls.lpszMenuName = NULL;wndcls.style = CS_HREDRAW | CS_VREDRAW;RegisterClass(&wndcls);m_hWnd = :CreateWindow(wndcls.lpszClassName, 培训中心,WS_OVERLAPPEDWINDOW, 0, 0, 600, 400, NULL, NULL, m_hInstance, NULL);:SetTimer(m_hWnd, 123, 1000, NULL);if (m_hWnd = NULL)return FALSE;elsereturn TRUE;BOOL CMyWnd:ShowWindow()return :ShowWindow(m_hWnd, SW_SHOWNORMAL);BOOL CMyWnd:UpdateWindow()return :UpdateWindow(m_hWnd);/主窗口回调函数LRESULT CALLBACK CMyWnd:WinProc(HWND hWnd, UINT wMsg, WPARAM wParam, LPARAM lParam)/ 如果当前消息是我们关心的、定义在数组中的消息,则处理之for (int i = 0; i Create();m_pMainWnd-ShowWindow();return m_pMainWnd-UpdateWindow();三、优化Win32Class,将不常用的代码移到.h文件中,将常用的代码移到.cpp文件中去。其中使用MY_MESSAGE_DECLARE和MY_MESSAGE_MAP这2个宏将原本在Win32Class.h文件中的声明消息响应函数和定义消息响应函数数组的代码也移到了Win32Class.cpp文件中。这样,.h文件中都是一些结构性和固定模式的不需要经常改动的内容了,而.cpp文件中的内容就全是需要经常改动、和应用相关的内容,如要再添加新的消息及其响应代码,只需要照葫芦画瓢即可,真正实现了将主要精力放在业务上而不是程序的框架上的目标。其实,上面2个宏的实现思想就是MFC中消息映射的核心思想,通过实现我们自己的类库的过程,将原本复杂晦涩、难于理解的MFC消息映射的概念轻松的揭示给了大家。这为我们后面学习MFC打下了良好的基础。头文件Win32Class.h的内容如下:/ Win32Lib.h: interface for the CMyWnd class./#if !defined(AFX_WIN32LIB_H_510E6511_F3DB_4E80_B512_INCLUDED_)#define AFX_WIN32LIB_H_510E6511_F3DB_4E80_B512_INCLUDED_#if _MSC_VER 1000#pragma once#endif / _MSC_VER 1000/返回元素的个数#define dim(x)(sizeof(x) / sizeof(x0)/定义函数指针typedef LRESULT(*FXN)(HWND, UINT, WPARAM, LPARAM);/消息映射结构struct tagMESSAGEMAPUINT Code;/消息FXN Fxn;/响应函数;class CMyWndpublic:HINSTANCE m_hInstance;HWND m_hWnd;public:BOOL Create();BOOL ShowWindow();BOOL UpdateWindow();CMyWnd();virtual CMyWnd();/主窗口回调函数static LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);/声明消息响应函数MY_MESSAGE_DECLARE;/消息映射数组MY_MESSAGE_MAPclass CMyApp public:CMyWnd* m_pMainWnd;BOOL InitInstance();BOOL Run();CMyApp();virtual CMyApp();/入口函数int WINAPI WinMain(HINSTANCE hInstance,/ handle to current instanceHINSTANCE hPrevInstance,/ handle to previous instanceLPSTR lpCmdLine,/ command lineint nCmdShow)/ show statereturn 0;/ CMyWnd Class/CMyWnd:CMyWnd()m_hWnd = NULL;m_hInstance = NULL;BOOL CMyWnd:Create()WNDCLASS wndcls;wndcls.cbClsExtra = 0;wndcls.cbWndExtra = 0;wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);wndcls.hIcon = LoadIcon(NULL, IDI_ERROR);wndcls.hInstance = m_hInstance;wndcls.lpfnWndProc = WinProc;wndcls.lpszClassName = ItJob2010;wndcls.lpszMenuName = NULL;wndcls.style = CS_HREDRAW | CS_VREDRAW;RegisterCla

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论