MFC封装API

一、Win32Application Architecture

一个Win32 Application Architecture的代码结构如下:

LRESULT CALLBACK WinWordsProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);  //定义回调处理消息函数

 

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){

         // 创建一个窗口类分为三步:1.设计窗口类 2.注册窗口类 3.创建窗口 4.显示及更新窗口

         // 步骤1.设计窗口类

         WNDCLASS wc;

……

         // 步骤2:注册窗口类

         RegisterClass(&wc);

         // 步骤3:创建窗口

         HWND hw = NULL;  

         hw = CreateWindow("Icanth2011", "My Fist Win32 Application Project!~", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, 600, 400, NULL, NULL, hInstance, NULL);

         // 步骤4:显示及更新窗口

         ShowWindow(hw, SW_SHOWNORMAL);

         UpdateWindow(hw);

         // 消息循环

         MSG msg;

         BOOL bRet;

         while((bRet=GetMessage(&msg, NULL, 0, 0))!=0){

                   if(-1 == bRet){

                            return -1;

                   }

                   TranslateMessage(&msg);

                   DispatchMessage(&msg);

         }

         return msg.wParam;

}

 
 


由此可见,Win32 Application 程序的组成分为如下几个部分:

1.       找到WinMain程序入口,并开始执行

2.       创建并设计窗口类

3.       注册窗口类

4.       创建窗口

5.       显示及更新窗口

6.       循环获取消息,经处理,交还系统让其调用相关回调消息处理函数进行处理。

 

二、MFCArchitecture

由于Windows API过多,不方便程序员使用,并且非面对象。于是MFC被用于对Windows API进行封装,MFC始终实际运行过程就是Win32 Application程序的运行过程。

 

1.      MFC的项目结构

利用MFC AppWipzard自动生成的项目包括五个文件:CMyFirstMFCApp、CMainFrame、CFirstMFCDoc、CMyFirstCView、CAboutDlg。CMyFirstMFCApp继承自CWinApp,CMainFrame、CMyFirstCView、CAboutDlg都继承自CWnd,CFirstMFCDoc继承自CDocument,体现“文档/视图”结构。其项目结构如下所示:

 

2.      MFC的执行过程

对于MFC框架运行过程进行剖析,最好的资料是MFC源代码,VC6位于“\Microsoft Visual Studio\VC98\MFC\SRC”下。执行过程如下:

定义theApp(:CMyFistMFCApp)

                   ——>执行构造函数:CWinApp()->CMyFistMFCApp()->

                                     ——>程序入口_tWinMain (宏,定义为WInMain)

——>执行AftxWinMain

 

 
 

 

 

 

 


2.1  MFC的WinMain

在\SRC\APPMODUL.CPP中,可找到如下代码:

MFC\SRC\APPMODUL.CPP:

 

extern "C" int WINAPI

_tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

         LPTSTR lpCmdLine, int nCmdShow)

{

         // call shared/exported WinMain

         return AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

 

 
 

 

 

 

 

 

 

 

 

 

 


而其中_tWinMain其实就是WinMain函数的宏,定义如下:

 

#define _tmain      main

#define _tWinMain   WinMain

#ifdef  _POSIX_

#define _tenviron   environ

 

 
 

 

 

 


由此可见,WinMain中调用AfxWinMain进行处理。MFC包含此文件,故将找到此入口并自动调用执行。

 

2.2  theApp全局对象

在Project\CMyFirstMFCApp.CPP中,可找到一行代码发下:

Project\CMyFirstMFCApp.CPP:

 

/

// The one and only CMyFistMFCApp object

CMyFistMFCApp theApp;

 

 
 

 

 

 

 


当定义theApp时,将先执行CWinApp(\MFC\SRC\APPCORE.CPP)的构造函数:

\MFC\SRC\APPCORE.CPP:

 

CWinApp::CWinApp(LPCTSTR lpszAppName) // 有在该类定义时有默认值NULL

{

         if (lpszAppName != NULL)

                   m_pszAppName = _tcsdup(lpszAppName);

         else

                   m_pszAppName = NULL;

 

         // initialize CWinThread state

         AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();

         AFX_MODULE_THREAD_STATE* pThreadState = pModuleState->m_thread;

         ASSERT(AfxGetThread() == NULL);

         pThreadState->m_pCurrentWinThread = this;

         ASSERT(AfxGetThread() == this);

         m_hThread = ::GetCurrentThread();

         m_nThreadID = ::GetCurrentThreadId();

 

         // initialize CWinApp state

         ASSERT(afxCurrentWinApp == NULL); // only one CWinApp object please

         pModuleState->m_pCurrentWinApp = this; // handle,this代表子类CMyFirstMFCApp对象

         ASSERT(AfxGetApp() == this);

……

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2.3  AfxWinMain(WINMAIN.CPP)

 

1.AfxWindMain定义

 

\MFC\SRC\WINMAIN.CPP:

 

int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

         LPTSTR lpCmdLine, int nCmdShow)

{

         CWinThread* pThread = AfxGetThread();

         CWinApp* pApp = AfxGetApp();

         if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))

         if (pApp != NULL && !pApp->InitApplication())

                   goto InitFailure;

         if (!pThread->InitInstance())

         {

                   if (pThread->m_pMainWnd != NULL)

                   {

                            pThread->m_pMainWnd->DestroyWindow();

                   }

                   goto InitFailure;

         }

         nReturnCode = pThread->Run();

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2.AfxGetThread

AfxGetThread(THRDCORE.CPP)中调用AfxGetApp,和afxGetApp返回同值,代码如下所示:

\MFC\SRC\ THRDCORE.CPP:

 

CWinThread* AFXAPI AfxGetThread()

{

         // check for current thread in module thread state

         AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();

         CWinThread* pThread = pState->m_pCurrentWinThread;

         // if no CWinThread for the module, then use the global app

         if (pThread == NULL)

                   pThread = AfxGetApp();

         return pThread;

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 


3.AfxGetApp

AfxGetApp(AFXWIN1.INL)中定义:

AFXWIN1.INL:

 

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp(){ return afxCurrentWinApp; }

 

 
 

 

 

 

 


而afxCurrentWinApp定义位于AFXWIN.H文件中,如下:

AFXWIN.H:

 

#define afxCurrentWinApp AfxGetModuleState()->m_pCurrentWinApp

 

 
 

 

 

 


即为CWinApp构造函数时初始化为this的m_pCurrentWinApp。

 

4.InitInstance

类CWinAPP(APPCORE.CPP)中InitInstance函数定义为:

\MFC\SRC\ APPCORE.CPP:

 

// overrides for implementation

virtual BOOL InitInstance();

 

 
 

 

 

 


类InitInstance即为虚函数,根据多态性,将调用CMyFirstMFCApp类的InitInstance。

 

2.4  InitInstance(CMyFirstMFCAPP.CPP)

\MFC\SRC\ CMyFirstMFCAPP.CPP:

 

BOOL CMyFistMFCApp::InitInstance()

{

         CSingleDocTemplate* pDocTemplate;

         pDocTemplate = new CSingleDocTemplate(

                   IDR_MAINFRAME,

                   RUNTIME_CLASS(CMyFistMFCDoc),

                   RUNTIME_CLASS(CMainFrame),       // main SDI frame window

                   RUNTIME_CLASS(CMyFistMFCView));

         AddDocTemplate(pDocTemplate);

         m_pMainWnd->ShowWindow(SW_SHOW);

         m_pMainWnd->UpdateWindow();

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 


2.5  MFC框架窗口

CFirstMyMFC有两个窗口,其中一个是CMainFrame。

 

2.5.1 设计和注册窗口

 

1.       CMainFrame::PreCreateWindow定义(\Project\CMainFrame.cpp)

\MFC\SRC\ CMyFirstMFCAPP.CPP:

 

BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)

{

         if( !CFrameWnd::PreCreateWindow(cs) )

                   return FALSE;

         return TRUE;

}

 

 
 

 

 

 

 

 


2.       CFrameWnd::PreCreateWindow(CREATESTRUCT& cs) (\MFC\SRC\WINFRM.CPP)

 

 

\MFC\SRC\ CMyFirstMFCAPP.CPP:

 

BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)

{

         if (cs.lpszClass == NULL)

         {

                   VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));

                   cs.lpszClass = _afxWndFrameOrView;  // COLOR_WINDOW background

         }

         return TRUE;

}

 

 
 

 

 

 

 

 

 

 

 


其中,AfxDeferRegisterClass即为AfxEndDeferRegisterClass的宏定义,位于AFXIMPL.H文件中:

AFXIMPL.H:

 

#define AfxDeferRegisterClass(fClass) AfxEndDeferRegisterClass(fClass)

 

 
 

 

 

 


3.       AfxEndDeferRegisterClass (位于WINCORE.CPP中)

此处指定DefWindowProc函数来处理回调消息。 (!~)

MFC\SRC\WINCORE.CPP:

 

BOOL AFXAPI AfxEndDeferRegisterClass(LONG fToRegister)

{

         // mask off all classes that are already registered

         AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

         fToRegister &= ~pModuleState->m_fRegisteredClasses;

         if (fToRegister == 0)

                   return TRUE;

         LONG fRegisteredClasses = 0;

         // common initialization

         WNDCLASS wndcls;

         memset(&wndcls, 0, sizeof(WNDCLASS));   // start with NULL defaults

         wndcls.lpfnWndProc = DefWindowProc;

         wndcls.hInstance = AfxGetInstanceHandle();

         wndcls.hCursor = afxData.hcurArrow;

         INITCOMMONCONTROLSEX init;

         init.dwSize = sizeof(init);

         // work to register classes as specified by fToRegister, populate fRegisteredClasses as we go

         if (fToRegister & AFX_WND_REG)

         {

                   // Child windows - no brush, no icon, safest default class styles

                   wndcls.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;

                   wndcls.lpszClassName = _afxWnd;

                   if (AfxRegisterClass(&wndcls))

                            fRegisteredClasses |= AFX_WND_REG;

         }

         ……

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


4.       AfxRegisterClass  (位于WINCORE.CPP中)

MFC\SRC\WINCORE.CPP:

 

BOOL AFXAPI AfxRegisterClass(WNDCLASS* lpWndClass)

{

         WNDCLASS wndcls;

         if (GetClassInfo(lpWndClass->hInstance, lpWndClass->lpszClassName,

                   &wndcls))

         {

                   // class already registered

                   return TRUE;

         }

         if (!::RegisterClass(lpWndClass))

         {

                   TRACE1("Can't register window class named %s\n",

                            lpWndClass->lpszClassName);

                   return FALSE;

         }

         return TRUE;

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


2.5.2 创建窗口

1. CFrameWnd::Create  (WINFRM.CPP)

MFC\SRC\WINFRM.CPP:

 

BOOL CFrameWnd::Create(LPCTSTR lpszClassName,

         LPCTSTR lpszWindowName,

         DWORD dwStyle,

         const RECT& rect,

         CWnd* pParentWnd,

         LPCTSTR lpszMenuName,

         DWORD dwExStyle,

         CCreateContext* pContext)

{

         HMENU hMenu = NULL;

         if (lpszMenuName != NULL)

         {

                   // load in a menu that will get destroyed when window gets destroyed

                   HINSTANCE hInst = AfxFindResourceHandle(lpszMenuName, RT_MENU);

                   if ((hMenu = ::LoadMenu(hInst, lpszMenuName)) == NULL)

                   {

                            TRACE0("Warning: failed to load menu for CFrameWnd.\n");

                            PostNcDestroy();            // perhaps delete the C++ object

                            return FALSE;

                   }

         }

         m_strTitle = lpszWindowName;    // save title for later

         if (!CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle,

                   rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,

                   pParentWnd->GetSafeHwnd(), hMenu, (LPVOID)pContext))

         {

                   TRACE0("Warning: failed to create CFrameWnd.\n");

                   if (hMenu != NULL)

                            DestroyMenu(hMenu);

                   return FALSE;

         }

         return TRUE;

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


3.       CWnd:CreateEx (WINCORE.CPP)

MFC\SRC\WINFRM.CPP:

 

BOOL CWnd::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName,

         LPCTSTR lpszWindowName, DWORD dwStyle,

         int x, int y, int nWidth, int nHeight,

         HWND hWndParent, HMENU nIDorHMenu, LPVOID lpParam)

{

         // allow modification of several common create parameters

         CREATESTRUCT cs;

         cs.dwExStyle = dwExStyle;

         ……

         if (!PreCreateWindow(cs)) //完成注册窗口类工作

         {

                   PostNcDestroy();

                   return FALSE;

         }

 

         AfxHookWindowCreate(this);

         HWND hWnd = ::CreateWindowEx(cs.dwExStyle, cs.lpszClass,

                            cs.lpszName, cs.style, cs.x, cs.y, cs.cx, cs.cy,

                            cs.hwndParent, cs.hMenu, cs.hInstance, cs.lpCreateParams);

         ……

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


以下是CREATESTRUCT和CreateWindowEx参数的对比:


由于CREATESTRUCT中的属性都定义为指针,故可在PreCreateWindow中更改属性,在CreateWindowEx中将更改显示。

 

4.      MFC的调用关系

① theApp

theApp(CMyFirstMFCApp.CPP)

——> CWinAPP ::CWinAPP(){ pModuleState->m_pCurrentWinApp = this;  }

 

 
 

 

 

 


② _tWinMain(APPMODUL.CPP)

_tWinMain ()

{

AfxWinMain(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

}

 

 
 

 

 

 

 

 

 

  


③ AfxWinMain(WinMain.CPP)

int AFXAPI AfxWinMain()

{

CWinThread* pThread = AfxGetThread(); //——>return AfxGetApp() (:THRDCORE.CPP)

         CWinApp* pApp = AfxGetApp();

//——>return afxCurrentWInApp (:AFXWIN1.INL)

//——>return AfxGetModuleState()->m_pCurrentWinApp (:AFXWIN.H)

AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow);

pApp->InitApplication();

pThread-> InitInstance ();

         //——> CMyFirstMFCApp::InitInstance

                   //——> AddDocTemplate(pDocTemplate);

                            //——> m_pMainWnd->ShowWindow(SW_SHOW);

                   //——> m_pMainWnd->UpdateWindow();

pThread->Run();

}

 

 
 

 

 

 

 

 

 

 

 

 

 

 

 

 


④ 窗口

设计和注册窗口:

CMainFrame::PreCreateWindow (\Project\ CMainFrame.cpp)

         ——>CFrameWnd::PreCreateWindow

                   ——>AfxDeferRegisterClass(宏= AfxEndDeferRegisterClass)

——>AfxEndDeferRegisterClass

——>AfxRegisterClass

         ——>::RegisterClass (SDK)

 

 
 

 

 

 

 

 

 

 


创建窗口:

CFrameWnd::Create()

         ——>CFrameWnd::CreateEx()

——>CWnd::CreateEx()

         ——>virsual CWnd::PreCreateWIndow(虚函数,调用子类中CFrameWnd:: PreCreateWIndow),

:: CreateWIndowEx()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/254875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通过阅读 Douglas Crockford 的源码学习如何写 JSON parser(一)

JSON-js Douglas Crockford 是 JSON 的发明者,所以通过 DC 的代码来学习 JSON 和 parser 绝对是上乘之选。这个仓库里面有四个 JS 文件,今天我们先研究 json_parse.js。 json_parse 定义了如下 API: json_parse(string) > object json_par…

halcon gen_region_hline 绘制霍夫变换提取直线

目录gen_region_hline(算子)描述gen_region_hline(算子) gen_region_hline - 将霍夫变换提取直线以普通形式描述的输入行存储为区域。 gen_region_hline( : Regions : Orientation, Distance : ) 描述 运算符gen_region_hline…

H.264视频RTP负载格式/NALU的类型

1. 网络抽象层单元类型(NALU) NALU 头由一个字节组成, 它的语法如下: |0|1|2|3|4|5|6|7| |F|NRI| Type | F: 1 个比特. forbidden_zero_bit:在H.264规范中规定了这一位必须为0。 NRI: 2 个比特. nal_ref_idc&#xff1…

4.10下午

转载于:https://www.cnblogs.com/yanyuying/p/6690662.html

虚函数

1、基于向上类型转换&#xff0c;基类通过虚函数可以对多个子类相似的功能实现统一管理。 2、例子&#xff1a; A为基类&#xff0c;B、C为A的同级子类。virtual只需在基类中标识一次&#xff0c;子类无需重复标识。class A {virtual void display(){cout<<"我是A&q…

Android绘制(一):来用shape绘出想要的图形吧!

目录 前言shape绘制矩形椭圆线环用shape绘制SeekBar最后前言 在没有UI设计师的时候, 或者是想简单看下效果的时候, 用shape进行快速绘制是极好的! 官方文档. shape绘制 一共有四种shape: rectangle, oval, line, ring. 矩形 我们一个一个来看, 首先是矩形: <?xml version&q…

halcon sobel 边缘检测 sobel_dir

目录sobel_dir&#xff08;算子&#xff09;描述参数sobel_dir&#xff08;算子&#xff09; sobel_dir - 使用Sobel算子检测边缘&#xff08;振幅和方向&#xff09;。 sobel_dir(Image : EdgeAmplitude, EdgeDirection : FilterType, Size : ) 描述 sobel_dir计算图像的一…

静态链接库LIB和动态链接库DLL的区别 创建和示例

1.什么是静态连接库&#xff0c;什么是动态链接库静态链接库与动态链接库都是共享代码的方式&#xff0c;如果采用静态链接库&#xff0c;则无论你愿不愿意&#xff0c; lib 中的指令都全部被直接包含在最终生成的 EXE 文件中了。 但是若使用 DLL&#xff0c;该 DLL 不必被包含…

【译】x86程序员手册37-第10章 初始化

Chapter 10 Initialization 第10章 初始化 After a signal on the RESET pin, certain registers of the 80386 are set to predefined values. These values are adequate to enable execution of a bootstrap program, but additional initialization must be performed by s…

在ubuntu中安装minicom时出现device /dev/tty8 is locked解决办法

未正常关闭minicom yesaiduywf-ubuntu: ~$ ls /var/lock LCK..ttyS0 subsys yesaiduywf-ubuntu: ~$ kill 0 yesaiduywf-ubuntu: ~$ ls /var/lock subsys yesaiduywf-ubuntu: ~$ sudo minicom Welcome to minicom 2.3 或者删除/var/lock下面以LCK开头的文件转载于:https://www.…

秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别

本文将带领你与多线程作第一次亲密接触&#xff0c;并深入分析CreateThread与_beginthreadex的本质区别&#xff0c;相信阅读本文后你能轻松的使用多线程并能流畅准确的回答CreateThread与_beginthreadex到底有什么区别&#xff0c;在实际的编程中到底应该使用CreateThread还是…

halcon get_image_pointer1获取图像指针

目录get_image_pointer1&#xff08;算子&#xff09;描述参数get_image_pointer1&#xff08;算子&#xff09; get_image_pointer1 - 访问单通道图像的指针。 get_image_pointer1(Image : : : Pointer, Type, Width, Height) 描述 运算符get_image_pointer1返回指向图像I…

如何传输文件到linux服务器?

我们知道&#xff0c;云主机文件传输是一件相对复杂的事情&#xff0c;经常需要搭建FTP服务器或者是借助其他工具来完成。下面为大家介绍一种简单易操作的传输文件到Linux服务器的方法。 Linux文件传输同Windows文件传输一样&#xff0c;我们为每一台Linux主机配置了一个1G的网…

C++学习笔记(五)--指针、NULL、引用

1. C中已经定义了NULL为0:#define NULL 0 指针p可以指向空值NULL即 p NULL;表示该指针变量不指向任何变量。   注意&#xff1a;指针未初始化与指针为NULL不同&#xff0c;   p NULL;是有值的&#xff0c;为0&#xff1b;   而在定义时&#xff1a;int *p;这时候碎虽然…

Sort函数的用法

快速排序sort的用法&#xff1a;&#xff08;适用于int float double char 。。。&#xff09; 记得加头文件&#xff01; 记得加头文件&#xff01; 记得加头文件&#xff01; 头文件&#xff1a; #include <algorithm> using namespace std ; // 两行都要写 数组排…

crf与bitrate对照表

crf与bitrate对照表 (2011-06-21 17:45:59)一些关于crf的备忘&#xff1a; 1、相较于bitrate方式&#xff0c;cpu占用与内存占用均会下降&#xff1b; 2、锐化滤镜会让crf的码率上升&#xff1b; 3、vbv对crf依然有效&#xff1b; 4、crf18就接近无损&#xff0c;字幕组惯用20-…

秒杀多线程第三篇 原子操作 Interlocked系列函数

上一篇《多线程第一次亲密接触 CreateThread与_beginthreadex本质区别》中讲到一个多线程报数功能。为了描述方便和代码简洁起见&#xff0c;我们可以只输出最后的报数结果来观察程序是否运行出错。这也非常类似于统计一个网站每天有多少用户登录&#xff0c;每个用户登录用一个…

Vue 教程第九篇—— 动画和过度效果

过渡效果 SPA 中组件的切换有一种生硬的隐藏显示感觉&#xff0c;为了更好的用户体验&#xff0c;让组件切换时淡出淡入&#xff0c;Vue 提供了专门的组件 transition。 过滤效果应用场景 条件渲染 (使用 v-if)条件展示 (使用 v-show)动态组件组件根节点过渡状态 enter&#xf…

halcon create_ocr_class_svm 使用SVM分类器创建OCR分类器

目录create_ocr_class_svm&#xff08;算子&#xff09;描述参数create_ocr_class_svm&#xff08;算子&#xff09; create_ocr_class_svm - 使用支持随机向量机制创建OCR分类器。 create_ocr_class_svm&#xff08;:: WidthCharacter&#xff0c;HeightCharacter&#xff0…

码率跟视频质量有关系

码率跟视频质量有关系.首先要清楚, 相同的视频编码方式下, 码率越高肯定画面越清晰. 但是高到一定值, 再往上的画面改善程度就不明显了, 只会增大文件体积. 所以码率选的合适, 才可以保证清晰度又保持文件不会太大. 个人经验如果是h.264编码(当前最好的视频压缩编码方案), …