MFC及其应用
WINDOWS应用程序一定要有WinMain 函数,该函数用来完成一些特殊的任务, 象创建程序的主窗口,主窗口用来处理消 息的代码。 MFC将WinMain隐藏在框架中,不象写 SDK程序时可以很容易的找到它。
WINDOWS采用的消息处理机制也交给了程序框架,我们不必担心如何使这些消息和代码联系起来 . WINDOWS定义好了一些消息,当窗口被创建时系统就会发送WM_CREATE消息. 当点击鼠标左键时便系统会发送WM_LBUTTONDOWN消息 当用户按下键盘时系统会发送WM_CHAR消息 当用户关闭窗口时系统会发送WM_CLOSE消息 当用户进行菜单项选择或单击按钮时系统回发送WM_COMMAND消息 什么都不做系统还会发送WM_TIMER消息
WINDOWS提供通用的图形设备接口(GUI),我们通过调用(GDI)函数和硬件打交道,不必理会设备环境,WINDOWS会自动将设备环境结构映射到相应的物理设备,这就是设备无关性。 动态连接库(DLL)应该是代码重用的典型例子(不知道可不可这样说),把一些模块、自己新编的类单独调试并编译成DLL,及增加代码的可读性也提高了程序模块的灵活性。
Developer Studio 创建的相关中间文件 APS -> 支持ResourceView BSC -> 浏览器信息文件 CLW -> 支持ClassWizard DSP -> 项目文件,不能删除和 用文本编辑器编辑 DSW -> 项目文件,不能删除和 用文本编辑器编辑
Developer Studio 创建的相关中间文件 MAK -> 外部的创建文件 NCB -> 支持ClassView OPT -> 保存工作空间的配置 PLG -> 建立日志文件 这些文件都有一定的作用,如CLW,如果你有 一个新类,需要加到ClassWizard中,除了将相 应的.h 和.cpp加到DSP中还需要重新编译CLW。 PLG文件记录着你的项目配置信息 …
MFC 特点 ◎MFC是C++的Microsoft Windows API,如果想要开发WINDOWS的应用程序当然VC/MFC是开发环境的首选。 ◎MFC产生的应用程序使用了标准化的 结构。 ◎MFC产生的应用程序短而运行速度快。 ◎VC++工具降低了编码的复杂性。 ◎MFC库功能非常丰富。
最简单的MFC例子 ”Hello,World” HELLO WORLD用AppWizard向导创建一个 显示一个字符串的单文档程序,只需要敲入一行 语句,完全体现了MFC的强大功能。 1、打开VC++6从菜单选择NEW,给项目命名为 ”MyApp01“。 2、选择MFC AppWizard[exe] 选项,除STEP 1选 择单文档外其他STEP缺省。
最简单的MFC例子 ”Hello,World” 3、在Class View选择CMyApp01View类的 OnDraw()成员函数双击会在C++编译器看 到以下内容: void CMyApp01View::OnDraw(CDC* pDC) { CMyApp01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here }
最简单的MFC例子 ”Hello,World” 在 // TODO: add draw code for native data here的位置增加一行代码 void CMyApp01View::OnDraw(CDC* pDC) { CMyApp01Doc* pDoc = GetDocument(); ASSERT_VALID(pDoc); pDC->TextOut(10,10," Hello,World "); //增加的一行 // TODO: add draw code for native data here }
MFC程序中的元素 ①WinMain函数:并非不存在只是已经被隐藏 在应用程序框架内部。 ②CMyApp类:CMyApp类的对象代表一个应用 程序,CWinApp基类决定它的大部分行为。 ③应用程序的启动:当开始运行应用程序时 WINDOWS会调用WinMain函数,WinMain会 查找该应用程序的全局对象theApp。 ④CMyApp::InitInstance成员函数: 发现theApp后自动调用重载的虚函数 InitInstance来完成主窗口的构造和显示工作。
MFC程序中的元素 ⑤CWinApp::Run成员函数:WinMain在调用 InitInstance之后紧接着调用Run函数,它被 隐藏在基类中负责传递应用程序的消息给相 映的窗口。 ⑥CMyFrame类:此类的对象代表着应用程序 的主窗口。它的构造函数调用基类CFrameWnd 的Create函数创建具体的窗口结构。 ⑦CMyFrame::OnLButtonDown函数:演示消息 处理机制,当鼠标坐键被按下这一事件被映射 到CMyFrame的OnLButtonDown函数上,如果 你选择F5进行编译运行的话可以在调试窗口看 到TRACE宏显示的信息
MFC程序中的元素 ⑧CMyFrame::OnPaint函数:应用程序每次重新 绘制窗口都需要调用此函数,将显示 “Hello World!”放在这里是因为每次窗口发生变化 时保证"Hello World!"被显示,你可以试着将语句: CPaintDC dc(this); dc.TextOut (0,0,"Hello World!"); 写在别出,例如写在 void CMyFrame::OnLButtonDown (UINT nFlags,CPoint point) { TRACE("Entering CMyFrame::OnLButtonDown - %lx,%d,%d\n", (long)nFlags,point.x ,point.y); CPaintDC dc(this); dc.TextOut (0,0,"Hello World!"); }
MFC程序中的元素 运行后当点击左键时显示“Hello World!”, 但当窗口最小化再最大化时"Hello World!"不见了。 ⑨关闭应用程序:用户关闭应用程序时会有一 系列事件发生。首先CMyFrame对象被删除, 然后退出Run,进而退出WinMain,最后 删除CMyApp对象。 上面的示例可见程序的大部分功能包含在基类CWinApp和CFrameWnd中,我们只写了很少的函数,便可以完成很复杂的功能。所以应用程序框架不仅仅是一种类库,它还定义了应用程序的结构,除了基类外还包括WinMain函数,以及用来支持消息处理、诊断、DLL、等都包含在应用程序框架中。
MFC的消息映射 MFC是通过一些宏来将特定的消息影射到派生类 相应的成员函数上,这种体制的好处是允许某些 非窗口类(如文档类)来控制命令消息。 且不需要C++作任何扩展。 MFC的消息控制函数要求提供函数原形、函数体 以及消息映射中的入口。 用Class Wizard可以很容易的将上面内容加到 类中。例如只要在Class Wizard中添加 WM_LBUTTONDOWN消息,则相应的代码 便加在合适的地方。
MFC的消息映射 应用程序除了包含应用程序框架类外,一般 还要包含文档和视图类。 这种文档-视图结构是应用框架的核心。 文档好比后台的数据库,视图就是界面上显示 的内容,同一个数据库可以用不同的界面显示, 但由于所有的界面内容都是从数据库中数据得来 ,所以当数据库发生变化时所有的相关界面显示 都会跟着改变。 应用程序实际上就是通过视图对文档进行一系 列操作。
MFC 视图 视图是一个从CView类派生的类的对象, 在屏幕上显示的窗口就是一种。 对象的行为完全由类的成员函数和数据成员 决定,其中及包括派生类中的特定函数,也 包括基类的标准函数,所以有必要了解MFC 类库的结构以及各类的标准成员函数 。 我们来回顾前面例子项目程序所在目录下 的相关文件:
MFC 视图 myapp01.dsp ---项目文件 myapp01.dsw ---工作空间文件 myapp01.rc ---资源描述文件 myapp01View.cpp ---包含CMyAppView 类成员函数的视图类实现文件 myapp01View.h ---包含CMyAppView 类成员函数的视图类头文件 myapp01.opt ---二进制文件,告诉 Developer Studio本项目的哪些文件是打开 的,又是如何排列的
MFC 视图 readme.txt ---用来解释所产生的所有文件, 未列出的myapp01Doc.cpp、myapp01Doc.h、 StdAfx.cpp、StdAfx.h....在这里都可以找到 相应解释。 resource.h ---包含#define常量定义的头文件 CMyAppView类的OnDraw成员函数,它是虚函数, 作用是每当窗口需重绘时应用程序框架会调用它。
MFC 视图 在myapp01View.h可以找到OnDraw原型 : 参数是CDC类的指针,WINDOWS是通过和 virtual void OnDraw(CDC* pDC); // overridden to draw this view 参数是CDC类的指针,WINDOWS是通过和 窗口相关联的设备环境(CDC类的对象就是 设备环境)和显示硬件进行通讯。 有了这个指针我们便可以调用CDC类的成员 函数来完成各种绘制工作 。 如前面用到的TextOut(),还有一些如Ellipse()、 Polygon()、BitBlt()等 。
MFC 资源文件 资源文件(就是以应用程序名和扩展名是.rc 的文件)很大程度上决定了应用程序的用户界面。 在VC++中资源文件包括以下内容: Accelerator --->模拟菜单和工具栏的选择内容 Dialog --->对话框的布局及内容 Icon ---> 图标有两种一种是16X16一种是32X32 Menu---> 应用程序的主菜单及所属的弹出式菜单 String table --->字符串不属于C++源代码部分 Toolbar --->工具条 Version --->程序的描述、版本号、支持语言信息
MFC 资源文件 以上信息都在.rc文件中包含,同时.rc文件 还包含了以下语句: #include “afxres.h” #include “afxres.rc” 它们的作用是把适合于所有应用程序的一些通用MFC库资源包含进来。 需要注意的是虽然resource.h是一个ASCII码文件 可以用文本编辑器进行编辑,但如果使用文本编 辑器进行编辑的话,下次再使用资源编辑器时所 做的修改有可能丢失,所以我们应该在尽量在资 源编辑器中编辑应用程序的资源,新增的资源内 容会自动地添加在我们的程序相应位置。
MFC编译模式 在VC++中有两种编译模式,一种是Release Build另一种是Debug Build。 的是MFC Release库,编译十对应用程序的 速度进行优化,而Debug Build则正好相反, 它允许对源代码进行调试,可以定义和使用 MFC的诊断宏,采用MFC Debug库,对速度 没有优化。
MFC编译模式 所以我们应该在Debug模式下开发应用程序, 然后在Release模式下发布应用程序。在我们 诊断宏是我们编译程序时检测程序状态的有利 工具,利用TRACE宏,可以在Debug窗口获得 你需要的诊断信息,而不用设置对话框之类的 方法,在发布时Release会自动滤掉此信息。 有了VC++提供的调试工具如诊断宏、设断点、 单步执行等等,会让我们省不少力气。
MFC基本事件处理 我们已经知道MFC库应用程序框架调用CView 视图类的虚函数OnDraw来完成屏幕显示。 其实CView和CWnd类包含了几百个成员函数, 在MSDN中可以看到这些成员函数, 其中有许多On开头的,前面的例子就有一个 OnLButtonDown,它们都是应用程序框架响 应各种事件所需调用的函数。 OnDraw便是当窗口发生变化是被调用的, OnLButtonDown是鼠标左键被按下时调用, 还有OnKeyDown是键盘被按下时调用等等。
MFC基本事件处理 当用户在视窗中按下鼠标左键时,Windows会 自动发送WM_LBUTTONDOWN消息给该视窗, 当然你可以什么都不做,如果你想要让程序对 此消息做出反应就必须在视图类给出相应的函数, 类似下面这样: void CMyView::OnLButtonDown(UINT nFlags,CPoint point) { //做些事情的代码 } 还需要在类头文件包含相应的函数原型说明 afx_msg void OnLButtonDown(UINT nFlags,CPoint point); afx_msg只是说明该函数原型是针对消息映射函数。
MFC基本事件处理 下一步在代码文件中还需要有一个消息映射宏, 作用是把OnLButtonDown函数和应用程序框架 联系在一起。 BEGIN_MESSAGE_MAP(CMyView,CView) ON_WM_LBUTTONDOWN END_MESSAGE_MAP() 最后在类库的头文件还需包含: DECLARE_MESSAGE_MAP() 函数和Windows消息的对应关系可以从MSDN中 找到在MSDN中索引输入(WM_ Messages) 便会列出所有的Windows消息和消息控制函数原型。
MFC基本事件处理 在实际的编程过程中我们不可能全部都用手工 的添加或编制消息控制函数。除了一些特殊的, 我们一般是借助Class Wizard来自动编制消息 映射函数。这又是MFC应用程序框架比起SDK 来的有一个便捷的地方。 MFC库对140种windows消息直接提供了消息控 制函数,并且我们还可以自己定义自己的消息。 下面列出的几种消息是我们应该特别注意的: (MSDN上有更详细的内容)
MFC基本事件处理 该消息是Windows发给视图的第一个消息。 当应用程序框架调用create函数时该消息便 WM_CREATE 该消息是Windows发给视图的第一个消息。 当应用程序框架调用create函数时该消息便 会被发送,此时窗口还未创建完成,不可见, 因此在消息控制函数OnCreate内不能调用那些 依赖窗口处于完全激活状态的Windows函数。 如果需要可以在重载的OnInitialUpdate函数内 调用。不过注意在SDI应用程序OnInitialUpdate 函数可能被多次调用。
MFC基本事件处理 当用户关闭窗口时,系统会发送WM_CLOSE消息。 如果派生类重新定义了OnClose函数,就可以完全 控制关闭过程,可以将提醒用户存盘之类的工作 放在这里完成。 WM_QUERYENDSESSION 从字面的意思看就可以看出,当用户退出 Windows时,或者调用了ExitWindows 函数时。 Windows会发送WM_QUERYENDSESSION消息 给所有的正在运行的应用程序,由 OnQueryEndSession消息映射函数对消息进行处理。 在它之后应该是WM_ENDSESSION 消息。
MFC基本事件处理 在Windows发送WM_CLOSE消息后,紧接着会 发送WM_DESTROY消息,虽然窗口已经Close 但实际上并没有完全清除,在任务管理器中还 可以看见应用程序的进程(我想很多木马或病毒 都是无窗口的程序,它们的做法是生成了已经活动 状态的窗口但不显示出来),利用这个消息控制 函数便可以对依赖于当前窗口存在的东西做清除 工作,不过一定要注意,应该调用基类的 OnDestroy函数,而不能在用户自己的视图的 OnDestroy函数中终止窗口的析构过程,终止 析构过程应该在OnClose函数中。
MFC映射模式 在窗口显示图形,更准确的说是在窗口指定位置 显示图形或文字,我们使用的坐标单位是象素, 称之为设备坐标。 pDC->Rectangle(CRect(0,0,200,200)); 画一个高和宽均为200个象素的方块,因为采用 的是默认的MM_TEXT映射模式,所以在设备环境 不一样时,画的方块大小也不一样,在1024*768 的显示器上看到的方块会比640*480的显示器上 的小(在不同分辨率下的屏幕象素), 在输出到打印机时也会有类似的情况发生。
MFC映射模式 如何做才能保证在不同设备上得到大小一致的 方块或者图形、文字呢? 需要进行模式映射选择,来转换设备坐标 和逻辑坐标。 Windows提供了以下几种映射模式: MM_TEXT MM_LOENGLISH MM_HIENGLISH MM_LOMETRIC MM_HIMETRIC MM_TWIPS MM_ISOTROPIC MM_ANISOTROPIC
MFC映射模式 默认的映射模式,把设备坐标被映射到象素。 x值向右方向递增;y值向下方向递增。 坐标原点是屏幕左上角(0,0)。 MM_TEXT 默认的映射模式,把设备坐标被映射到象素。 x值向右方向递增;y值向下方向递增。 坐标原点是屏幕左上角(0,0)。 可以通过调用CDC的SetViewprotOrg和 SetWindowOrg函数来改变坐标原点的位置。 void CMyView::OnDraw(CDC * pDC) { pDC->Rectangle(CRect(0,0,200,200)); //全部采用默认画一个宽和高为200象素的方块 }
MFC映射模式 这两个例子显示出来的图形是否一样 ? void CMyView::OnDraw(CDC * pDC) { pDC->SetMapMode(MM_TEXT); //设定映射模式为MM_TEXT pDC->SetWindowOrg(CPoint(100,100)); //设定逻辑坐标原点为(100,100) pDC->Rectangle(CRect(0,0,200,200));//*** //画一个宽和高为200象素的方块 } 这两个例子显示出来的图形是否一样 ? pDC->Rectangle(CRect(100,100,300,300)); //***改成上句哪?
MFC映射模式 固定比例映射模式: MM_LOENGLISH、MM_HIENGLISH、 MM_LOMETRIC、MM_HIMETRIC、MM_TWIPS 是Windows提供的重要的固定比例映射模式。 它们都是x值向右方向递增,y值向下递减。 它们之间的区别在于比例因子: MM_LOENGLISH 0.01英寸 MM_HIENGLISH 0.001英寸 MM_LOMETRIC 0.1mm MM_HIMETRIC 0.01mm MM_TWIPS 1/1440英寸 //应用于打印机,一个twip相当于1/20磅,一磅又相当于1/72英寸。
MFC映射模式 还有一种是可变比例映射模式, MM_ISOTROPIC、MM_ANISOTROPIC。 void CMyView::OnDraw(CDC * pDC) { pDC->SetMapMode(MM_HIMETRIC); //设定映射模式为MM_HIMETRIC pDC->Rectangle(CRect(0,0,4000,-4000)); //画一个宽和高为4厘米的方块 } 还有一种是可变比例映射模式, MM_ISOTROPIC、MM_ANISOTROPIC。
MFC映射模式 用这种映射模式可以做到当窗口大小发生变化 时图形的大小也会相应的发生改变,同样当翻 转某个轴的伸展方向时图象也会以另外一个轴 为轴心进行翻转,并且我们还可以定义任意的 比例因子。 MM_ISOTROPIC、MM_ANISOTROPIC两种映射 模式的区别在于MM_ISOTROPIC模式下无论比 例因子如何变化纵横比是1:1而 M_ANISOTROPIC模式则可以纵横比独立变化。
MFC映射模式 void CMy002View::OnDraw(CDC* pDC) { CRect rectClient; // GetClientRect(rectClient); //返回客户区矩形的大小 pDC->SetMapMode(MM_ANISOTROPIC); //设定映射模式为MM_ANISOTROPIC pDC->SetWindowExt(1000,1000); pDC->SetViewportExt (rectClient.right ,-rectClient.bottom ); //用SetWindowExt和SetViewportExt函数 设定窗口为1000逻辑单位高和1000逻辑单位宽 pDC->SetViewportOrg(rectClient.right/2,rectClient.bottom/2 ); //设定逻辑坐标原点为窗口中心 pDC->Ellipse(CRect(-500,-500,500,500)); //画一个撑满窗口的椭圆。 // TODO: add draw code for native data here }
MFC映射模式 怎么样,屏幕上有一个能跟随窗口大小改变 而改变的椭圆。 把pDC->SetMapMode(MM_ANISOTROPIC); 这句改为pDC->SetMapMode(MM_ISOTROPIC) 会怎样?大家可以试试。那还有一个问题就是 上例的比例因子是多少呢? x比例因子=rectClient.right/1000 //视窗的宽除以窗口范围 y比例因子=-rectClient.bottom/1000 //视窗的高除以窗口范围
MFC映射模式 我们有时需要利用物理坐标,物理坐标的概念 就是现实世界的实际尺寸。 设备坐标-逻辑坐标-物理坐标之间如何进行转换 便成为我们要考虑的一个问题,物理坐标和逻辑 坐标是完全要我们自己来做的,但WINDOWS 提供了函数来帮助我们转换逻辑坐标和设备坐标。 CDC的LPtoDP函数可以将逻辑坐标 转换成设备坐标 CDC的DPtoLP函数可以将设备坐标 转换成逻辑坐标
MFC映射模式 下面列出我们应该在什么时候使用什么样 的坐标系一定要记住: ◎CDC的所有成员函数都以逻辑坐标为参数 ◎CWnd的所有成员函数都以设备坐标为参数 ◎区域的定义采用设备坐标 ◎所有的选中测试操作应考虑使用设备坐标 ◎需要长时间使用的值用逻辑坐标或物理坐标 来保存。 因设备坐标会因窗口的滚动变化而改变。
图形设备接口(GDI) 设备环境类CDC CDC是设备环境类的基类直接由CObject派生。 是GDI的关键元素,它代表了物理设备。 每一个C++设备环境对象都有相对应Windows 设备环境,并通过一个32位类型的HDC句柄 来标识。 CDC类的虚拟性使我们可以很容易的做到编写 同时适用于多种设备的代码。 如OnDraw函数的pDC->TextOut(0,0,"Hello"); 既可以适用于显示器、还可以适用于打印预览 和打印,只需要在CView::OnDraw函数的pDC 参数指向不同的对象类。
图形设备接口(GDI) CClientDC和CWindowDC是显示设备环境类, 都是由CDC派生而来,区别在于CClientDC是 窗口的客户区不包括边框、标题栏和菜单栏, (0,0)指客户区域的左上角。 CWindowDC的(0,0)指整个屏幕的左上角, 这意味着我们可以在显示器的任意地方绘图, 包括窗口边框、标题栏和菜单栏等等。 CWindowDC一般应用在框架窗口,而不是 视图窗口。
图形设备接口(GDI) 创建的设备环境对象具有一些默认的特性, 通过CDC类的成员函数可以设定这些特性。 例如刷子、映射模式等等。我们可以通过重载 SelectObject函数将GDI对象选进设备环境中。 GDI对象是通过CGdiObject派生类的C++对象 来表示的。 CBrush是一个GDI的派生类,它在MFC中的层次 结构是这样的:CObject派生CGdiObject派生 CBrush。CGdiObject是所有GDI对象的抽象基类。
图形设备接口(GDI) 下面列出的是GDI派生类的列表: CBitmap:位图是一种位矩阵,每一个显示象素 都对应于其中的一个或多个位,可以用来表示 图象,也可以用来创建刷子 CBrush:刷子定义了一种位图形式的象素, 可以用来对区域内部填充颜色。 CFont:字体是一种具有某种风格和尺寸的所有 字符的完整集合,常常被作为资源,其中一些 依赖某种设备。
图形设备接口(GDI) CPalette:调色板是一种颜色映射接口,它允许 应用程序在不影响其他应用程序的前提下,可 以充分利用输出设备的颜色描绘能力。 CPen:笔是一种用来画线及绘制有形边框的 工具,可以指定它的颜色及宽度,并可以指定 画虚线、点线还是实线。 CRgn:区域是由多边形、椭圆二者组合形成的 一种范围,可以用来进行填充、裁剪、鼠标点 中测试等等。
图形设备接口(GDI) CGdiObject类很眼生,看过很多代码就没有看 到过它,原因是由于CGdiObject类是所有GDI 对象类的虚拟基类,所以我们不必创建 CGdiObject类的对象,可以直接构造它的派生 类的对象,例如 : CPen newPen(PS_DASHDOTDOT,2,(COLORREF) 0); //黑色的笔宽度为2 但需要注意的是CFont和CRgn的对象建立需要 先调用默认的构造函数来构造C++对象,然后 再调用相应的创建函数如: CreateFont或CreatePolygonRgn等。
图形设备接口(GDI) CGdiObject类有一个虚拟的析构函数,它派生类 的析构函数需要将与C++对象相关联的GDI对象 删除掉,一定要在退出程序之前把构造的 CGdiObject派生类对象释放掉。因为一个没有 释放的GDI对象会占用很多的内存。
图形设备接口(GDI) void CMy10View::OnDraw(CDC* pDC) { pDC->MoveTo (10,10); pDC->LineTo (110,10); CPen newPen(PS_DASHDOTDOT,10,(COLORREF) 192); //红色的笔宽度为10 CPen * pOldPen=pDC->SelectObject (&newPen); //在将新对象选进设备环境的同时返回指向前一次被选 对象的指针。作用保存原来的对象,以便完成任务时恢复它。 pDC->MoveTo (10,20); pDC->LineTo (110,20); pDC->SelectObject (pOldPen);//把原来的对象恢复 pDC->MoveTo (10,30); pDC->LineTo (110,30); }
图形设备接口(GDI) 屏幕上应该显示三条线,第一条和第三条一样 颜色和粗细因为他们都是用的设备环境默认的 CPen对象,第二条是一条用我们自己设定的 CPen对象。我们可以看出在将新对象选进设备 环境的同时返回指向前一次被选对象的指针。 作用保存原来的对象,以便完成任务时恢复它。 Windows还包含有一些可以利用的库存对象, 它们不会被删除。我们可以用SelectStockObject 函数将它们选进设备环境。
图形设备接口(GDI) 下面列出的是所有的有关刷子、笔、字体和 调色板的库存对象: // MSDN中的内容 BLACK_BRUSH //Black brush. DKGRAY_BRUSH //Dark gray brush. GRAY_BRUSH //Gray brush. HOLLOW_BRUSH //Hollow brush. LTGRAY_BRUSH //Light gray brush. NULL_BRUSH //Null brush. WHITE_BRUSH //White brush. BLACK_PEN //Black pen. NULL_PEN //Null pen. WHITE_PEN //White pen.
图形设备接口(GDI) ANSI_FIXED_FONT //ANSI fixed system font. ANSI_VAR_FONT // ANSI variable system font. DEVICE_DEFAULT_FONT //Device-dependent font. OEM_FIXED_FONT //OEM-dependent fixed font. SYSTEM_FONT //The system font. By default, Windows uses the system font to draw menus, dialog-box controls, and other text. In Windows versions 3.0 and later, the system font is proportional width; earlier versions of Windows use a fixed-width system font. SYSTEM_FIXED_FONT //The fixed-width system font used in Windows prior to version 3.0. This object is available for compatibility with earlier versions of Windows. DEFAULT_PALETTE //Default color palette. This palette consists of the 20 static colors in the system palette.