简介:MFC(Microsoft Foundation Classes)是用于简化Windows应用程序开发的C++类库,特别是针对图形用户界面(GUI)的应用程序。本项目以实现画图功能为核心,详细描述了如何使用MFC中的类如CView、CDC以及GDI来构建丰富的用户交互式应用程序。开发者将深入了解MFC框架的结构、消息传递机制、GDI绘图方法,并通过实践提升在创建具有复杂图形界面的应用程序方面的技能。
1. MFC图形界面开发概述
在现代软件开发中,图形用户界面(GUI)不仅提供了与用户交互的美观方式,还直接影响着软件的可用性和用户的体验。微软基础类库(MFC)是一个用于创建Windows应用程序的C++类库,它封装了Windows API并提供了一种更为便捷和面向对象的方式来开发GUI。
MFC图形界面开发的核心思想是基于文档/视图架构模式,文档管理应用程序的数据,而视图则负责以图形方式显示这些数据。从简单的窗口应用程序到复杂的多文档界面(MDI)应用程序,MFC都能提供全面的支持。
本章将简要介绍MFC的历史背景、GUI开发的基本概念及其在当代软件开发中的重要性。我们将探讨MFC如何简化Windows编程,并为接下来的章节奠定基础。在后续章节中,我们将深入探讨如何搭建开发环境、创建应用程序、处理消息以及优化绘图技术。
2. MFC基础与GUI开发环境搭建
2.1 MFC简介及GUI开发
2.1.1 MFC的定义和特点
MFC(Microsoft Foundation Classes)是一个用于简化Windows应用程序开发的C++类库。MFC封装了Windows API(应用程序编程接口),使得开发人员可以使用面向对象的方法开发Windows平台上的应用程序,而无需直接与底层的Win32 API打交道。
MFC的特点可以概括为以下几点:
- 面向对象 :MFC使用C++语言的特性,如继承、封装、多态等,让开发者能够以面向对象的方式组织代码。
- 事件驱动编程模型 :MFC为Windows消息驱动机制提供了面向对象的框架和封装,简化了消息处理。
- 文档-视图架构 :MFC应用通常采用文档-视图架构,将数据处理(文档)与数据表示(视图)分离,提高了代码的可维护性。
- 可视化编辑 :MFC提供了资源编辑器,允许开发者通过图形化工具设计用户界面。
- 扩展性 :MFC为开发者提供了丰富的类库,涵盖了常用的各种功能,支持进一步的扩展和自定义。
2.1.2 MFC与Win32 API的关系
虽然MFC是为了简化Windows编程而设计的,但其核心仍是基于Win32 API。MFC在底层通过封装Win32 API提供了一组高级的C++类库。开发者在使用MFC时,实际上是在使用这些经过封装的API。
MFC与Win32 API的关系可以从以下几个方面来理解:
- 封装性 :MFC通过封装减少了代码量,同时提高了代码的可读性和可维护性。
- 兼容性 :虽然MFC提供了高级接口,但它依然可以调用任何Win32 API函数,保证了与原生Windows API的兼容性。
- 性能 :在必要时,开发者可以直接使用Win32 API来提高性能,但通常会牺牲一些代码的可读性。
- 灵活性 :对于特定的Windows特性和复杂功能,MFC可能没有提供封装,这时开发者需要直接使用Win32 API。
2.2 MFC应用程序框架结构
2.2.1 框架与文档的关系
MFC应用程序框架的基础是文档/视图结构。这种架构将应用程序的数据(文档)与其表现形式(视图)分开管理,有助于提高代码的模块化和可重用性。
- 文档类(CDocument) :负责数据的存储、加载和保存。它管理了应用的数据内容,但不负责如何显示这些数据。
- 视图类(CView) :负责数据的可视化表示和与用户的交互。视图类通常与一个文档对象关联,显示文档的数据。
- 框架窗口类(CFrameWnd) :包含菜单、工具栏和状态栏,并拥有视图窗口。它为应用程序提供了一个窗口环境。
2.2.2 MFC应用程序的启动流程
当MFC应用程序启动时,遵循以下流程:
- 初始化MFC库 :应用程序首先调用
AfxWinInit
函数初始化MFC库。 - 创建应用程序对象 :创建
CWinApp
派生类的对象,这个对象负责初始化应用程序并处理消息循环。 - 加载应用程序资源 :通过调用
InitInstance
函数,应用程序加载必要的资源,如菜单、图标等。 - 显示主窗口 :使用
ShowWindow
和UpdateWindow
函数显示应用程序的主窗口,并进入消息循环。 - 消息循环 :应用程序开始接收和处理消息。消息循环负责将Windows消息发送给相应的窗口过程函数处理。
2.3 开发环境的搭建与配置
2.3.1 Visual Studio中的MFC项目创建
在Visual Studio中创建一个MFC项目的基本步骤如下:
- 打开Visual Studio,选择“创建新项目”。
- 在项目模板中选择“MFC应用程序”。
- 输入项目名称,选择存储位置,并配置项目的其他设置。
- 在接下来的向导中,选择项目的类型,例如单文档界面(SDI)、多文档界面(MDI)或其他。
- 完成向导,Visual Studio将创建MFC项目的基本文件和结构。
2.3.2 必要的工具和库的安装与配置
为了有效地使用MFC进行开发,以下是一些必要的工具和库的安装与配置步骤:
- 安装Visual Studio :确保安装了包含MFC支持的Visual Studio版本。
- 配置MFC库 :在项目的链接器设置中添加
mfc.lib
和mfcs.lib
(或相应的DLL版本),这些是MFC程序运行时所需的库。 - 配置包含目录和库目录 :确保项目的编译器和链接器包含了正确的MFC头文件和库文件路径。
- 配置C运行时库 :根据项目需求选择合适的C运行时库版本(如多线程、动态链接等)。
以下是一个简单的代码块,展示了如何在MFC中创建一个消息框:
#include <afxwin.h> // MFC 核心组件和标准组件
#include <afxext.h> // MFC 扩展
class CMyApp : public CWinApp
{
public:
virtual BOOL InitInstance();
};
class CMyDoc : public CDocument
{
};
class CMyView : public CView
{
public:
CMyView() { }
protected:
virtual void OnDraw(CDC* pDC); // 重写此函数以绘制视图
};
BOOL CMyApp::InitInstance()
{
m_pMainWnd = new CMyView;
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
void CMyView::OnDraw(CDC* pDC)
{
pDC->TextOut(10, 10, _T("Hello, MFC!"));
}
CMyApp theApp;
在上述代码中,我们定义了一个MFC应用程序类 CMyApp
,一个文档类 CMyDoc
和一个视图类 CMyView
。 CMyApp
类重写了 InitInstance
方法来创建视图对象并显示窗口,而 CMyView
类重写了 OnDraw
方法以在视图上绘制文本。
MFC提供了一套丰富而强大的工具和类库,使得Windows应用程序开发变得更加高效和容易管理。通过安装Visual Studio和配置必要的工具和库,可以快速开始MFC项目的开发。在后续的章节中,我们将深入探讨如何使用这些工具和类库来构建功能丰富的Windows应用程序。
3. CView类与视图实现
CView类是MFC框架中的核心组件之一,它负责显示应用程序的用户界面和响应用户的交互操作。通过本章内容,我们将深入探讨CView类的工作原理,以及如何通过派生类来实现自定义的视图功能。
3.1 CView类的原理与作用
3.1.1 CView类在MFC中的角色
CView类在MFC中充当了视图组件的角色,它是连接用户界面和后端逻辑的桥梁。CView类提供了多种接口,包括消息处理、图形显示、交互事件处理等,使得开发者能够构建动态的、可交互的用户界面。
CView类继承自CWnd类,并实现了诸如绘图、滚动条管理、视图状态保存与恢复等功能。开发者通过创建CView的派生类,并重写相关函数来实现特定的视图行为。
3.1.2 视图与文档的关系
在MFC的文档/视图架构中,视图(View)和文档(Document)之间存在紧密的关联。文档类负责保存应用数据的逻辑表示,而视图类则负责将这些数据以图形化的方式展示给用户。一个文档可以关联多个视图,这使得同一数据集可以在不同的视图中以不同的形式展示。
MFC通过封装这些关系,使得视图和文档之间的同步更新变得简单。例如,当文档中的数据发生变化时,框架可以通知所有关联的视图进行更新。
3.2 CView派生类的创建与应用
3.2.1 创建自定义CView派生类
创建自定义CView派生类首先需要从CView类继承。开发者需要在派生类中重写特定的成员函数,如OnDraw、OnInitialUpdate等,以实现自定义的视图行为。以下是一个简单的例子:
class CMyView : public CView
{
protected:
// 重写视图的绘制函数
virtual void OnDraw(CDC* pDC);
// 视图初始化更新函数
virtual void OnInitialUpdate();
// 更多自定义函数...
};
在CMyView的实现文件中,需要定义这些函数的具体实现:
void CMyView::OnDraw(CDC* pDC)
{
// 绘图代码
}
void CMyView::OnInitialUpdate()
{
// 初始更新代码
CView::OnInitialUpdate();
}
通过这种方式,开发者可以根据需要定制视图的外观和行为。
3.2.2 视图中消息处理机制
MFC的消息处理机制是基于消息映射表的。开发者需要在派生类中使用宏如BEGIN_MESSAGE_MAP和END_MESSAGE_MAP来定义消息映射表,然后使用ON_MESSAGE等宏将消息和对应的处理函数关联起来。
在自定义CView派生类中处理消息的流程大致如下:
- 定义消息处理函数。
- 在消息映射表中将消息和处理函数关联。
- 实现消息处理函数。
示例代码片段:
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
void CMyView::OnPaint()
{
CPaintDC dc(this); // 设备上下文对象
// 绘图代码
}
void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
// 鼠标左键点击事件处理
}
通过上述步骤,开发者可以将用户的操作与特定的代码逻辑相绑定,实现丰富的用户交互体验。
3.3 视图类的图形显示与交互
3.3.1 视图刷新机制
视图的刷新机制主要依赖于框架自动调用OnDraw函数来实现。当视图需要更新时(例如窗口大小改变、文档数据更新等),框架会调用OnDraw函数来重绘视图。
开发者还可以通过调用Invalidate或UpdateWindow函数来手动触发视图的刷新。Invalidate函数标记视图区域为无效,导致框架在下一个绘图事件中调用OnDraw;UpdateWindow函数则直接刷新视图,不等待消息队列中的其他消息。
3.3.2 键盘与鼠标事件处理
CView类提供了一系列消息处理函数来响应键盘和鼠标事件,例如OnKeyDown、OnKeyUp、OnLButtonDown等。开发者可以通过重写这些函数来响应用户的输入事件。
下面是一个示例,展示如何响应键盘事件:
void CMyView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// 键盘按键事件处理
CView::OnKeyDown(nChar, nRepCnt, nFlags);
}
在处理这些事件时,开发者可以编写代码来实现特定的功能,比如根据用户的按键输入来调整视图显示的内容。
通过本章节的介绍,我们已经了解了CView类的基础知识以及如何创建和应用CView派生类。在下一章节中,我们将深入探讨GDI绘图技术,进一步了解如何在MFC中实现图形界面的绘制和优化。
4. 深入理解GDI绘图技术
4.1 GDI绘图技术简介
4.1.1 GDI概述及其在MFC中的应用
图形设备接口(GDI)是Windows操作系统中用于渲染文本、图形和图像的编程接口。GDI提供了与设备无关的编程模型,这意味着开发人员可以编写与硬件无关的代码,使得应用程序能够在不同的显示设备上保持一致的外观和功能。在MFC(Microsoft Foundation Classes)中,GDI被广泛用于实现复杂的图形用户界面(GUI)。
GDI对象包括用于定义绘图的实体,如笔(Pen)、画刷(Brush)、字体(Font)和位图(Bitmap)。这些对象被设备上下文(DC)所使用,DC是一个描述设备属性和绘图工具的结构体,它为图形对象提供了绘制表面。在MFC中,CView类及其派生类提供了与DC交互的接口,使得开发者可以不必直接与GDI API打交道。
4.1.2 GDI对象和设备上下文(DC)
设备上下文(DC)是GDI中的核心概念,它是一个抽象层,提供了一组函数来在不同的输出设备上进行绘图。DC持有设备的绘图信息,如颜色、字体、剪裁区域等。当在MFC应用程序中进行绘图时,实际上是通过一个指向DC的指针来进行的。
不同的设备可能有不同的DC类型,例如打印机和显示器。每种DC类型都有其特定的属性和行为,但它们都遵循相同的编程接口。MFC通过封装这些底层细节,提供了统一的DC接口。例如,CClientDC和CWindowDC类分别用于客户区和整个窗口的绘图。GDI对象在DC上操作,例如,使用CPen对象指定线条的样式和颜色,使用CBrush对象指定填充区域的样式和颜色。
4.2 GDI图形对象的使用与管理
4.2.1 笔、画刷、字体和位图的创建与使用
在GDI中,绘图的基础是GDI对象,包括笔、画刷、字体和位图。这些对象定义了绘图的各个方面,从简单的线条和填充图案到文本和复杂图像。
- 笔(CPen) :用于定义线条的粗细、样式和颜色。例如,创建一条红色的实线,可以使用如下代码:
CPen redPen(PS_SOLID, 1, RGB(255, 0, 0)); // 创建实线笔,宽度为1,红色
CDC* pDC = GetDC(); // 获取设备上下文
pDC->SelectObject(&redPen); // 选择笔到DC
pDC->MoveTo(10, 10); // 移动到起始位置
pDC->LineTo(100, 100); // 绘制线条到指定位置
pDC->ReleaseDC(); // 释放DC
- 画刷(CBrush) :用于定义填充区域的颜色和样式。例如,创建一个红色的空心画刷:
CBrush redBrush(BS_HOLLOW, RGB(255, 0, 0)); // 创建红色空心画刷
CDC* pDC = GetDC(); // 获取DC
pDC->SelectObject(&redBrush); // 选择画刷到DC
pDC->Rectangle(50, 50, 150, 150); // 绘制红色空心矩形
pDC->ReleaseDC(); // 释放DC
- 字体(CFont) :用于定义文本的样式、大小和类型。例如,创建一个12像素的Arial字体:
CFont font;
font.CreatePointFont(120, _T("Arial")); // 创建Arial字体,大小为12点
CDC* pDC = GetDC(); // 获取DC
pDC->SelectObject(&font); // 选择字体到DC
pDC->TextOut(10, 10, _T("Hello, GDI!")); // 输出文本
pDC->ReleaseDC(); // 释放DC
- 位图(CBitmap) :用于定义图像数据,可以用于显示图像或作为绘图的基础。例如,加载一个位图文件:
CBitmap bitmap;
bitmap.LoadBitmap(IDB_MYBITMAP); // 加载一个名为IDB_MYBITMAP的位图资源
CDC* pDC = GetDC(); // 获取DC
pDC->BitBlt(10, 10, bitmap.GetWidth(), bitmap.GetHeight(), bitmap.GetDC(), 0, 0, SRCCOPY); // 将位图绘制到DC
pDC->ReleaseDC(); // 释放DC
4.2.2 GDI对象的内存管理
GDI对象在使用时需要进行创建和选择(或“选入”)到设备上下文中。当不再需要时,应该将这些对象从设备上下文中移除(或“选出”),并进行适当的删除,以避免资源泄漏。以下是一些最佳实践:
-
对象选入和选出 :在对DC进行操作时,应该先选择当前GDI对象到DC,然后进行绘制。绘制完成后,应选择原对象回到DC,并删除临时对象。
cpp CDC* pDC = GetDC(); CPen oldPen; // 用于保存原对象 pDC->SelectObject(&oldPen); // 保存旧笔对象 CPen newPen(PS_SOLID, 1, RGB(255, 0, 0)); // 创建新笔对象 pDC->SelectObject(&newPen); // 选入新笔对象 pDC->MoveTo(10, 10); pDC->LineTo(100, 100); pDC->SelectObject(&oldPen); // 选回旧笔对象 pDC->ReleaseDC();
-
资源删除 :创建的GDI对象(如CPen,CBrush,CFont等)在不再使用时,应该调用
DeleteObject
进行删除。
cpp redPen.DeleteObject(); // 删除笔对象 redBrush.DeleteObject(); // 删除画刷对象 font.DeleteObject(); // 删除字体对象 bitmap.DeleteObject(); // 删除位图对象
- 使用RAII技术 :为了避免忘记删除GDI对象,可以使用C++的RAII(Resource Acquisition Is Initialization)技术,例如通过重载
operator new
和operator delete
来自动管理资源。
4.3 GDI绘图实践
4.3.1 基本绘图函数的使用
MFC中的CView类提供了许多成员函数用于GDI绘图操作。以下是一些基本的绘图操作函数:
-
CDC::MoveTo
和CDC::LineTo
:在设备上下文中移动到指定点,并绘制线条到另一点。 -
CDC::Rectangle
:绘制矩形边框。 -
CDC::FillSolidRect
:使用画刷填充指定矩形区域的实心颜色。 -
CDC::SetPixel
:设置指定点的颜色。 -
CDC::BitBlt
:从一个DC中拷贝像素数据到另一个DC中,常用于图像处理。
示例代码:
CDC* pDC = GetDC();
pDC->Rectangle(10, 10, 200, 200); // 绘制一个190x190像素的矩形
pDC->SetPixel(50, 50, RGB(0, 0, 255)); // 在(50, 50)位置绘制一个蓝色的点
pDC->ReleaseDC();
4.3.2 图形绘制的高级技巧
为了实现更复杂的图形效果,GDI提供了多种高级绘图技巧:
-
坐标变换 :通过
CDC::LPtoDP
和CDC::DPtoLP
可以进行逻辑坐标与设备坐标之间的转换,这对于图形变换(如旋转、缩放)非常有用。 -
Alpha混合 :
CDC::SetBkMode
和CDC::SetROP2
可以与CDC::GradientFill
结合使用来实现透明和半透明效果。 -
路径(CPen) :
CDC::BeginPath
、CDC::EndPath
和CDC::StrokeAndFillPath
可以创建复杂的形状路径,并进行填充和描边。
示例代码:
CDC* pDC = GetDC();
pDC->SetBkMode(TRANSPARENT);
pDC->SetROP2(R2_NOTXORPEN);
pDC->Rectangle(10, 10, 200, 200);
pDC->ReleaseDC();
在这一节中,我们了解了GDI绘图技术的基础知识,如何创建和管理GDI对象以及如何应用这些对象进行基本和高级绘图。GDI的强大功能为MFC应用程序提供了丰富的视觉效果。接下来的章节将会深入讨论MFC中的消息处理机制,这是应用程序响应用户操作的基石。
5. MFC消息处理机制深入解析
在前一章中,我们已经深入了解了视图类如何与用户交互以及GDI绘图技术的高级应用。现在,我们将深入探讨MFC的消息处理机制,这是每个MFC程序的核心,也是编程中最具挑战性的部分之一。
5.1 WM_PAINT消息处理
5.1.1 WM_PAINT消息的产生与处理
WM_PAINT消息是当应用程序的窗口客户区域需要被绘制时产生的消息。它是GDI绘图中非常重要的一个消息,因为几乎所有的绘图操作都会与这个消息关联。Windows通过发出WM_PAINT消息来通知应用程序需要进行绘制更新。
在MFC中,处理WM_PAINT消息通常涉及到OnPaint函数。当发生重绘事件时,MFC框架会调用该函数,此时用户可以通过重写OnPaint函数来执行绘制代码。例如:
void CMyView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: 在此处添加消息处理程序代码
// 不要调用 CView::OnPaint() 对于此消息
}
5.1.2 双缓冲技术与闪烁控制
闪烁问题是导致用户体验不佳的主要因素之一。双缓冲技术就是用来解决这个问题的方法之一,它通过在内存中创建一个与屏幕显示区域大小相同的位图(称为缓冲区),然后在这个位图上进行所有的绘制操作,绘制完成后再一次性地将整个缓冲区的内容绘制到屏幕上。
在MFC中实现双缓冲的方法如下:
CDC memDC; // 内存设备上下文
CBitmap memBitmap; // 内存中的位图
CBitmap* pOldBitmap; // 旧位图指针
// 初始化
memDC.CreateCompatibleDC(&dc); // 创建兼容的内存设备上下文
memBitmap.CreateCompatibleBitmap(&dc, rect.Width(), rect.Height()); // 创建与屏幕兼容的位图
pOldBitmap = memDC.SelectObject(&memBitmap); // 选择新的位图到内存设备上下文中
// 在memDC上绘制
// ...
// 将绘制好的内容绘制到屏幕
dc.BitBlt(0, 0, rect.Width(), rect.Height(), &memDC, 0, 0, SRCCOPY);
// 清理
memDC.SelectObject(pOldBitmap); // 恢复原来的位图
memBitmap.DeleteObject(); // 删除创建的位图
memDC.DeleteDC(); // 删除内存设备上下文
5.2 用户交互消息的处理
5.2.1 键盘消息的捕获与响应
键盘消息分为两种:键盘输入消息(如WM_KEYDOWN, WM_KEYUP)和键盘焦点消息(如WM_SETFOCUS, WM_KILLFOCUS)。通过重写视图类或对话框类中的相关函数,可以实现对键盘消息的响应。
例如,要捕获按下F1键,可以在视图类中重写OnKeyDown函数:
void CMyView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
if(nChar == VK_F1)
{
AfxMessageBox(_T("F1按键被按下!"));
}
}
5.2.2 鼠标消息的捕获与响应
MFC框架同样提供了多种鼠标消息处理函数,如OnLButtonDown, OnLButtonUp, OnMouseMove等。要捕获鼠标事件,只需重写这些函数即可。
void CMyView::OnLButtonDown(UINT nFlags, CPoint point)
{
AfxMessageBox(_T("鼠标左键被按下!"));
}
5.3 消息映射与消息传递
5.3.1 消息映射表的创建与使用
消息映射机制允许开发者将特定的消息与处理这些消息的成员函数关联起来。这通常是通过使用宏来实现的。在MFC中,消息映射宏主要包含DECLARE_MESSAGE_MAP() 和 BEGIN_MESSAGE_MAP/END_MESSAGE_MAP()。
例如,在视图类中,开发者通常会在类声明中使用DECLARE_MESSAGE_MAP宏,在实现文件中使用BEGIN_MESSAGE_MAP、ON_MESSAGE宏和END_MESSAGE_MAP宏,如下所示:
// 类声明
class CMyView : public CView
{
DECLARE_MESSAGE_MAP()
};
// 类实现
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_WM_PAINT()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
5.3.2 消息传递机制的深入理解
当MFC应用程序接收到消息时,MFC框架会自动将消息传递到消息映射表中,寻找与消息对应的处理函数进行处理。如果消息没有在当前对象中得到处理,MFC框架会继续沿着MFC的类层次结构进行消息传递,直至消息被处理或被忽略。
MFC还提供了一种自定义消息传递机制,允许开发者使用消息映射宏发送自定义消息。开发者可以使用ON_REGISTERED_MESSAGE宏来注册自定义消息,并使用AfxRegisterMsg函数进行消息注册。
例如,注册一个自定义消息:
UINT WM_CUSTOM_MSG = ::RegisterWindowMessage(_T("MyCustomMessage"));
BEGIN_MESSAGE_MAP(CMyView, CView)
ON_REGISTERED_MESSAGE(WM_CUSTOM_MSG, &CMyView::OnMyCustomMsg)
END_MESSAGE_MAP()
处理自定义消息:
LRESULT CMyView::OnMyCustomMsg(WPARAM wParam, LPARAM lParam)
{
// 处理消息
}
通过本章节内容的介绍,我们了解到了MFC中消息处理机制的重要性,以及如何在实际应用中处理各种消息。这不仅仅是理论上的知识,而且需要在实际开发中不断地实践和应用。下一章我们将继续深入,讨论MFC框架类层次结构以及资源文件的管理与使用。
简介:MFC(Microsoft Foundation Classes)是用于简化Windows应用程序开发的C++类库,特别是针对图形用户界面(GUI)的应用程序。本项目以实现画图功能为核心,详细描述了如何使用MFC中的类如CView、CDC以及GDI来构建丰富的用户交互式应用程序。开发者将深入了解MFC框架的结构、消息传递机制、GDI绘图方法,并通过实践提升在创建具有复杂图形界面的应用程序方面的技能。