Visual C++/MFC 指南

本文是Visual C++/MFC的入门教程,介绍了Windows编程的基础概念,如消息和句柄,以及如何处理它们。文章强调了消息在程序中的作用,以及句柄如何用于引用Windows对象。此外,还讲解了C++类和对象的基本知识,包括构造函数、析构函数、类的继承和重载函数。最后,提到了MFC中的CWnd类、CWinApp类和CString类的重要角色。
摘要由CSDN通过智能技术生成

Visual C++MFC Tutorial 第一课:幕后:消息和句柄第一课:幕后:消息和句柄

尽管你会想要深入钻研源代码,但你其实并不会这样做。Windows编程起初都是非常困难的。
让我们来快速的看一看Windows下的程序是这样运作的。
你编程的关键将是处理和发送消息。那什么是消息呢?
简单的说,消息是一个32位值,用来指明一个事件。比如:
当你移动鼠标的时候,一个消息(定义为WM_MOUSEMOVE)就被发送给当前的窗口。
当你按下键盘上的键,一个消息(定义为WM_KEYDOWN)就被发送给了当前的窗口。
当你调整窗口的尺寸,一个消息(定义为WM_SIZE)被发送到当前的窗口。
想象出这个过程了么?
那么这些消息被发送到哪里去了呢?
它们会排进一个队里,窗口最终会将它们拿出来并相应的执行。
例如当窗口得到WM_MOVE消息,它将改变窗口坐标并在屏幕上重画窗口。

让我们来看看句柄。
Windows在面向对象方面做的很好。你面对着一些window对象(比如桌面,你现在用来阅读的程序,等等。。。)。一个程序员用非面向对象的方式怎么区分这类东呢?
使用句柄。
句柄用来引用不同的windows对象。你可以对窗口、文件使用句柄,也能对分配了的内存、图象使用句柄。可以把句柄理解为与指针类似。你必须通过某种方式来创建句柄;而且在使用完后销毁掉,不然将造成资源泄漏而使你的系统瘫痪。所以要保证它们在某个时候被销毁了。

好了,现在是时候让我们把这两件东西放在一起了。
比方说有一个窗口,你有一个指向它的句柄(称为HWND)。把你的句柄命名为your_HWND。当这个遮盖在这个窗口上面的其他窗口被移去的时候,系统会要求你重画窗口。windows会这样发送消息:
PostMessage(your_HWND, WM_PAINT, 0,0);
这个函数发送一个重画的消息给句柄为your_HWND的窗口。最后的两个参数作为该消息的额外信息,现在先不必考虑。这样,你的程序就应该有一个包括很多分支判断的函数来处理不同的消息。比如:

void  HandleTheMessage(long Message)
{
 switch(Message)
 {
  case WM_PAINT:
   DrawWindow();
  break;
 
  case WM_KEYDOWN:
  break;
  //etc...
 }
}


好了,这些是windows幕后最基本的运作。
不过这些足够让你继续来学习MFC了。

第二课:C++ 要点 

如果你想使用Microsoft Visual C++,懂得C++中关于类的内容将会有极大的帮助。如果你习惯使用简单的C,你只有实践过才能掌握对类的处理。在开始VC++之前,让我们来复习一下你应该弄清楚的关于类的内容。

在很大程度上来说类是一种结构。我们从一个例子入手来而不是仅说明规则。写一个类来描述直线。在.h文件里这样定义类:

class CLine 
{ 
 int m_nX1; 
 int m_nY1; 
 int m_nX2; 
 int m_nY2; 
 
public: 
 // constructors 
 CLine(); 
 CLine(int x1, int y1, int x2, int y2); 
 
 // destructor 
 ~CLine(); 
 
 // set the line data 
 void SetPoints(int x1, int y1, int x2, int y2); 
 
 // draw the line 
 void Draw(); 
} ;

        简短的说一下命名惯例。类的名字通常是由‘C’打头;成员变量使用前缀m_’, 接着按照微软的习惯使用一个字母来指明数据类型,然后是变量的名称。所有的单词用大写开头。我推荐这种微软的标准(叫做匈牙利法),因为它使用广泛而且容 易看懂。这样的话以后你看到m_pPoint,你就会想到这是一个成员变量而且是指向POINT类型的指针;看到fData就会想到这是一个浮点值。

        回 到关于类的讨论。整型变量记录线的端点。注意它们是放在‘public:’之前的,表明使用这个类的程序员不能直接使用这些变量,它们不是“公开”使用 的。那些在公有声明下面的函数是公开使用的。前面的两个叫做构造函数,这些函数总是在一个新的Cline对象被建立的时候执行。下面是它们被调用的一些时 候:

// this calls CLine()
CLine MyLine; 
 
// this is a pointer to a CLine class
CLine *pMyLine; 
 
// this  calls CLine()
pMyLine = new CLine; 
 
// this is a pointer to a CLine class
CLine *pMyLine; 
// this calls CLine(int x1, int y1, int x2, int y2)
pMyLine = new CLine(0,0,10,10); 
 
// this calls CLine(int x1, int y1, int x2, int y2)
CLine MyLine(0,0,10,10); 

所有的这些都建立了一条直线。有的直线被初始化为默认的设置有的则用了新的参数。关键字“new”在C++里建立新的对象,类似于C里的malloc。你必须对使用“new”的所有对象使用“delete”,就像在c里用free。不仅对类是这样,其他的数据类型也一样。我分配一个有100个整型数据的数组:

// a pointer to some integers
int *pNumbers; 
 
// make memory for 100 of them
pNumbers = new int[100]; 
 
// set the first element to 0
pNumbers[0]=0; 
 
// set the last element to 99
pNumbers[99]=99; 
 
// free the memory.
delete [] pNumbers; 

        注意在delete后面的[],这是在对程序说删除整个数组。如果你写的是“delete pnumbers;”,就只删除了第一个元素。这样就会造成内存泄漏。

    对不起啊,让我们回到Cline的构造函数。一条直线在建立的时候自动条用构造函数,代码是这样的:

CLine::CLine() 
{ 
 m_nX1=0; 
 m_nX2=0; 
 m_nY1=0; 
 m_nY2=0; 
}
CLine::CLine(int x1, int y1, int x2, int y2) 
{ 
 m_nX1=x1; 
 m_nX2=x2; 
 m_nY1=y1; 
 m_nY2=y2; 

}

         我们看到,除了把类名和两个冒号(CLine::)放在函数名的前面.,函数的声明很像标准的C函数。一个差异是构造函数没有返回值,析构函数也是如此。析构函数是在我们的Cline对象被删除或出了生存空间后被自动调用的。比如:

// this is a pointer to a CLine class
CLine *pMyLine; 
 
// this  calls CLine()
pMyLine = new CLine; 
 
// memory for the class is cleared up and ~CLine() is called
delete pMyLine; 
 
{ 
 // this  calls CLine()
 CLine MyLine; 
} 
 
// this '}' ends the section of the program where MyLine is
// valid. ~CLine() will be called. (MyLine goes out of 'scope')

         对于我们这个类,~Cline()不必做任何事情。但你可以把做清理的代码放在这里,象回收类中分配的内存。以为现在不必清理所以函数是空的:

CLine::~CLine() 
{ 
 // do nothing
} 

现在我们来填写另外的两个函数:

void CLine::SetPoints(int x1, int y1, int x2, int y2) 
{ 
 m_nX1=x1; 
 m_nX2=x2; 
 m_nY1=y1; 
 m_nY2=y2; 
 
 return; 
} 
void CLine::Draw() 
{ 
 // psuedo code here, these are operating system 
 // functions to draw a line
 MoveTo(m_nX1, m_nY1); 
 LineTo(m_nX2, m_nY2); 
 
 return; 
} 

怎么调用这些它们呢?这里有两个例子。 一个使用了指针另一个没有用指针:

CLine *pLine = new CLine(0,0,10,10); 
pLine->Draw(); 
delete pLine; 
CLine MyLine; 
MyLine.SetPoints(0,0,10,10); 
MyLine.Draw(); 

这个类就完成了。现在这个类可以在别的类里。你可以用4个直线来建立一个正方形类CSquare:

class CSquare 
{ 
 CLine m_LineTop; 
 CLine m_LineLeft; 
 CLine m_LineBottom; 
 CLine m_LineRight; 
 //... 
} 

还有更好的,根据类的特性,你可以用Cline类来建立你自己的类。这个用法在VC里用的太多了。比如你想在程序里画直线,那你就会想用直线类就好了,但这样做还缺少一个重要的特性,不能设置直线的颜色。当然不用再来写新的类了,更简单的办法是继承Cline类。像这样:

class CColorLine : public CLine 
{ 
public: 
 void Draw(long color); 
}; 

现在怎么样了呢?这个类有Cline类的所有功能,而且我们可以使用另外一个可以设置颜色的Draw()函数,在CPP文件里代码是这样的:

void CColorLine::Draw(long color) 
{ 
 // psuedo code here, these are operating system 
 // functions to draw a line 
 SetColor(color); 
 CLine::Draw(); 
 return; 
}

现在我们有了另外一个类的上所有功能而且添加了一个额外的Draw函数。但这个函数跟原来的Draw函数是同名的!没关系,C++足够聪明,它能辩明:如果你调用Draw(color)就使用新的函数而如果你调用Draw()就用旧的函数。在代码里CLine::Draw()也许会使你感到陌生。这是在告诉程序调用基类的画线函数。我们不必在费时重写LineTo MoveTo的代码了,很好,不是么?现在我们可以这样做了:

CColorLine MyLine; 
MyLine.SetPoints(0,0,10,10); 
// assuming 0 is black, this will draw a black line.
MyLine.Draw(0); 

当然,这里我省略了很多方面的问题。比如定义操作符,函数重载,虚函数,保护和私有成员……等等。但已经足够让你继续了。

第三课 环境: Visual C++ IDE and Workspaces

Windows编程是一件很需要技巧的事,不要给迷糊了。好在微软提供了IDE环境,叫做Developer's Studio,集合了编译,联接,帮助,写好的代码,还提供了可视化的环境让你制作漂亮的对话框。

有一些东西你应该知道。首先,也是最重要的,使用在线帮助。因为Windows的函数太多了,所以在开始的几个月里,你会发现你有50%的时间是在看帮助。如果你用的是VC6.0你就需要MSDN来作为帮助。一定要弄到它。

接下来,说一个最重要的组合键Ctrl-W,用来打开'Class Wizard'。这东西会在工程里替你插入代码。它处理了所有与消息关联的函数代码。

不妨也看看resource view。这是用来设计对话框的。你可以在上面把按钮拖来拖去,通过这里那里的双击设计你的程序。再使用class wizard,你就可以完成一半的工作了。剩下的事就是填写函数来处理按钮的消息。

现在你应该知道怎么开始写一个新的程序了。我们来写真正的代码。在File菜单里选择New,看到 Projects标签,选MFC AppWizard。输入你程序的名字,按OK。接下来,最重要的是第一步,选择程序的类型。最简单的就是'Dialog Based',你应该都试试,但现在我们先选'Dialog Based',下面的步骤都接受默认设置。完成时建立了新的文件,但不管它。

resource view里拉一些按钮放在对话框里。先玩一回。当你感觉不错了,菜单里选择'Build'来编译工程,再运行(我通常都是按Ctrl-F5,编译并运行工程。所有的程序都必须编译后执行。好~,程序运行了。

还有一些关于IDE的技巧。如果你右击菜单栏,会弹出一个对话框。选择'Customize',这个很有 用,通过拖拽就能定制菜单和工具条。很好的一个方法,定制你的主工具条并且把它的尺寸弄的你看起来舒服。我的屏幕只有一个工具条,有这么些按 钮:save, save all, compile, build, stop build, rebuild all, set active configuration, find, find in files, show view, show output window, set break point, remove break point, tile windows, find in help.

第四课: MFC 简要指点

已经作好开始写程序的准备了么?不,还没有。不要说你要让我教你写个愚蠢的'hello world'程序。如果你想好好利用Visual C++你就得会Microsoft Foundation Classes(MFC)。这些类非常好,它包含了所有我们在第二课里讨论过的好处。现在对你最重要的是CWnd类。它封装了那些需要窗口句柄的函数。记 得我曾提过的PostMessage函数么?

PostMessage(your_HWND, WM_PAINT, 0,0); 

现在我们可以拥有窗口类并调用成员函数:

MyCWnd.PostMessage(WM_PAINT, 0, 0);

这个语句做了同样的事情,我们不必再去关心窗口句柄了。但你不要被骗了,它们还是在的,我们还在使用它们呢。它们现在仅是类的成员变量了。CWnd类里有窗口句柄m_hWnd。我们现在要这样调用老的发送消息函数:

::PostMessage(MyCWnd.m_hWnd, WM_PAINT, 0,0);

两个冒号 (::)用来告诉MFC我们调用的是老版本的函数。通常你不需要这样使用,但我在这里说一下免的你看到其他代码的时候感到困惑。

CWnd类是一些其他类的基类。像CButton和CDialog一样,带有解释性的名字。从CButton也能访问窗口句柄。(你会惊讶Windows里有多少东西啊。。滚动条,编辑框,树型视窗,桌面。。。。)。

另外一个重要的类是CWinApp类,虽然你以后并不会特意的使用它。这个类是MFC的主干,它在幕后做了 很多的苦活。你的每个程序都有一个CWinApp的对象,当它建立的时候,程序也就开始运行了。CWinApp对象建立的时候调用的主要的函数是 InitInstance(),是在这个函数里,你的程序被建立并开始运行。你可以认为InitInstance()跟C里的Main()函数很像。

让我们最后来看一个在MFC里挺重要的类,你肯定会用到的:CString类。这是微软的支撑类之一,用来简化对字符串的操作。CString类重载了大部分常用的操作符,比如 = 和 +,你就何以这样用了:

CString strMyString; 
strMyString="May the Force be with you"; 
strMyString+=" young Jedi." 
printf("%s", strMyString); 
//output will be "May the Force be with you young Jedi."; 


该书共分成15个章节,由易到难,由浅及深的介绍了MFC的功能框架和实际运用。每个知识点都有对应的代码实例。学习起来快速而不费力。更重要的是不是扫描版本。看着舒服。 目录结构如下: 目 录 译者序 前言 第一部分 基础知识 第1章 窗口 2 1.1 窗口和API环境 2 1.1.1 三种类型窗口 2 1.1.2 客户区和非客户区 3 1.2 窗口和MFC环境 4 1.3 怎样应用MFC创建一个窗口 5 1.4 怎样使用MFC销毁一个窗口 9 1.4.1 捆绑到一个已有的窗口 9 1.4.2 窗口类 10 1.4.3 窗口进程 10 1.5 怎样使用MFC创建一个窗口类 11 1.5.1 使用AfxRegisterWndClass () 函数注册一个窗口类 11 1.5.2 使用AfxRegisterClass ()函数 创建一个窗口类 12 1.6 怎样销毁一个MFC窗口类 14 1.7 厂商安装的窗口类 14 1.8 其他类型窗口 15 1.9 桌面窗口 16 1.10 小结 16 第2章 类 18 2.1 基类 18 2.1.1 CObject 18 2.1.2 CCmdTarget 19 2.1.3 CWnd 19 2.2 应用程序、框架、文档和视图类 19 2.2.1 CWinApp(O/C/W) 20 2.2.2 CView (O/C/W) 21 2.3 其他用户界面类 22 2.3.1 通用控件类 23 2.3.2 菜单类 23 2.3.3 对话框类 24 2.3.4 控制条类 24 2.3.5 属性类 25 2.4 绘图类 25 2.4.1 设备环境类 25 2.4.2 图形对象类 25 2.5 文件类 26 2.6 数据库类 26 2.6.1 ODBC类 26 2.6.2 DAO类 27 2.7 数据集类 27 2.8 其他数据类 27 2.9 通信类 28 2.10 其他类 29 2.11 小结 31 第3章 消息处理 32 3.1 发送或寄送一个消息 32 3.1.1 发送一个消息 32 3.1.2 寄送一个消息 32 3.1.3 发送一个消息与寄送一个消息 的比较 32 3.2 怎样使用MFC发送一个消息 33 3.3 怎样用MFC寄送一个消息 33 3.4 三种类型的消息 34 3.4.1 窗口消息 34 3.4.2 命令消息 34 3.4.3 控件通知 34 3.5 MFC怎样接收一个寄送的消息 36 3.6 MFC怎样处理一个接收到的消息 36 3.7 处理用户界面的对象 44 3.8 创建自定义窗口消息 45 3.8.1 静态分配的窗口消息 45 3.8.2 动态分配的窗口消息 46 3.9 重定向消息 47 3.9.1 子分类和超分类 47 3.9.2 用MFC子分类窗口 48 3.9.3 重载OnCmdMsg ( ) 49 3.9.4 使用SetWindowsHookEx ( ) 49 3.9.5 使用SetCapture ( ) 49 3.9.6 专有的消息泵 50 3.10 小结 50 第4章 绘图 51 4.1 设备环境 51 4.2 在MFC环境中创建一个设备环境 52 4.2.1 屏幕 52 4.2.2 打印机 53 4.2.3 内存 54 4.2.4 信息 54 4.3 绘图例程 55 4.3.1 画点 55 4.3.2 画线 55 4.3.3 画形状 55 4.3.4 形状填充和翻转 55 4.3.5 滚动 56 4.3.6 绘制文本 56 4.3.7 绘制位图和图标 56 4.4 绘图属性 56 4.4.1 设备环境属性 57 4.4.2 画线属性 58 4.4.3 形状填充属性 58 4.4.4 文本绘制属性 58 4.4.5 映像模式 59 4.4.6 调色板属性 62 4.4.7 混合属性 62 4.4.8 剪裁属性 63 4.4.9 位图绘制属性 64 4.5 元文件和路径 65 4.5.1 元文件 65 4.5.2 路径 66 4.6 颜色和调色板 66 4.6.1 抖动色 67 4.6.2 未经抖动色 67 4.6.3 系统调色板 67 4.6.4 使用系统调色板 68 4.6.5 动画色 71 4.7 控制什么时候在哪里绘图 71 4.7.1 处理WM_PAINT 71 4.7.2 只绘制被无效化的区域 72 4.7.3 处理WM_DRAWITEM 72 4.7.4 在其他时间绘图 73 4.8 小结 74 第二部分 用户界面实例 第5章 应用程序与环境 76 5.1 例1 规划MFC应用程序 76 5.2 例2 用AppWizard创建一个MFC 应用程序 79 5.3 例3 用ClassWizard创建一个类 83 5.4 例4 初始化应用程序屏幕 84 5.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值