回 帖 发 新 帖 刷新版面

主题:MFC学习进阶02

大家好,上一次我们主要是学习了WIN32 API编程的主要特点,今天我们用一个具体的MFC运用程序来理解

MFC是建立在WIN32 API上的。
这是一个称作Skeleton的框架性运用程序。它使用了创建一个MFC运用程序所需的最少代码。Skeleton除了

创建,管理一个主窗口外,不做任何事情。Skeleton可以完成的工作有:
。响应一个窗口的尺寸变化
。显示一个自定义图标
。最小化和最大化
。与其他运用程序一起共享系统资源
Skeleton主要包含以下的文件:
。StdAfx.h StdAfx.cpp .Skeleton.h Skeleton.cpp .MainFrame.h

MainFrame.cpp .Resource.h Skeleton.rc

下面分别就每个文件进行简单的讲述:
1。StdAfx.h:
这个文件是用来帮助生成预编译头文件的。其源代码为:

//the file of StdAfx.h
#ifndef _STDAFX_H_
#define _STDAFX_H_

#include<AfxWin.h>
#include<AfxExt.h>

#endif

可以看得出,这个文件里面只是包含了两个头文件。(有人肯定会想,就包含几个头文件还要一个

专门的文件,有费马达又费电?但是这里有一个实际情况要考虑,那就是几乎每一个MFC程序都要这些相同

的代码,那么每写一个程序就要重新输入,编译。而这个文件就避免了这个问题。看来该留)


2。StdAfx.cpp
这个文件用来存放StdAfx.h的源代码。其清单为:

//the file of StdAfx.cpp
#include"StdAfx.h"

因为这是一个最简单的程序,所以没有其他代码,只是把文件包含进来。

3。Skeleton.h
这个文件创建了一个运用程序核心的对象:运用程序对象。这个对象管理者运用程序的总体操作,

在这个程序中主要完成创建一个主窗口,因为它是后台操作,所以不可见.
其清单为:

//file of Skeleton.h

#ifndef _SKELETON_H_
#define _SKELETON_H_

//CSkeletonApp class-Skeleton Application Object

class CSkeletonApp:public CWinApp
{
    public:
        CSkeletonApp();
        virtual ~CSkeletonApp();
        
    public:
        virtual BOOL InitInstance();
    
    protected:
        DECLARE_MESSAGE_MAP()
        //the last method has no ';'
};//end of class CSkeletonApp

#endif

其实现文件清单为:

//the file of Skeleton.cpp

#include"StdAfx.h"
#include"Skeleton.h"
#include"MainFrame.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[]=__FILE__;
#endif

CSkeletonApp theApp;

BEGIN_MESSAGE_MAP(CSkeletonApp,CWinApp)
END_MESSAGE_MAP()

CSkeletonApp::CSkeletonApp(){
}

CSkeletonApp::~CSkeletonApp(){
}

BOOL CSkeletonApp::InitInstance()
{
    m_pMainWnd=new CMainFrame;
    ASSERT(m_pMainWnd);
    if(((CMainFrame*)m_pMainWnd)->Create(NULL,NULL))
    {
        m_pMainWnd->ShowWindow(m_nCmdShow);
        m_pMainWnd->UpdateWindow();
        return TRUE;
    }//end of if
    
    return FALSE;
}//END OF CSkeletonApp::IninInstance


这个文件创建了一个应用程序对象CSkeletonApp,从CWinApp继承来。这其中的InitInstance用来初始化一个

程序,一个程序的初始化包括两部分,一是首次初始化,一是后继初始化。首次初始化是在程序第一次运行

的时候调用的,而当每次程序拷贝运行时,包括第一次都要进行后继初始化,重载InitInstance来初始化。
InitInstance()是被WinMain()调用来初始化的。

这个运用程序对象的InitInstance方法创建了一个窗口对象。并用Create()来完成实际创建工作。当调用

ShowWindow,UpdataWindow绘制程序后,初始化工作完成。

4。MainFrame.h和MainFrame.cpp
这个创建了一个主窗口。用宏定义DECLARE_MESSAGE_MAP为类定义了一个消息映射表,指明如何处

理消息。这个消息映射表的入口放在MainFrame.cpp文件的BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间。
头文件的DECLARE_DYNCREATE宏来使MFC对象能够在运行时动态创建。DECLARE_MESSAGE_MAP和

IMPLEMEN_DYNCREATE成对出现,而且是要动态创建必需的。
其清单为:
//the file of  MainFrame.h

#ifndef _MAINFRAME_H_
#define _MAINFRAME_H_

class CMainFrame:public CFrameWnd
{
    public:
        CMainFrame();
        virtual ~CMainFrame();
    public:
        BOOL Creat(const CString& sTitle);
    protected:
        DECLARE_MESSAGE_MAP()
        DECLARE_DYNCREATE(CMainFrame)
};//end of class CMainFrame

#endif


//the file of MainFrame.cpp

#include"StdAfx.h"
#include"MainFrame.h"
#include"Resource.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[]=__FILE__;
#endif

BEGIN_MESSAGE_MAP(CMainFrame,CFrameWnd)
END_MESSAGE_MAP()

IMPLEMENT_DYNCREATE(CMainFrame,CFrameWnd)

CMainFrame::CMainFrame()
{
}//end of method CMainFrame

CMainFrame::~CMainFrame()
{
}//end of method ~CMainFrame

BOOL CMainFrame::Create(const CString& sTitle)
{
    CString sClassName;
    sClassName=AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,::LoadCursor(NULL,IDC_ARROW),
    

(HBRUSH)(COLOR_WINDOW+1),::LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_SKELETON)));
    
    return CFrameWnd::Create(sClassName,sTitle);
}//end of method Create

5。Resource.h和Skeleton.rc
Resoutce.h文件包含了运用程序中的资源(如:图标)的表示符。
其清单为:

//the file of Resource.h

#define IDR_SKELETON 1000

虽然只有一行,但它定义了一个资源的标示符
Skeleton.rc文件使用Icon语句Skeleton图标。
其清单为:
//the file of Skeleton.rc
#include"AfxRes.h"
#include"Resource.h"

IDR_SKELETON ICON"Skeleton.ico"

STRINGTABLE
BEGIN
    AFX_IDS_APP_TITLE"Skeleton v1.0"
END
这一次通过具体的代码,讲述了一个典型的运用程序的源程序框架。好,就到这吧!

回复列表 (共16个回复)

沙发

老兄干得很好请继续努力我支持你~~~!!!

板凳

谢谢!

3 楼

好·········!!!!!!

4 楼

这里我再来提一下重点:

1.AFXWIN.H这是一个很重要的头文件,你在MFC中所用到的类基本上都是在这里定义的,不信你可以看一下在VC6下的源文件.

2.对于CWINAPP类重要的就是这个InitInstance();只要记住我们如果想变换程序的外观,就得重载这个函数,因为这个函数是产生窗口的地方.它首先调用InitApplication,这个是程序只初使化一次的地方,然后调用InitInstance()来为每一个实例进行初使化,在这里调用Frame::Create()来产生窗口.
   这里我尽量挑大家熟悉的说,其实实际情况比这个复杂,但是我这样讲并不违背本意,只不过把一些不熟悉的地方省了.

3.CFrameWnd类
    里面最重要的就是Create()函数,看其源代码,可知窗口类的注册,窗口资源的连接都在里面完成.但我们通常都重载另一个函数,PreCreateWindow(),因为很多时候都是由Create()函数调用PreCreateWindow()来完成注册.

5 楼

顶!~~~~

6 楼

谢谢拉,GOOD LUCK!正 看 着 呢。

7 楼

楼主,我想问点小问题
1.    if(((CMainFrame*)m_pMainWnd)->Create(NULL,NULL))
这句为什么要把对象m_pMainWnd转换成指针,这里我不明白一点,指针和对象有什么联系,难道只有指针可以引用Create()?可以m_pMainWnd.Create()来使用吗?

2.    AfxRegisterWndClass(CS_HREDRAW|CS_VREDRAW,::LoadCursor(NULL,IDC_ARROW),
    (HBRUSH)(COLOR_WINDOW+1),::LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDR_SKELETON)));
这句是什么意思,这么长的函数,能给讲讲吗?

3.    对楼主的工作表示12分的敬意!

8 楼

第一个问题,m_pMainWnd本身就是个指针,实际上比较规范的写法是CMainFrame *m_pMainWnd=new CMainFrame;但如果不用这个(((CMainFrame*)转换,编译器不过

第二个问题,这是一个注册窗口类的API,参数1是指窗口在宽度,高度改变是重绘,第二个就是指定光标样子,第三是画刷,第四是图标,第五是指定诸如菜单,工具栏之类的资源

9 楼

对楼主的工作表示12分的敬意!

10 楼

支持

我来回复

您尚未登录,请登录后再回复。点此登录或注册