文档库 最新最全的文档下载
当前位置:文档库 › MFC的CObject类详解

MFC的CObject类详解

MFC的CObject类详解
MFC的CObject类详解

3.CObject类

CObject是大多数MFC类的根类或基类。CObject类有很多有用的特性:对运行时类信息的支持,对动态创建的支持,对串行化的支持,对象诊断输出,等等。MFC从CObject派生出许多类,具备其中的一个或者多个特性。程序员也可以从CObject类派生出自己的类,利用CObject类的这些特性。

本章将讨论MFC如何设计CObject类的这些特性。首先,考察CObject 类的定义,分析其结构和方法(成员变量和成员函数)对CObject特性的支持。然后,讨论CObject特性及其实现机制。

1.CObject的结构

以下是CObject类的定义:

class CObject

{

public:

//与动态创建相关的函数

virtual CRuntimeClass* GetRuntimeClass() const;

析构函数

virtual ~CObject(); // virtual destructors are necessary

//与构造函数相关的内存分配函数,可以用于DEBUG下输出诊断信

void* PASCAL operator new(size_t nSize);

void* PASCAL operator new(size_t, void* p);

void PASCAL operator delete(void* p);

#if defined(_DEBUG) && !defined(_AFX_NO_DEBUG_CRT)

void* PASCAL operator new(size_t nSize, LPCSTR lpszFileName,

int nLine);

#endif

//缺省情况下,复制构造函数和赋值构造函数是不可用的

//如果程序员通过传值或者赋值来传递对象,将得到一个编译错误

protected:

//缺省构造函数

CObject();

private:

//复制构造函数,私有

CObject(const CObject& objectSrc); // no implementation

//赋值构造函数,私有

void operator=(const CObject& objectSrc); // no implementation

// Attributes

public:

//与运行时类信息、串行化相关的函数

BOOL IsSerializable() const;

BOOL IsKindOf(const CRuntimeClass* pClass) const;

// Overridables

virtual void Serialize(CArchive& ar);

// 诊断函数

virtual void AssertValid() const;

virtual void Dump(CDumpContext& dc) const;

// Implementation

public:

//与动态创建对象相关的函数

static const AFX_DATA CRuntimeClass classCObject;

#ifdef _AFXDLL

static CRuntimeClass* PASCAL _GetBaseClass();

#endif

};

由上可以看出,CObject定义了一个CRuntimeClass类型的静态成

员变量:

CRuntimeClass classCObject

还定义了几组函数:

构造函数析构函数类,

诊断函数,

与运行时类信息相关的函数,

与串行化相关的函数。

其中,一个静态函数:_GetBaseClass;五个虚拟函数:析构函数、

GetRuntimeClass、Serialize、AssertValid、Dump。这些虚拟函

数,在CObject的派生类中应该有更具体的实现。必要的话,派生

类实现它们时可能要求先调用基类的实现,例如Serialize和Dump

就要求这样。

静态成员变量classCObject和相关函数实现了对CObjet特性的支

持。

2.CObject类的特性

下面,对三种特性分别描述,并说明程序员在派生类中支持这些特性的方法。

1.对运行时类信息的支持

该特性用于在运行时确定一个对象是否属于一特定类(是该类的实例),或者从一个特定类派生来的。CObject提供IsKindOf函数来实现这个功能。

从CObject派生的类要具有这样的特性,需要:

定义该类时,在类说明中使用DECLARE_DYNAMIC(CLASSNMAE)宏;

?在类的实现文件中使用IMPLEMENT_DYNAMIC(CLASSNAME,BASECLASS)宏。

1.对动态创建的支持

前面提到了动态创建的概念,就是运行时创建指定类的实例。在MFC中大量使用,如前所述框架窗口对象、视对象,还有文档对象都需要由文档模板类(CDocTemplate)对象来动态的创建。

从CObject派生的类要具有动态创建的功能,需要:

?定义该类时,在类说明中使用DECLARE_DYNCREATE(CLASSNMAE)宏;

?定义一个不带参数的构造函数(默认构造函数);

?在类的实现文件中使用IMPLEMENT_DYNCREATE(CLASSNAME,BASECLASS)宏;

?使用时先通过宏RUNTIME_CLASS得到类的RunTime信息,然后使用CRuntimeClass的成员函数CreateObject创建一个该类的实例。

例如:

CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CNname)

//CName必须有一个缺省构造函数

CObject* pObject = pRuntimeClass->CreateObject();

//用IsKindOf检测是否是CName类的实例

Assert( pObject->IsKindOf(RUNTIME_CLASS(CName));

1.对序列化的支持

“序列化”就是把对象内容存入一个文件或从一个文件中读取对象内容

的过程。从CObject派生的类要具有序列化的功能,需要:

?定义该类时,在类说明中使用DECLARE_SERIAL(CLASSNMAE)宏;

?定义一个不带参数的构造函数(默认构造函数);

?在类的实现文件中使用IMPLEMENT_SERIAL(CLASSNAME,BASECLASS)宏;

?覆盖Serialize成员函数。(如果直接调用Serialize函数进行序列化读写,可以省略前面三步。)

对运行时类信息的支持、动态创建的支持、串行化的支持层(不包括直接调用Serailize实现序列化),这三种功能的层次依次升高。如果对后面的功能支持,必定对前面的功能支持。支持动态创建的话,必定支持运行时类信息;支持序列化,必定支持前面的两个功能,因为它们的声明和实现都是后者包含前者。

1.综合示例:

定义一个支持串行化的类CPerson:

class CPerson : public CObject

{

public:

DECLARE_SERIAL( CPerson )

// 缺省构造函数

CPerson(){}{};

CString m_name;

WORD m_number;

void Serialize( CArchive& archive );

// rest of class declaration

};

实现该类的成员函数Serialize,覆盖CObject的该函数:void CPerson::Serialize( CArchive& archive )

{

// 先调用基类函数的实现

CObject::Serialize( archive );

// now do the stuff for our specific class

if( archive.IsStoring() )

archive << m_name << m_number;

else

archive >> m_name >> m_number;

}

使用运行时类信息:

CPerson a;

ASSERT( a.IsKindOf( RUNTIME_CLASS( CPerson ) ) );

ASSERT( a.IsKindOf( RUNTIME_CLASS( CObject ) ) );

动态创建:

CRuntimeClass* pRuntimeClass = RUNTIME_CLASS(CPerson)

//Cperson有一个缺省构造函数

CObject* pObject = pRuntimeClass->CreateObject();

Assert( pObject->IsKindOf(RUNTIME_CLASS(CPerson));

1.实现CObject特性的机制

由上,清楚了CObject的结构,也清楚了从CObject派生新类时程

序员使用CObject特性的方法。现在来考察这些方法如何利用

CObjet的结构,CObject结构如何支持这些方法。

首先,要揭示DECLARE_DYNAMIC等宏的内容,然后,分析这些宏的

作用。

1.DECLARE_DYNAMIC等宏的定义

MFC提供了DECLARE_DYNAMIC、DECLARE_DYNCREATE、DECLARE_SERIAL声明宏的两种定义,分别用于静态链接到MFC DLL和动态链接到MFC DLL。对应的实现宏IMPLEMNET_XXXX也有两种定义,但是,这里实现宏就不列举了。

MFC对这些宏的定义如下:

#ifdef _AFXDLL //动态链接到MFC DLL

#define DECLARE_DYNAMIC(class_name) \

protected: \

static CRuntimeClass* PASCAL _GetBaseClass(); \

public: \

static const AFX_DATA CRuntimeClass class##class_name; \

virtual CRuntimeClass* GetRuntimeClass() const; \

#define _DECLARE_DYNAMIC(class_name) \

protected: \

static CRuntimeClass* PASCAL _GetBaseClass(); \

public: \

static AFX_DATA CRuntimeClass class##class_name; \

virtual CRuntimeClass* GetRuntimeClass() const; \

#else

#define DECLARE_DYNAMIC(class_name) \

public: \

static const AFX_DATA CRuntimeClass class##class_name; \

virtual CRuntimeClass* GetRuntimeClass() const; \

#define _DECLARE_DYNAMIC(class_name) \

public: \

static AFX_DATA CRuntimeClass class##class_name; \

virtual CRuntimeClass* GetRuntimeClass() const; \

#endif

// not serializable, but dynamically constructable

#define DECLARE_DYNCREATE(class_name) \

DECLARE_DYNAMIC(class_name) \

static CObject* PASCAL CreateObject();

#define DECLARE_SERIAL(class_name) \

_DECLARE_DYNCREATE(class_name) \

friend CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb);

由于这些声明宏都是在CObect派生类的定义中被使用的,所以从这些宏的上述定义中可以看出,DECLARE_DYNAMIC宏给所在类添加了一个CRuntimeClass类型的静态数据成员class##class_name(类名加前缀class,例如,若类名是CPerson,则该变量名称是classCPerson),且指定为const;两个(使用MFC DLL 时,否则,一个)成员函数:虚拟函数GetRuntimeClass和静态函数_GetBaseClass (使用MFC DLL时)。

DECLARE_DYNCREATE宏包含了DECLARE_DYNAMIC,在此基础上,还定义了一个静态成员函数CreateObject。

DECLARE_SERIAL宏则包含了_DECLARE_DYNCREATE,并重载了操作符“>>”(友员函数)。它和前两个宏有所不同的是CRuntimeClass数据成员

class##class_name没有被指定为const。

对应地,MFC使用三个宏初始化DECLARE宏所定义的静态变量并实现DECLARE宏所声明的函数:IMPLEMNET_DYNAMIC,IMPLEMNET_DYNCREATE,IMPLEMENT_SERIAL。

首先,这三个宏初始化CRuntimeClass类型的静态成员变量class#class_name。IMPLEMENT_SERIAL不同于其他两个宏,没有指定该变量为const。初始化内容在下节讨论CRuntimeClass时给出。

其次,它实现了DECLARE宏声明的成员函数:

?_GetBaseClass()

返回基类的运行时类信息,即基类的CRuntimeClass类型的静态成员变量。这是静态成员函数。

?GetRuntimeClass()

返回类自己的运行类信息,即其CRuntimeClass类型的静态成员变量。这是虚拟成员函数。

对于动态创建宏,还有一个静态成员函数CreateObject,它使用C++操作符和类的缺省构造函数创建本类的一个动态对象。

?操作符的重载

对于序列化的实现宏IMPLEMENT_SERIAL,还重载了操作符<<和定义了一个静态成员变量

static const AFX_CLASSINIT

_init_##class_name(RUNTIME_CLASS(class_name));

比如,对CPerson来说,该变量是_init_Cperson,其目的在于静态成员在应用程序启动之前被初始化,使得AFX_CLASSINIT类的构造函数被调用,从而通过

AFX_CLASSINIT类的构造函数在模块状态的CRuntimeClass链表中插入构造函数参数表示的CRuntimeClass类信息。至于模块状态,在后文有详细的讨论。

重载的操作符函数用来在序列化时从文档中读入该类对象的内容,是一个友员函数。定义如下:

CArchive& AFXAPI operator>>(CArchive& ar, class_name* &pOb)

{

pOb = (class_name*) ar.ReadObject(

RUNTIME_CLASS(class_name));

return ar;

}

回顾CObject的定义,它也有一个CRuntimeClass类型的静态成员变量classCObject,因为它本身也支持三个特性。

以CObject及其派生类的静态成员变量classCObject为基础,IsKindOf和动态创建等函数才可以起到作用。

这个变量为什么能有这样的用处,这就要分析CRuntimeClass类型变量的结构和内容了。下面,在讨论了CRuntimeClass的结构之后,考察该类型的静态变量被不同的宏初始化之后的内容。

1.CruntimeClass类的结构与功能

从上面的讨论可以看出,在对CObject特性的支持上,CRuntimeClass类起到了关键作用。下面,考查它的结构和功能。

1.CRuntimeClass的结构

CruntimeClass的结构如下:

Struct CRuntimeClass

{

LPCSTR m_lpszClassName;//类的名字

int m_nObjectSize;//类的大小

UINT m_wSchema;

CObject* (PASCAL* m_pfnCreateObject)();

//pointer to function, equal to newclass.CreateObject()

//after IMPLEMENT

CRuntimeClass* (PASCAL* m_pfnGetBaseClass)();

CRumtieClass* m_pBaseClass;

//operator:

CObject *CreateObject();

BOOL IsDerivedFrom(const CRuntimeClass* pBaseClass) const;

...

}

CRuntimeClass成员变量中有两个是函数指针,还有几个用来保存所在CruntimeClass对象所在类的名字、类的大小(字节数)等。

这些成员变量被三个实现宏初始化,例如:

m_pfnCreateObject,将被初始化指向所在类的静态成员函数

CreateObject。CreateObject函数在初始化时由实现宏定义,见上文的说明。

m_pfnGetBaseClass,如果定义了_AFXDLL,则该变量将被初始化指向所在类的成员函数_GetBaseClass。_GetBaseClass在声明宏中声明,在初始化时由实现宏定义,见上文的说明。

下面,分析三个宏对CObject及其派生类的CRuntimeClass类型的成员变量class##class_name初始化的情况,然后讨论CRuntimeClass成员函数的实现。

2.成员变量class##class_name的内容

IMPLEMENT_DYNCREATE等宏将初始化类的CRuntimeClass类型静态成员变量的各个域,表3-1列出了在动态类信息、动态创建、序列化这三个不同层次下对该静态成员变量的初始化情况:

表3-1 静态成员变量class##class_name的初始化

m_wSchema类型是UINT,定义了序列化中保存对象到文档的程序的版本。

如果不要求支持序列化特性,该域为0XFFFF,否则,不能为0。

Cobject类本身的静态成员变量classCObject被初始化为:

{ "CObject", sizeof(CObject), 0xffff, NULL,

&CObject::_GetBaseClass, NULL };

对初始化内容解释如下:

类名字符串是“CObject”,类的大小是sizeof(CObject),不要求支持序列化,不支持动态创建。

3.成员函数CreateObject

回顾3.2节,动态创建对象是通过语句pRuntimeClass->CreateObject 完成的,即调用了CRuntimeClass自己的成员函数,CreateObject函数又调用m_pfnCreateObject指向的函数来完成动态创建任务,如下所示:

CObject* CRuntimeClass::CreateObject()

{

if (m_pfnCreateObject == NULL) //判断函数指针是否空

{

TRACE(_T("Error: Trying to create object which is not ")

_T("DECLARE_DYNCREATE \nor DECLARE_SERIAL: %hs.\n"),

m_lpszClassName);

return NULL;

}

//函数指针非空,继续处理

CObject* pObject = NULL;

TRY

{

pObject = (*m_pfnCreateObject)(); //动态创建对象

}

END_TRY

return pObject;

}

4.成员函数IsDerivedFrom

该函数用来帮助运行时判定一个类是否派生于另一个类,被CObject的成员函数IsKindOf函数所调用。其实现描述如下:

如果定义了_AFXDLL则,成员函数IsDerivedFrom调用成员函数

m_pfnGetBaseClass指向的函数来向上逐层得到基类的CRuntimeClass类型的静态成员变量,直到某个基类的CRuntimeClass类型的静态成员变量和参数指定的CRuntimeClass变量一致或者追寻到最上层为止。

如果没有定义_AFXDLL,则使用成员变量m_pBaseClass基类的

CRuntimeClass类型的静态成员变量。

程序如下所示:

BOOL CRuntimeClass::IsDerivedFrom(

const CRuntimeClass* pBaseClass) const

{

ASSERT(this != NULL);

ASSERT(AfxIsValidAddress(this, sizeof(CRuntimeClass), FALSE));

ASSERT(pBaseClass != NULL);

ASSERT(AfxIsValidAddress(pBaseClass, sizeof(CRuntimeClass), FALSE));

// simple SI case

const CRuntimeClass* pClassThis = this;

while (pClassThis != NULL)//从本类开始向上逐个基类搜索

{

if (pClassThis == pBaseClass)//若是参数指定的类信息

return TRUE;

//类信息不符合,继续向基类搜索

#ifdef _AFXDLL

pClassThis = (*pClassThis->m_pfnGetBaseClass)();

#else

pClassThis = pClassThis->m_pBaseClass;

#endif

}

return FALSE; // 搜索完毕,没有匹配,返回FALSE。

}

由于CRuntimeClass类型的成员变量是静态成员变量,所以如果两个类的CruntimeClass成员变量相同,必定是同一个类。这就是IsDerivedFrom 和IsKindOf的实现基础。

5.RUNTIME_CLASS宏

RUNTIME_CLASS宏定义如下:

#define RUNTIME_CLASS(class_name)

(&class_name::class##class_name)

为了方便地得到每个类(Cobject或其派生类)的CRuntimeClass类型的静态成员变量,MFC定义了这个宏。它返回对类class_name的CRuntimeClass类型成员变量的引用,该成员变量的名称是“class”加上class_name(类的名字)。例如:

RUNTIME_CLASS(CObject)得到对classCObject的引用;

RUNTIME_CLASS(CPerson)得到对class CPerson的引用。

1.动态类信息、动态创建的原理

MFC对Cobject动态类信息、动态创建的实现原理:

动态类信息、动态创建都建立在给类添加的CRuntimeClass类型的静态成员变量基础上,总结如下。

C++不支持动态创建,但是支持动态对象的创建。动态创建归根到底是创建动态对象,因为从一个类名创建一个该类的实例最终是创建一个以该类为类型的动态对象。其中的关键是从一个类名可以得到创建其动态对象的代码。

在一个类没有任何实例之前,怎么可以得到该类的创建动态对象的代码?借助于C++的静态成员数据技术可达到这个目的:

?静态成员数据在程序的入口(main或WinMain)之前初始化。因此,在一个静态成员数据里存放有关类型信息、动态创建函数等,需要的时候,得到这个成员数据就可以了。

?不论一个类创建多少实例,静态成员数据只有一份。所有的类的实例共享一个静态成员数据,要判断一个类是否是一个类的实例,只须确认它是否使用了该类的这个静态数据。

从前两节的讨论知道,DECLARE_CREATE等宏定义了一个这样的静态成员变量:类型是CRuntimeClass,命名约定是“calss”加上类名;IMPLEMENT_CREATE等宏初始化该变量;RUNTIME_CLASS宏用来得到该成员变量。

动态类信息的原理在分析

CRuntimeClass的成员函数

IsDerivedFrom时已经作了解释。

动态创建的过程和原理了,用图表

示其过程如下:

注:下面一个方框内的逐级缩进表示逐层调用关

系。

1.序列化的机制

由上所述可知,一个类要支持实现序列化,使得它

的对象可以保存到文档中或者可以从文档中读入

到内存中并生成对象,需要使用动态类信息,而且,

需要覆盖基类的Serialize虚拟函数来完成其对象

的序列化。

仅仅有类的支持是不够的,MFC还提供了一个归档类CArchive来支持简单类型的数据和复杂对象的读写。

CArchive 在文件和内存对象之间充当一个代理者的角色。它负责按一定的顺序和格式把内存对象写到文件中,或者读出来,可以被看作是一个二进制的流。它和文件类CFile的关系如图3-2所示:

一个CArchive对象在要序列化的对象和存储媒体(storage medium,可以是一个文件或者一个Socket)之间起了中介作用。它提供了系列方法来完成序列化,不仅能够把int、float等简单类型数据进行序列化,而且能够把复杂的数据如string等进行序列化,更重要的是它能把复杂的对象(包括复合对象)进行序列化。这些方法就是重载的操作符>>和<<。对于简单类型,它针对不同类型直接实现不同的读写操作;对于复杂的对象,其每一个支持序列化的类都重载了操作符>>,从前几节可以清楚地看到这点:IMPLEMENT_SERIAL给所在类重载了操作符>>。至于<<操作,就不必每个序列化类都重载了。

复杂对象的“<<”操作,先搜索本模块状态的CRuntimeClass链表看是否有“<<”第二个参数指定的对象类的运行类信息(搜索过程涉及到模块状态,将在9.5.2节描述),如果有(无,则返回),则先使用这些信息动态的创建对象(这就是是序列化类必须提供动态类信息、支持动态创建的原因),然后对该对象调用Serilize函数从存储媒体读入对象内容。

复杂对象的“>>”操作先把对象类的运行类信息写入存储媒体,然后对该对象调用Serilize函数把对象内容写入存储媒体。

在创建CArchive对象时,必须有一个CFile对象,它代表了存储媒介。通常,程序员不必做这个工作,打开或保存文档时MFC将自动的创建CFile对象和

CArchive对象并在适当的时候调用序列化类的Serialize函数。在后面讨论打开(5.3.3.2节)或者关闭(6.1节)文档时将会看到这样的流程。

CArchive对象被创建时,需要指定它是用来读还是用来写,即指定序列化操作的方向。Serialize函数适用CArchive的函数IsStoring判定CArchive是用于读出数据还是写入数据。

在解释实现序列化的方法时,曾经提到如果程序员直接调用Serilize函数完成序列化,而不借助CArchive的>>和<<操作,则可以不需要动态类信息和动态创建。从上文的论述可以看出,没有CArchive的>>和<<操作,的确不需要动态类信息和动态创建特性。

mfc资料

你创建的是一个对话框程序,所以只有CMyApp 和CMyDlg 两个类。 但如果创建的是个单文档或者多文档程序。那么就有5个类。 程序是按顺序执行的,虽然都被封装成了类对象,看起来模块话,其实还是按顺序执行的,APP这个对象那个先于dlg构建。所以很多需要初始化的东西直接在App的成员initInstance 中编写。dlg中编写的基本都是一些与对话框相关的逻辑。 CMyApp是主线程类。他的InitInstance函数中会用CMyDlg构造一个对象,产生主对话框,CMyDlg是对话框类的一个派生类。两个类功能不同。 MFC的东西很复杂,不是三言两语可以说清楚的,可以参考下深入浅出mfc等书。CMyApp负责程序主框架的工作,可以理解为WinMain的封装。 CMyDlg是主对话框了,负责界面显示,消息循环等。 ------解决方案-------------------- CMyApp派生于CWinApp类,CMyDlg派生于CDialog类 程序运行时先执行CMyApp的InitInstance()函数 在InitInstance()中会有这样的代码 CMyDlg dlg; m_pMainWnd = &dlg; int nResponse = dlg.DoModal(); 一个最基本的单文档视图的MFC程序,包含CxxApp、CxxDoc、CMainFrame、CxxView和CAboutDlg五个类。 它们在程序开始运行时被创建的顺序是:CxxApp 、CxxDoc 、CMainFrame 、CxxView 、CAboutDlg 。

C**App()定义了窗体加载之前需要做的预处理。比如一个加密的软件,打 开后提示用户输入密码。这个事件的处理程序就要写在C**App()的 InitInstance(中。 CMainFrame()包含了对工具栏、状态栏、窗口的定义。 C**View包含了最主要的处理功能,如菜单操作、快捷键、用户交互操作等。 CAboutDlg定义了ABOUT对话框。 其中,前四个都是在程序主窗口出现之前被创建的,CAboutDlg是在“关于”对话框弹出 时被创建的 1CAboutDlg //这个是关于对话框里面是构造和析构2CMainFrame //主框架`是在窗口生成之前准备工作全在这吗 ?3CTestApp//这个是什么`initlnstance()在这里也是初始化什 么对象 ? 4CTestDoc//这是文档`是管理哪些文档`对初学者来说很少用 呐 ?5CTestView视图`这个常用 OnDraw我了解一些`我想知道`是不是默认就调 用一次 ? 还有个问题啊`我想加个音乐`虽然加成功了`但是`我一直不明白加在哪个函数里 `运行就有音乐?看过孙鑫的教程后来忘了`各位高手各抒已见,互相学习 LZ需要系统地学习一下。 CTestApp是基于WinApp的,WinApp封装了程序的主入口WinMain,WinMain就和c语言的main函数地位一样,是Win32程序的入口。在MFC的封装中,一个程序启动,Windows调用WinMain,这个WinMain函数现在由MFC事先写好藏好了,你不能也不需要修改,在这个预定义的WinMain里面会调用CWinApp的InitInstrance函数。你仔细看你CTestApp::InitInstrance函数,在这里一个CMainFrame的对象被创建,文档模板被创建,主窗口通过ShowWindow(SW_SHOW)被显示出来。 CMainFrame是个框架,是你整个应用程序的主窗口,他负责管理应用程序的菜单,工具栏,状态栏等。中间的区域,成为客户区,由View类来管理,View类也是一个窗口,他是MainFrame的子窗口。OnDraw函数负责绘制客户区的内容,该函数会被多次调用,他可以被你自己调用,比如你调用View类的UpdateWindow,或者在Document类中调用UpdateAllViews等等,MFC自动会调用OnDraw。他还会被Windows调用,Windows在需要刷新窗口的时候发送给窗口WM_PAINT消息,MFC事先已经预定义了,在响应WM_PAINT消息的时候会调用OnDraw。何时Windows会发送WM_PAINT呢,比如窗口从最小化还原,比如窗口被用户改变了 大小等等。这部分内容最好看看Windows GDI,Windows GDI是Windows操作系统整个可视化界面的基础。

MFC知识点(自己整理的,只供参考)

知识点:不是很全面,只供参考 第一章 Windows应用程序使用的界面是由各种图形元素组成的图形界面(GUI)。 Windows提供了大量预定义的用C语言编写的函数,这些函数就叫做API(Application Programming Interface)函数。 在Windows应用程序中,存在着许多与DOS应用程序不同的复杂对象,例如窗口、按钮、滚动条等等。Windows把为这种复杂对象所定义的标识叫做句柄。 常用的句柄类型:HWND 窗口句柄,HDC 图形设备环境句柄,HINSTANCE 当前程序应用实例句柄,HBITMAP 位图句柄,HICON 图标句柄,HCURSOR 光标句柄,HBRUSH 画刷句柄,HPEN 画笔句柄,HFONT 字体句柄,HMENU 菜单句柄,HFILE 文件句柄 事件的描述是一个消息 消息的结构: typedef struct tagMSG { HWND hwnd; //产生消息的窗口句柄 UINT message;//消息的标识码 WPARAM wParam;//消息的附加信息1 LPARAM lParam;//消息的附加信息2 DWORD time; //消息进入消息队列的时刻 POINT pt; //表示发送该消息时鼠标的位置 }MSG; 消息循环: while(GetMessage(&msg,NULL,NULL,NULL))//系统处理了消息后返回 { TranslateMessage(&msg);//把键盘消息翻译成字符消息 DispatchMessage(&msg);//把消息派发给Windows系统 创建窗口的三个步骤: 注册窗口类: RegisterClass(&wc); 创建窗口: hwnd=CreateWindow( lpszClassName, "Windows", WS_OVERLAPPEDWINDOW, 120,50,800,600, NULL, NULL, hInstance, NULL); 显示窗口: ShowWindow(hwnd,nCmdShow); UpdateWindow(hwnd); 大题:用函数封装Windows程序(P16) 第二章

MFC对话框程序中的各组件常用方法

MFC对话框程序中的各组件常用方法: Static Text: 将ID号改成唯一的一个,如:IDC_XX,然后进一次类向导点确定产生这个ID,之后更改Caption属性: GetDlgItem(IDC_XX)->SetWindowText(L"dsgdhfgdffd"); 设置字体: CFont *pFont = new CFont; pFont->CreatePointFont(120,_T("华文行楷")); GetDlgItem(IDC_XX)->SetFont(pFont); Edit Control: 设置文本: SetDlgItemText(IDC_XX,L"iuewurebfdjf"); 获取所有输入: 建立类向导创建一个成员变量(假设是shuru1,shuru2……)类型选value,变量类型任选。 UpdateData(true); GetDlgItem(IDC_XX)->SetWindowText(shuru1); 第一句更新所有建立了变量的对话框组件,获取输入的值。第二句将前面的IDC_XX的静态文本内容改为shuru1输入的内容。 若类型选用control: 1.设置只读属性: shuru1.SetReadOnly(true); 2.判断edit中光标状态并得到选中内容(richedit同样适用) int nStart, nEnd; CString strTemp; shuru1.GetSel(nStart, nEnd); if(nStart == nEnd) { strTemp.Format(_T(" 光标在%d" ), nStart); AfxMessageBox(strTemp); } else { //得到edit选中的内容 shuru1.GetWindowText(strTemp); strTemp = strTemp.Mid(nStart,nEnd-nStart); AfxMessageBox(strTemp); } 其中nStart和nEnd分别表示光标的起始和终止位置,从0开始。strTemp.Format 方法用于格式化字符串。AfxMessageBox(strTemp)显示一个提示对话框,其内容是字符串strTemp。 strTemp = strTemp.Mid(nStart,nEnd-nStart)返回一个被截取的字符串,从nStart开始,长度为nEnd-nStart。如果nStart == nEnd说明没有选择文本。 注:SetSel(0,-1)表示全选;SetSel(-1,i)表示删除所选。

常用的MFC类及其作用

常用的MFC类及其作用 分类:MFC基础类专区2008-10-14 11:16 445人阅读评论(1) 收藏举报 1.CRuntimeClass结构 继承自CObject的类都有一个与它相关的CRuntimeClass结构,用来在运行时获得对象以及其基类的信息。 要使用CRuntimeClass结构,必需借助于RUNTIME_CLASS()宏和其他有关运行时类型识别的宏。 2.CObject CObject类的作用: a.对象诊断:MFC提供了两种对象的诊断机制,一种是利用成员含数AssertValid 进行对象有效性检查,这样可以使类在继续运行以前对自已进行正确性检查。另一种是利用成员含数Dump输出对象的数据成员的值,诊断信息以文本形式放入一个数据流中,用于调试器的输出窗口信息显示。这两种诊断只能用于Debug版的应用程序。 b.CObject类提供了GetRuntimeClass与IsKindOf两个成员含数来支持运行时类型识别。GetRunntimeClass根据对象的类返回一个CRuntimeClass结构的指针,它包含了一个类的运行信息,含数IsKindOf用于测试对象与给定类的关系。 c.提供对象的序列化。必须在类的定义中包含DECLARE_SERIAL宏,并且在类的实现文件中加入包含IMPLEMENT_SERIAL宏. https://www.wendangku.net/doc/a13428740.html,mdTarget 该类直接从CObject类派生而来. 它负责将消息发送到能够响应这些消息的对象。它是所有能实行消息映射MFC类的基类,如CWinThread,CWinApp,CWnd,CView,CDocument等类。CCmdTarget 类的主要功能包括消息发送,设置光标和支持自动化. a.消息发送:MFC应用程序为每个CCmdTarget派生类创建一个称为<消息映射表>的<静态数据结构>,该消息映射结构将消息映射到对象所对应的消息处理含数

常用MFC和API函数

常用MFC和API函数 索引 CArchive类:用于二进制保存档案 CBitmap类:封装Windows的图形设备接口(GDI)位图 CBrush类:封装图形设备接口(GDI)中的画刷 CButton类:提供Windows按钮控件的功能 CByteArray类:该类支持动态的字节数组 CCmdUI类:该类仅用于ON_UPDATE_COMMAND_UI处理函数中 CColorDialog类:封装标准颜色对话框 CDC类:定义设备环境对象类 CDialog类:所有对话框(模态或非模态)的基类 CDocument类:提供用户定义的文档类的基本功能 CEdit类:是一个用于编辑控件的类 CFile类:该类是基本文件类的基类 CFileDialog类:封装了打开和保存文件的标准对话框 CFindReplaceDialog类:封装了标准查找/替换对话框 CFont类:封装了Windows图形设备接口(GDI)中的字体对象 CFontDialog类:封装了字体选择对话框 CGdiObject类:GDI绘图工具的基类 CIPAddressCtrl类:提供了IP地址控件的功能 CImageList类:管理大小相同的图标或位图集 CMenu类:封装应用程序菜单栏和弹出式菜单 CPen类:封装了Windows图形设备接口(GDI)中的画笔对象 CPoint类:操作CPoint和POINT结构 CRect类:封装了一个矩形区域及相关操作 CRgn类:封装用于操作窗口中的椭圆、多边形或者不规则区域的GDI区域 CSize类:用于表示相对坐标或位置 CSpinButtonCtrl类:旋转控件Spin的控制类 CStatusBar类:状态栏窗口的基类 CString类:处理字符串 CStringList类:支持CString对象的列表 CWinApp类:派生的程序对象的基类 CWnd类:提供所有窗口类的基本函数 API函数 CArchive类:用于二进制保存档案 CArchive::CArchive 建立一个CArchive对象 CArchive(CFile* pFile,UINT nMode,int nBufSize=4096,void* lpBuf=NULL); 参数:pFile 指向CFile对象的指针,这个CFile对象是数据的最终源或目的;nMode是标志,取值为CArchive::load时,从文档中加载数据(要求CFile读许可),取值为CArchive::store时,将数据存入文档(要求CFile写许可);nBufSize 指定内部文件缓冲区的大小(按字节计); lpBuf 指向大小为nBufSize的缓冲区,若未指定,则从局部堆中分配一缓冲区,

C++_MFC快速超简单入门

C++ MFC快速超简单入门学习 注意:红色字体为重要的信息,必须理解并记住。 在学习MFC之前,你必须对C++的“类和对象有一定的认识和理解,因为MFC就是C++完全的面向对象设计,它里面封装了好多类,我们只要调用就OK,就像C语言调用库函数一样,直接使用,这就是C++ 第一特性:封装性,第二性就是继承与派生, 这个在MFC中体现得淋淋至间(字打错了)。如果不懂,我再来解释一下,例:有一个商品类,class GOODS 商品属性有名字,价格 它可作为一个基类,我可以派上出苹果类,class Apple :public GOODS . 苹果属性出了继承了商品的属性名字,价格之外,还可派 生出,颜色,等属性,继承与派生就是一个是另一个的子集,但是这 个子集不仅包括父集的特征,还具有一些新的特性,懂了吧,这样。MFC其中重要的类是:CDialog 对话框类,CEdit,(编辑框 类)CButton,(按钮类)CRadio(单选钮类),这些都是作为基类,由我们自己定义的类去派生它们。 好了,现在先了解一下什么是MFC吧,请看当前目录下的MFC入门知识的幻灯片1—20张,或大概的浏览一下当前目录下的其它连个word文件,后面的幻灯片我觉得没必要看了,因为是快速吗,节约时间,(首先看不懂没关系,)但但看完之后,必须掌握如下知识: 1.MFC是作什么用的?与以前我们写的C,C++语言有什 么不同。以及它的一些优点, 不同,以前的是控制台的界面不好看,不友好,操作不 方便,黑框框的一片。 MFC反之。 优点:可用极少的代码实现强大的功能, 2.关于MFC的一些术语,概念啊

3.你要知道MFC的对话框是由控件组成的,具有 哪些控件(例按钮:Button, 单选钮:radio,Edit)例:要知道MFC的编程的原则,也就是宗旨理念吧,“消息映射,事件驱动“,这句话要记住并理解,很重要,真的。那到底是什么意思呢? 现实举例:一个人具备一种“感知“的能力,(也可称消息吧),当用火接近这个人时(发生的事件),就会(驱动)这个人做出反应,远离”火“, 用MFC举例:一个按钮有什么消息啊,我可以单 击它,所以它具备单击的消息: 第一个就是左键单击的消息,第二个 就是双击的消息,见名思议就 OK了。我单击这个按钮要产生某个事件, 我就可以第一步,先给按钮添加一个消息响应函 数,意思就是当我单击按钮时,就调用那个函数, 按钮时时刻刻都处于待命的状态, 假如添加的函数如下: void CDsDlg::OnButton1() { AfxMessageB ox(“我单击了这个按钮”);

MFC常用函数

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★//这一页的代码最重要了,呵呵……什么都在这里面呢; 单文档新建:CWinApp_________docManager->docSingleTemplate的OpenDocumentFile函数参数为空,此函数完成了大部分东西,包括新建文档类框架类等______________然后是调用CDocument就没什么意思了,当然我们要是重载了CDocument的新建函数就是调用子类虚函数。 多文档新建:CWinApp_________docManager->docMultTemplate的OpenDocumentFile函数参数为空,此函数完成了大部分东西,包括新建文档类框架类等______________然后是调用CDocument就没什么意思了,当然我们要是重载了CDocument的新建函数就是调用子类虚函数。 单文档打开:CWinApp_________docManager中经过一个打开对话框传递参数,中途还调用了APP的OpenDocumentFile,当然如果我们的APP重载了这个函数也要调用我们的但是我们的函数一定别忘记最后返回是调用父类的此函数___________docSingleTemplate的OpenDocumentFile函数参数不为空,此函数完成了大部分东西,包括新建文档类框架类等______________然后是调用CDocument就没什么意思了,当然我们要是重载了CDocument的新建函数就是调用子类虚函数。 多文档打开:CWinApp_________docManager中经过一个打开对话框传递参数,中途还调用了APP的OpenDocumentFile,当然如果我们的APP重载了这个函数也要调用我们的但是我们的函数一定别忘记最后返回是调用父类的此函数___________docMultTemplate的OpenDocumentFile函数参数不为空,此函数完成了大部分东西,包括新建文档类框架类等______________然后是调用CDocument就没什么意思了,当然我们要是重载了CDocument的新建函数就是调用子类虚函数。 他们两个只有在docMultTemplate和docSingleTemplate的OpenDocumentFile函数中的动作不同,单文档负责新建框架类和视类但是如果存在了我们就不重建了,只是给其赋值。而多文档无论如何都会新建一个视类和框架类文档类,这也就是为什么他是多文档结构的原因。 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ 接下来介绍这个最重要的函数,它基本什么都干了,不管是新建还是打开都得调用它,呵呵…… // CDocument* CMultiDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName, BOOL bMakeVisible) { //下面调用的是CDocTemplate::CreateNewDocument() CDocument* pDocument = CreateNewDocument();//这里面调用了AddDocument(pDocument); //添加了一个CMyMultiTestDoc : public CDocument

MFC常用类-链表类

MFC的链表类 模板类Clist CTypedPtrList 非模板类CObList CPtrList CStringList MFC链表类的常用成员函数——以Clist为例 1.CList(int nBlockSize = 10 ); 2.TYPE GetHead()const; 3.TYPE GetTail()const; 4.RemoveHead() 5.RemoveTail() 6.原型1:POSITION AddHead(ARG_TYPE newElement ); 原型2:void AddHead(CList* pNewList ); 7.原型1:POSITION AddTail(ARG_TYPE newElement ); 原型2:void AddTail(CList* pNewList ); 8.RemoveAll() 9.POSITION GetHeadPosition()const; 10.POSITION GetTailPosition()const; 11.TYPE GetNext(POSITION& rPosition )const; 12.TYPE GetPrev(POSITION& rPosition )const; 13.TYPE GetAt(POSITION position )const; 14.void SetAt(POSITION pos, ARG_TYPE newElement ); 15.void RemoveAt(POSITION position ); 16.POSITION InsertBefore(POSITION position, ARG_TYPE newElement ); 17.POSITION InsertAfter(POSITION position, ARG_TYPE newElement ); 18.POSITION Find(ARG_TYPE searchValue, POSITION startAfter = NULL)const; 19.POSITION FindIndex(int nIndex )const; 20.int GetCount()const; 21.BOOL IsEmpty()const; 例题 struct CStudent { CString m_strName; int m_nScore; }; CPtrList m_List; 向添加链表中添加元素 CStudent* m_pStudent = new CStudent; m_pStudent->m_strName = m_strName; m_pStudent->m_nScore = m_nScore; m_List.AddTail(m_pStudent); 删除节点 int nNumber;

(适合初学者)MFC基础教程

Visual C++/MFC初学教程 目录 +-- 第一章 VC入门 |------ 1.1 如何学好VC |------ 1.2 理解Windows消息机制 |------ 1.3 利用Visual C++/MFC开发Windows程序的优势 |------ 1.4 利用MFC进行开发的通用方法介绍 |------ 1.5 MFC中常用类,宏,函数介绍 +-- 第二章图形输出 |------ 2.1 和GUI有关的各种对象 |------ 2.2 在窗口中输出文字 |------ 2.3 使用点,刷子,笔进行绘图 |------ 2.4 在窗口中绘制设备相关位图,图标,设备无关位图 |------ 2.5 使用各种映射方式 |------ 2.6 多边形和剪贴区域 +-- 第三章文档视结构 |------ 3.1 文档视图框架窗口间的关系和消息传送规律 |------ 3.2 接收用户输入 |------ 3.3 使用菜单 |------ 3.4 文档,视,框架之间相互作用 |------ 3.5 利用序列化进行文件读写 |------ 3.6 MFC中所提供的各种视类介绍 +-- 第四章窗口控件 |------ 4.1 Button |------ 4.2 Static Box |------ 4.3 Edit Box |------ 4.4 Scroll Bar |------ 4.5 List Box/Check List Box |------ 4.6 Combo Box/Combo Box Ex |------ 4.7 Tree Ctrl |------ 4.8 List Ctrl |------ 4.9 Tab Ctrl |------ 4.A Tool Bar |------ 4.B Status Bar |------ 4.C Dialog Bar |------ 4.D 利用AppWizard创建并使用ToolBar StatusBar Dialog Bar |------ 4.E General Window

MFC常用类-CTimeSpan类

CTimeSpan类 1.构造函数。 CTimeSpan类有下列构造函数: (1)CTimeSpan(); (2)CTimeSpan(const CTimeSpan& timeSpanSrc ); (3)CTimeSpan(time_t time ); (4)CTimeSpan(LONG lDays, int nHours, int nMins, int nSecs ); 参数timeSpanSrc为一个已存在的CTimeSpan 对象,time为一个time_t 类型的时间值,lDays, nHours, nMins, nSecs分别为天数、小时数、 分数和秒数。 2.时间值的提取函数 (1)GetDays()获得CTimeSpan类对象中包含的完整的天数。 (2)GetHours()获得当天的小时数,值在-23到23之间。 (3)GetTotalHours()获得CTimeSpan类对象中包含的完整的小时数。 (4)GetMinutes()获得当前小时包含的分数,值在-59到59之间。 (5)GetTotalMinutes()获得CTimeSpan类对象中包含的完整的分数。 (6)GetSeconds()获得当前分钟包含的秒数,值在-59到59之间。 (7)GetTotalSeconds()获得CTimeSpan类对象中包含的完整的秒数。 格式化时间 Format()将一个CTimeSpan对象转换成格式字符串。使用方式与CTime类似,格式化字符包括以下几个: %D: CTimeSpan的总天数; %H:不足整天的小时数; %M:不足1小时的分数; %S:不足1分钟的秒数; %%:百分号。 4.重载运算符 CTimeSpan类也重载了运算符“=”,“+”,“-”,“+=”,“-=”,“==”,“!=”,“<”,“>”,“<=”,“>=”,用于CTimeSpan对象的赋值、加减运 算及两个CTimeSpan对象的比较。 例子代码 构造一个CTimeSpan对象,并获取其中的完整天数、小时数、分数和秒数,将获得的信息在信息框中显示。 CTimeSpan m_timespan(3,4,5,6); // 3天,4小时,5分,6秒 LONG m_totalDays=m_timespan.GetDays(); //获得完整天数 LONG m_totalHours=m_timespan.GetTotalHours(); //获得完整小时数 LONG m_totalMinutes=m_timespan.GetTotalMinutes(); //获得完整分数 LONG m_totalSeconds=m_timespan.GetTotalSeconds(); //获得完整秒数 char s1[8], s2[8], s3[8], s4[8]; wsprintf(s1,"%ld",m_totalDays); wsprintf(s2,"%ld",m_totalHours); wsprintf(s3,"%ld",m_totalMinutes); wsprintf(s4,"%ld",m_totalSeconds); CString m_str = "此时间范围包含:\n完整天数:"+CString(s1)+"\n完整小时数:"+CString(s2)+"\n完整分数:"+CString(s3)+"\n完整秒 数:"+CString(s4); MessageBox(m_str);

MFC类库的基本类

MFC类库是一个层次结构,主要有CObject类、应用程序类、可视对象类、绘图和打印类、通用类、数据库类、Internet和网络类、OLE类。 (1)CObject类 CObject类是MFC的抽象基类,MFC中的大多数类是从CObject类派生出来的。它是MFC 中多数类和用户自定义的根类,该类为程序员提供了希望融入所编写程序的许多公共操作,包括对象的建立和删除、串行化支持、对象诊断输出、运行时信息以及集合类的兼容等。CObject类的声明在Afx.h中。 (2)应用程序结构类 该类主要用于构造框架应用程序的结构,提供了多数应用程序公用的功能.编写程序的任务是填充框架,添加应用程序专有的功能。 1.应用程序和线程支持类 CWinThread类是所有线程的基类,窗口应用程序类CWinApp类就是从该类中派生来的。每个应用程序有且只有一个应用程序对象,在运行程序中该对象和其他对象相互协调,该对象从CWinApp中派生出来。该类封装了初始化、运行、终止应用程序的代码。 2.命令相关类 CCmdTarget类是CObject的子类,它是MFC所有具有消息映射属性的基类。消息映射规定了当一对象接收到消息命令时,应调用哪个函数对该消息进行处理。程序员很少需要从CCmdTarget类中直接派生出新类,往往都是从它的子类中派生出新类。如窗口类(CWnd)、应用程序类(CWinApp)、文档模板类(CDocTemplate)、视类(CView)及框架窗口类(CFrameWnd)等。 3.文档类 文档对象由文档对象模板创建,用于管理应用程序的数据。视图对象表示一个窗口的客户区,用于显示文档数据并允许读者与之交互。有关文档/视结构的类如下: ①CDocTemplate类:文档模板的基类。文档模板用于协调文档、视图和框架窗口的创建。 ②CSingleDocTemplate类:单文档界面(SDI)的文档模板。 ③CMultiDocTemplate类:多文档界面(MDI)的文档模板。 ④CDocument类:应用程序专用文档的基类。 (3)可视对象类 1. CWnd类 该类提供了MFC中所有窗口类的基本功能。它是CCmdTarget类的子类。创建Windows窗口要分两步进行:首先,引入构造函数,构造一个CWnd对象;然后调用Creat建立Windows 窗口并将它连到CWnd对象上。MFC中还从CWnd类派生出了进一步的窗口类型,以完成更具体的窗口创建工作,这些派生类有: ①CFrameWnd类:SDI应用程序主框架窗口的基类。 ②CMDIFrameWnd类:MDI应用程序主框架窗口的基类。 ③CMDIChildFrameWnd类:应用程序文档框架窗口的基类。 2. CView类 使用CView类(视图类)可以在其他窗口中创建子窗口,它可以提供一个特殊的接受外来输入的结构窗口。也就是说,CView类用于控制用户如何观看文档的数据,以及怎样与这些数据交互。即CView类管理着框架窗口的客户区,为用户与Windows之间提供可视接口。该类接收来自用户的键盘或鼠标的输入,还允许用户对数据进行预览和打印。 CView类广泛应用于基于文档的应用程序中。利用该类的派生类,可图形化地管理文档数据,用户对文档的操作都是通过它来实现的。CView类可用来实现用户自定义视图类的基本功能。在程序运行时,CView类用于视图的实现。一个视图只能分配给一个文档,但一个文档

MFC常用类-CPoint,CRect,CSize类

CPoint类 类CPoint是对Windows结构POINT的封装,凡是能用POINT结构的地方都可以用CPoint代替。 结构POINT表示屏幕上的一个二维点,其定义为: typedef struct tagPOINT{ LONG x; LONG y; } POINT; 其中x、y分别是点的横坐标和纵坐标。 由于CPoint提供了一些重载运算符,使得CPoint的操作更加方便。如运算符“+”,“-”,“+=”和“-=”用于两个CPoint 对象或一个CPoint对象与一个CSize对象的加减运算,运算符“==”和“!=”用于比较两个CPoint对象是否相等。 CSize类 类CSize是对Windows结构SIZE的封装,凡是能用SIZE结构的地方都可以用CSize代替。 结构SIZE表示一个矩形的长度和宽度,其定义为: typedef struct tagSIZE{ LONG cx; LONG cy; } SIZE; 其中cx、cy分别是长度和宽度。 与CPoint类似,CSize也提供了一些重载运算符。如运算符“+”,“-”,“+=”和“-=”,用于两个CSize对象或一个CSize对象与一个CPoint 对象的加减运算,运算符“==”和“!=”用于比较两个CSize对象是否相等。 由于CPoint和CSize都包含两个整数类型的成员变量,他们可以进行相互操作。CPoint对象的操作可以以CSize对象为参数。同样,CSize 对象的操作也可以以CPoint对象为参数。如可以用一个CPoint对象构造一个CSize对象,也可以用一个CSize对象构造一个CPoint对象, 允许一个CPoint对象和一个CSize对象进行加减运算。 CRect类 类CRect是对Windows结构RECT的封装,凡是能用RECT结构的地方都可以用CRect代替。 结构RECT表示一个矩形的位置和尺寸,其定义为: typedef struct tagRECT{ LONG left; LONG top; LONG right; LONG bottom; } RECT; 其中left、top分别表示矩形左上角顶点的横坐标和纵坐标,right、bottom分别表示矩形右下角顶点的横坐标和纵坐标。 由于CRect提供了一些成员函数和重载运算符,使得CRect的操作更加方便。 1.CRect的构造函数 CRect有如下6个构造函数: CRect(); CRect(int l, int t, int r, int b ); CRect(const RECT& srcRect ); CRect(LPCRECT lpSrcRect ); CRect(POINT point, SIZE size );

MFC常用控件用法

MFC 常用整理 MFC USUAL TRIM 艾德温*范克里夫 学生所在学院:信息科学与工程学院 学生所在班级:软件2班 学生姓名:王海波 学生学号:110120010061 指导教师:王海波 教务处 2014年 7 月

目录 MFC 常用知识 第一回:整体感知 第二回: MFC是什么 第三回:开始用MFC创建窗体以及MFC的结构第四回: VS2010界面组织 MFC 常用控件写法 常用控件介绍 常用控件使用 按钮的使用 编辑框的使用 选项卡的使用 报表的使用

MFC 常用知识 第一回: 想写一个像上图(大二写的的吧。。囧)的窗体程序,我们就可以用简单的MFC.怎么用MFC做出上图的窗体? 1 如下图用vs2010的可视化工具栏拖控件,很简单

2 然后双击某个按钮,vs2010会自动弹出函数,我们就可以在函数中填写代码。之后,每当你按那个按钮一次,你在函数中写的代码就会执行一次。 3 显然这一点功能远远不够,更多请看下回。

第二回: 回顾:第一回讲的就是一个窗体初级的原型。接下来说说更深一点的东西。 MFC 是什么?(上面的窗体等是哪里来的?) 定义:MFC: Microsoft function class (微软功能类) 理解:MFC 就是许许多多的类。 跟我们有什么联系:我们利用MFC中的许多类作为工具来开发出窗体。 更浅显的理解:MFC就是工具,让我们能快速开发的工具。之前穆云峰老师的windows编程课记着么,最开始窗体就是那么一句句代码手动写出来的,特繁琐,所以微软就写了功能封装类,把一些重复的工作写成类,之后写窗体就更方便了。 第三回: 一:开始用MFC 写窗体 1 2

MFC中常用函数

1.IsEmpty() 函数判断一对象是否初始化,返回布尔值. 表达式 IsEmpty(expression) 实例: <% Dim i response.write IsEmpty(i) %> 返回结果: true 2. GetAt 函数原型:TCHAR GetAt( int nIndex ) const; 函数返回值:字符中第nIndex个字符(从0开始). Header: atlcoll.h 注意:nIndex的最大值可由GetUpperBound()得到。若nIndex小于0或大于最大值,将返回错误。 3. isdigit isdigit 原型:extern int isdigit(char c); 用法:#include 功能:判断字符c是否为数字 说明:当c为数字0-9时,返回非零值,否则返回零。 附加说明此为宏定义,非真正函数。

相关函数: isalnum,isalpha,isxdigit,iscntrl,isgraph,isprint,i spunct,isspace 4. isalnum 原型:extern int isalnum(int c); 用法:#include 功能:判断字符变量c是否为字母或数字 说明:当c为数字0-9或字母a-z及A-Z时,返回非零值,否则返回零。 5. isalpha 函数:isalpha 原型:int isalpha(int ch) 用法:头文件加入#include (旧版本的编译器使用) 功能:判断字符ch是否为英文字母,当ch为英文字母a-z或A-Z时,在标准c中相当于使用 “isupper(ch)||islower(ch)”做测试,返回非零值,否则返回零。 PS:{ isupper 原型:extern int isupper(int c);

C _MFC快速超简单入门

C++MFC快速超简单入门学习 注意:红色字体为重要的信息,必须理解并记住。 在学习MFC之前,你必须对C++的“类和对象有一定的认识和理解,因为MFC就是C++完全的面向对象设计,它里面封装了好多类,我们只要调用就OK,就像C语言调用库函数一样,直接使用,这就是C++ 第一特性:封装性,第二性就是继承与派生, 这个在MFC中体现得淋淋至间(字打错了)。如果不懂,我再来解释一下,例:有一个商品类,class GOODS商品属性有名字,价格 它可作为一个基类,我可以派上出苹果类,class Apple:public GOODS.苹果属性出了继承了商品的属性名字,价格之外,还可派生出,颜色,等属性,继承与派生就是一个是另一个的子集,但是这个子集不仅包括父集的特征,还具有一些新的特性,懂了吧,这样。MFC其中重要的类是:CDialog对话框类,CEdit,(编辑框 类)CButton,(按钮类)CRadio(单选钮类),这些都是作为基类,由我们自己定义的类去派生它们。 好了,现在先了解一下什么是MFC吧,请看当前目录下的MFC入门知识的幻灯片1—20张,或大概的浏览一下当前目录下的其它连个word文件,后面的幻灯片我觉得没必要看了,因为是快速吗,节约时间,(首先看不懂没关系,)但但看完之后,必须掌握如下知识: 1.MFC是作什么用的?与以前我们写的C,C++语言有什 么不同。以及它的一些优点, 不同,以前的是控制台的界面不好看,不友好,操作不 方便,黑框框的一片。 MFC反之。 优点:可用极少的代码实现强大的功能, 2.关于MFC的一些术语,概念啊

3.你要知道MFC的对话框是由控件组成的,具有 哪些控件(例按钮:Button,单选钮:radio,Edit)例:要知道MFC的编程的原则,也就是宗旨理念吧,“消息映射,事件驱动“,这句话要记住并理解,很重要,真的。那到底是什么意思呢? 现实举例:一个人具备一种“感知“的能力,(也可称消息吧),当用火接近这个人时(发生的事件),就会(驱动)这个人做出反应,远离”火“, 用MFC举例:一个按钮有什么消息啊,我可以单击它,所以它具备单击的消息: 第一个就是左键单击的消息,第二个 就是双击的消息,见名思议就OK了。我单击这个按钮要产生某个事件, 我就可以第一步,先给按钮添加一个消息响应函数,意思就是当我单击按钮时,就调用那个函数,按钮时时刻刻都处于待命的状态, 假如添加的函数如下: void CDsDlg::OnButton1() { AfxMessageB ox(“我单击了这个按钮”);

MFC常用类-CTime类

CTime类 1.构造和初始化CTime类对象 CTi me类有下列构造函数: CTi me(); CTi me(const CTi me& timeSrc ); CTi me(time_t time ); CTi me(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST = -1 ); CTi me(WORD wDosDate, WORD wDosTime, int nDST = -1); CTi me(const SYSTEMTIME& sysTi me, int nDST = -1 ); CTi me(const FILETIME& fileTi me, int nDST = -1); 说明:以不同的方式构造一个CTi me对象。可以用一个已经存在的CTi me对象或一个time_t(在ti me.h中被定义为long)类型变量来构造和初始化CTi me对象,也可以用年、月、日、小时、分、秒来构造和初始化CTi me对象,还可以用SYSTEMTIME、FILETIME结构来构造和初始化CTime对象。SYSTEMTIME、FILETIME结构定义如下: typedef struct _SYSTEMTIME { WORD wYear; WORD wMonth; WORD wDayOfWeek; WORD wDay; WORD wHour; WORD wMinute; WORD wSecond; WORD wMilliseconds; } SYSTEMTIME; typedef struct _FILETIME { DWORD dwLowDateTime; /* low 32 bits */ DWORD dwHighDateTime; /* high 32 bits */ } FILETIME, *PFILETIME, *LPFILETIME; 2.时间值的提取函数 (1)GetCurrentTime()获取系统当前时间。 原型:static CTi me PASCAL GetCurrentTime(); (2)GetTime()由CTi me对象返回一个time_t变量。 原型:time_t GetTime()const; (3)GetYear()获取CTime对象代表的年。 原型:int GetYear()const; 以下(4)至(9)函数原型与GetYear()类似。 (4)GetMonth()获取CTi me对象代表的月。 (5)GetDay()获取CTi me对象代表的日期。 (6)GetHour()获取CTi me对象代表的小时。 (7)GetMinute()获取CTi me对象代表的分。 (8)GetSecond()获取CTime对象代表的秒。 (9)GetDayOfWeek()获取CTi me对象代表的星期几,1代表周日、2代表周一、等等。

相关文档