如何看MFC程序代码

如何看MFC程序代码,第1张

如何看MFC 程序代码 看下面内容之前,建议你学学《深入浅出MFC》,这本书强烈推荐! 现在只是做个了解。不妨做个知识备份! 在MFC 程序中,我们并不经常直接调用Windows API,而是从MFC 类创建对象并调用属于这些对象的成员函数也就是说MFC 封装了Windows API 你说你喜欢C++而MFC 换一种说法就是一个用C++写的一个函数库然后你来调用只不过这个类不是你写的MFC 提供数百个类,最重要的、也是编写任何VC++应用程序都必不可少的两个类CWinApp 和CFrameWnd,这两个类是编写复杂庞大应用程序的基石。1 封装特性:构成MFC 框架的是MFC 类库而MFC 类库又是C++的一个类库。这些类封装WIN32 应用程序编程接口,OLE(Object Link Embed 对象链接嵌入) 特性,ODBC 和DAO 数据访问的功能。2 继承特性:MFC 抽象出了众多类的共同特性,并设计出一些基类作为实现其他类的基础,这些类中最重要的类是 CObject 类和CCmdTarget 类,程序员可以从适当的MFC 类中派生出自己的类,实现特定的功能达到编程的目的。3 虚拟和消息映射:MFC 是以C++为基础,当然支持虚函数,但作为一个编程框架必须要解决的是效率问题:如果MFC 仅仅通过虚函数来支持动态约束必然会产生大量的虚函数表这样编程框架过于臃肿而且消耗更多的内存。但是MFC 建立了消息映射机制这样降低了内存的使用却大大提高了效率消息映射是一个将消息和成员函数相互关联的表,当应用程序的框架窗口接收到一个消息时,MFC 将搜索该窗口的消息映射,如果存在一个处理消息的处理程序,那么就调用该处理程序它通过宏来实现消息到成员函数的映射,而且这些函数不必是虚拟的成员函数,这样不需要为消息映射函数生成一个很大的虚拟函数表(V 表),节省内存。MFC 消息映射机制:将消息与消息处理函数联系起来,形成一一对应的机制。消息映射宏声明:DECLARE_MESSAGE_MAP 定义:BEGIN_MESSAGE_MAP ON_COMMAND ON_CONTROL ON_MESSAGE END_MESSAGE_MAP MFC 主要组成部分:类、宏和全局函数。类是MFC 中最主要的内容。MFC 类是以层次结构方式组织起来的。MFC 中的类分成两部分,除了一些辅助类,大多数的MFC 类是直接或间接从根类CObject 派生而来。MFC 宏主要功能:消息映射、运行时对象类型服务、诊断服务、异常处理。MFC 约定:全局函数以"Afx"为前缀,全局变量以"afx"为前缀MFC 类的层次关系CObject 项目类)-CCmdTarget(消息响应类)-{CWinThread(线程类)-CWinApp(Window 应用程序类)CDocument(文档类)CWnd(窗体类)-[CFrameWnd(框架类)CView(视图类)]}CObject 类由于MFC 中大部分类是从CObject 类继承而来的,CObject 类描述了几乎所有的MFC 类的一些公共特性,CObject 类为程序员提供了对象诊断、运行时类型识别和序列化等功能。CCmdTarget 类由CObject 类直接派生而来,它负责将消息发送到能够响应这些消息的对象。它是所有能进行消息映射的MFC 类的基类。CWinApp 类在任何MFC 应用程序中有且仅有一个CWinApp 派生类的对象,它代表了程序中运行的主线程,也代表了应用程序本身。CWinApp 类取代了WinMain()主函数在SDK 应用程序中的地位。传统SDK 应用程序 WinMain()函数完成的工作。现在由类CWinApp 的InitApplication(), InitInstance()和Run()三个成员函数承担。CWnd 类由CCmdTarget 类直接派生而来,该类及其派生类的实例是一个窗口。CWnd 类代表了MFC 中最基本的GUI 对象,它是一个功能最完善、成员函数最多的MFC 类。CFrameWnd 类是CWnd 类的派生类,主要用来掌管一个窗口,它取代了SDK 应用程序中窗口函数 WndProc()的地位。CFrameWnd 类的对象是一个框架窗口,包括边框、标题栏、菜单、最大化按钮、最小化按钮和一个激活的视图。CDocument 类在应用程序中作为用户文档类的基类,它代表了用户存储或打开的一个文件。CView 类是 MFC 中一个很基本的类,它作为其它MFC 视图类和用户视图派生类的基类。从 API 编程到MFC 编程的过渡:WinMain(){初始化WNDCLASS 注册窗体结构创建窗口-应用程序类CWinApp 显示窗口消息循环}WndProc(){switch(…){case:…}- 框架窗口类CFrameWnd}MFC Object 和Windows Object 的对应关系:描述 Windows 句柄MFC Object 窗口HWND CWnd 设备上下文HDC CDC 菜单HMENU CMenu 笔HPEN CPen 刷子HBRUSH CBrush 字体HFONT CFont 位图HBITMAP CBitmap 套接字SOCKET CSocket 三、手工创建一个MFC 应用程序:注意:创建 MFC 程序,要创建一个Win32 空项目,并要选择项目属性中的"在共享DLL 文件中使用MFC,然后新建我们的文件例子:在"helloh"头文件中添写如下代码: class CMyApp:public CWinApp{public:virtual BOOL InitInstance();// 虚函数};class CMainWindow:public CFrameWnd{public:CMainWindow(); protected:afx_msg void OnPaint();DECLARE_MESSAGE_MAP();//声明消息映射};在"hellocpp"源文件中添写如下代码:#include afxwinh#include"helloh"CMyApp myApp;BOOL CMyApp: InitInstance(){m_pMainWnd=new CMainWindow;m_pMainWnd- ShowWindow(m_nCmdShow);m_pMainWnd-UpdateWindow();return TRUE;}BEGIN_MESSAGE_MAP(CMainWindow,CFrameWnd)ON_WM_PAINT()END_MESSA GE_MAP()//消息映射CMainWindow:CMainWindow()//构造函数初始化 {Create(NULL,"我的第一个MFC 应用程序");//创建窗体}void CMainWindow: OnPaint(){CPaintDC dc(this);CRect rect;GetClientRect(&rect); dcDrawText("Hello MFC",- 1,&rect,DT_SINGLELINE|DT_CENTER|DT_VCENTER);}CWinApp 是应用程序类,在MFC 应用程序中必须从这个类派生出一个类,该派生类是MFC 应用程序的入口必须定义这个派生类的对象,并且只能有一个这个对象代表整个应用程序。成员函数:InitInstance()功能:初始化应用程序实例和窗口实例,虚函数 CWinApp:InitInstance 必须在派生类中重写。在InitInstance 函数中,编写初始化代码,如:创建一个窗口显示一个窗口CFrameWnd 类作用:为应用程序提供一个窗口,同时实现消息处理功能。成员函数:Create()功能:创建窗体, 将之赋于CFrameWnd 对象上。BOOL Create(窗口类型,窗口标题,显示风格,显示区域,符窗口句柄,菜单,扩展显示风格,上下文对象)共有8 个参数,前两个必须给出,后6 个可以默认。MFC 应用程序的核心就是基于CWinApp 类的应用程序对象,CWinApp 提供了消息循环来检索消息并将消息调度给应用程序的窗口我们在编写MFC 应用程序时,要包含afxwinh,一个MFC 应用程序可以有且仅有一个应用程序对象,对象必须声明为在全局范围内有效(也就是全局对象), 以便它在程序开始时即在内存中被实例化我们的Hello MFC 的应用程序类被命名为CMyApp,它在hellocpp 中用如下语句进行了实例化:CMyApp myApp; CMyApp 的类声明在helloh 中代码如下:class CMyApp:public CWinApp{public:virtual BOOL InitInstance();};CMyApp 没有声明任何的数据成员,只是重写了一个从CWinApp 类中继承来的函数,在应用程序的生存期内InitInstance 的调用比较早,是在应用程序开始运行以后而窗口创建之前,除非InitIstance 创建一个窗口,否则应用程序是不会有窗口,这正是为什么即使最小的MFC 应用程序也必须从CWinApp 派生出一个类并重写CWinApp: InitIstance 的原因InitInstance 函数:CWinApp:InitInstance 是一个虚函数,其默认 *** 作仅包含一条语句:return TRUE;InitInstance 是用来执行程序每次开始时都需要进行的初始化工作最好的地方在hellocpp 中,CMyApp 的 InitInstance 通过实例化hello 的CMainWindow 类来创建hello 窗口,语句: m_pMainWnd=new CMainWindow;构造了一个CMainWindow 对象指针,并将其地址复制到了应用程序对象的m_pMainWnd 数据成员中,窗口创建以后,InitInstance 就会通过CMainWindow 指针调用ShowWindow 和UpdateWindow 函数显示它: m_pMainWnd-ShowWindow(m_nCmdShow);m_pMainWnd-UpdateWindow(); ShowWindow 和UpdateWindow 是所有窗口对象共用的CWnd 成员函数其中包括 CFrameWnd 类的对象,CMainWindow 就是从CFrameWnd 派生出来的要从MFC 程序调用一个常规的Windows API 函数,需要在函数名称前添加一个全局运算符:例如::UpdateWindow();通过生成窗口对象并调用其Create 函数,MFC 应用程序可以创建一个窗口,在CMyApp:InitInstance 中,hello 创建了一个 CMainWindow 对象,CMainWindow 的构造函数生成在屏幕上看到的窗口: Create(NULL,"我的第一个MFC 应用程序");CPaintDC dc(this);MFC 的 CPaintDC 类是从MFC 的CDC 类派生的,CDC 类封装了Windows 设备环境,以及包含了绘制到屏幕、打印机和其他设备的几十个成员函数在MFC 中如何处理消息呢在SDK 中我们利用的是消息循环和窗口过程函数对消息进行消息处理在 MFC 中我们用的是消息映射机制下面是将消息映射添加到一个类中需要做的全部工作1 通过将DECLARE_MESSAGE_MAP 语句添加到类声明中,声明消息映射2 通过放置标识消息的宏来执行消息映射,相应的类将在对BEGIN_MESSAGE_MAP 和 END_MESSAGE_MAP 的调用之间处理消息3 添加成员函数来处理消息1、构造 CWinApp 派生类的对象2、系统调用WinMain()3、WinMain 调用InitInstance, 在该函数中创建CFrameWnd 派生类对象,调用Create 函数创建窗口、调用 ShowWindow 函数显示窗口。4、之后内部机制调用Run,接受用户的消息,并将消息导向默认的处理函数。当接收到WM_QUIT 消息时,Run 内部调用 ExitInstance,退出程序。MFC 采用消息映射(Message Map)机制取代C/C++语言中的switch-case 结构来处理消息。消息映射:在MFC 中把消息处理函数和它所要处理的特定的消息连接起来的一种机制。它通过宏来实现消息到成员函数的映射,而且这些函数不必是虚拟的成员函数,这样不需要为消息映射函数生成一个很大的虚拟函数表(V 表),节省内存。MFC 消息映射机制包括一组消息映射宏。一条消息映射宏把一个Windows 消息和其消息处理函数联结起来。MFC 应用程序框架提供了消息映射功能。在类的实现源文件中用 BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP()宏来定义消息映射。在类定义的结尾用DECLARE_MESSAGE_MAP()宏来声明使用消息映射。

如果子对话框是模态对话框(domodal),那么子对话框是无法在d出后“调用”父对话框的控件变量的。你只能在domodal之前,通过一个子对话框的自定义成员变量传递过去。

举个栗子:

cxxdlg dlg;

updatedate(true);

dlgmy_str = m_edit1;

dlgdomodal();

用的较多的是:CWnd::GetDlgItem再使用CWnd::GetWindowText还有一个是 CWnd::GetDlgItemText

这些都是比较常用的、

例如获取一个EDIT控件的文本,ID是IDC_EDITRESULT

第一种方式:

CString str_edit;

GetDlgItem(IDC_EDITRESULT)->GetWindowText(str_edit);

第二种方式:

CString str_edit;

GetDlgItemText(IDC_EDITRESULT,str_edit);

具体看MSDN

用类向导给这个ID为IDC_COURSE_COMBO的控件添加两个成员变量,一个变量名用m_strType,选项分别选Value和CString,另一个变量名用m_cmdType,选项分别选Control和CComboBox。

用MFC制作的工程由很多文件构成,它不能象一般C++程序那样随意在类外定义全局变量,在这里要想定义能被工程内多个文件共享的全局变量和函数必须用一些特殊方法才行。实际上有多种方法可以实现,这里只介绍两种方法。

一、在应用程序类中定义

用MFC生成的工程中都有一个名为CxxxApp的类,它派生于CWinApp类。这个类主要进行程序的初始化,生成文档、视图对象等工作。我们可以把需要全局访问的变量和函数定义为这个类的成员变量和成员函数,就可以实现全局访问了。

从严格意义上讲,这种变量和函数并不是全局的,因为它仍然只是类中的成员,只是由于我们很容易获得CxxxApp类的指针,所以我们可以在文档、视图、对话框以及各种自定义类中访问到它们,达到与全局变量类似的效果。访问时用函数“AfxGetApp()”获得CxxxApp类的指针,用“AfxGetApp()->成员”访问变量或函数。

例:

Testh:(应用程序类头文件)

class CTestApp : public CWinApp

{

  public:

int x; //全局变量

int f(int y); //全局函数

…………

};

Testcpp:(应用程序类程序文件)

int CTestApp::f(int y) //全局函数定义

{

  y++;

  return y;

}

定义在CTestApp类中的变量和函数可以在其它类中被访问。比如在视图的某函数中要访问变量x和函数f():

void CTestView::xyz()

{

  CTestApp app = (CTestApp )AfxGetApp(); //生成指向应用程序类的指针

  app->x = 0; //访问变量x

  int z = app->f(1); //访问函数f()

  …………

}

这样,变量x和函数f()可以视作为全局的。

用这种方法实现的全局变量和全局函数虽比较简单,但也有缺点,一是访问不太方便,每次都需要获取应用程序类的指针;再就是把一些与应用程序类本身无关的变量和函数放在里面,使这个类看上去怪怪的,破坏了类的封装。

二、用静态变量和静态函数实现

很喜欢API函数的那种调用方法,不论在哪个类中只要用“::API函数”就可以调用了。合理利用静态类型(static)可以实现与此相似的全局变量和全局函数。

静态变量和静态函数有如下性质:

若在一个类中用关键字static声明数据成员,则这个数据成员就只存在一个拷贝,无论该类创建了多少个实例,它始终只存在一个,即使该类的实例一个也没创建,它也存在。

若在一个类中用关键字static声明函数,该函数可以用“类名::函数名”方式访问,无需引用该类的实例,甚至这个类的实例可以不存在。

利用这个性质实现的全局变量和函数使用起来很方便。

值得注意的是,全局变量和全局函数最好集中封装,不要在文档、视图等类内部定义,这样用起来才有全局的感觉。

例:

1、添加一个没有基类的新类,设类名起为CPublic,姑且称之为公用类

单击“Insert”菜单下的“New Class”命令,选择“Class type”为“Generic Class”,在“Name”栏中填入类名“CPublic”,单击“OK”,则新类建立完毕。

2、包含公用类的头文件,使各个类都能访问它

CPublic的头文件应包含在应用程序类的头文件中,这样在其它类中引用CPublic类时就不需要再包含了。

Testh:(应用程序类头文件)

#include "Publich" //包含公用类头文件

class CTestApp : public CWinApp

{

…………

};

3、在公用类中定义全局变量和全局函数,均使用static修饰,静态变量还必须在类外定义和初始化

Publich:(公用类头文件)

class CPublic

{

public:

CPublic();

virtual ~CPublic();

public:

static int x; //全局变量

static int time; //全局变量

static int f(int y); //全局函数

…………

}

在公用类中对静态变量进行初始化和定义函数体:

Publiccpp:(公用类程序文件)

int CPublic::x = 0; //初始化全局变量

int CPublic::time; //定义全局变量

CPublic::CPublic()

{

}

CPublic::~CPublic()

{

}

int CPublic::f(int y) //全局函数,这里不要再加static

{

y++;

return y;

}

4、全局量的使用

使用变量:CPublic::变量名

使用函数:CPublic::函数()

如在视图的某函数中访问变量x和函数f():

void CTestView::xyz()

{

CPublic::x = 0; //访问变量x

CPublic::time = CPublic::f(1); //访问函数f()

…………

}

在其它类中访问x、time和f()的方法与此相同。

5、几点注意:

① 由于静态量可独立于类存在,不需要生成CPublic类的实例。

② 静态数据成员的定义和初始化必须在类外进行,如例中x的初始化;变量time虽然没有初始化,但也必须在类外进行定义。由于没有生成CPublic类的实例,所以它的构造函数和析构函数都不会被执行,在里面做什么工作都没有什么意义。

③ 如果静态函数需要访问CPublic类内的变量,这些变量也必须为静态的。因为非静态量在不生成实例时都不会存在。 如:

class CPublic

{

public:

int x; //内部变量

static int f(int y) //全局函数

{

x++;

return x;

};

…………

};

这里x虽为类内成员,但如果不生成CPublic类的实例,就会出现函数f()存在,而变量x不存在的问题。

总之,用没有实例的类管理全局量是一个不错的选择,它具有集中管理,使用方便的好处。当然,除非特别必要,全局量还是少用为好,一个好的编程者决不会随意滥用全局量的,一个封装做得不好的程序,在修改维护时会让你吃足苦头。

int _tmain(int argc, TCHAR argv[], TCHAR envp[]) 这是带MFC功能的控制台程序主函数声明,其中argc是输入参数个数;argv[]是参数字符串数组;envp[]是环境变量字符串数组,下面是取得和显示他们的代码://注意:必须设置此项才能输出宽字符串 _tsetlocale(LC_ALL, _T("chs")); _tprintf(_T("参数: %d 个\n"),argc);//显示参数个数 _tprintf(_T("\n"));//换行 //显示所有参数 for (int i=0; i<argc; ++i) { _tprintf(_T("输入参数 [%d] = [%s]\n"), i, argv[i]); } _tprintf(_T("\n"));//换行 //显示环境变量 for (int i=0; i<argc; ++i) { _tprintf(_T("环境变量 [%d] = [%s]\n"), i, envp[i]); } _tsystem(_T("pause"));//使DOS窗口暂停,不马上退出

以上就是关于如何看MFC程序代码全部的内容,包括:如何看MFC程序代码、mfc中父对话框变量获取子对话框控件的变量、vs2010中,MFC基于对话框的编程,在一个对话框中想要获取其他对话框中变量的值,要怎么做等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9672086.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存