已阅读5页,还剩55页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Windows绘图机制 哈尔滨工程大学 概述 图形设备接口GDI理解设备描述表理解WIN PAINT消息有关绘图GDI的API函数使用 句柄 在Windows编程中 会经常提到句柄这个名词 要理解句柄 应注意以下几点 句柄是一个4字节的整数 Windows利用它标志应用程序创建和使用的资源 包括应用程序实例 窗口 菜单 控件 内存 外设 文件以及与图形相关的画笔 刷子等 句柄是Windows内部表资源数据存储的内存索引值 Windows利用它可访问表中的信息 通常 在程序中 要访问某个资源时 需要提供该资源的句柄 因此句柄可理解为是内存的索引值 Windows平台下 不仅可以运行多个程序 还可以对同一个程序多次加载 每加载一次 Windows会创建一个运行的备份 即实例 同时系统为每个实例分配一个唯一的句柄 该句柄称为实例句柄 常用句柄类型及其说明如下表所示 常用句柄类型及其说明 图形设备接口GDI 图形设备接口 GraphicsDeviceInterface 简称为GDI 是Windows操作系统的子系统 负责在显示设备上显示图形 显而易见 GDI子系统是Windows非常重要的组成部分 不但Windows应用程序显示图形时需要使用GDI 就连Windows本身也使用GDI来显示窗口 菜单和鼠标光标等用户界面对象 GDI的主要目标之一是支持在各种输出设备 如显示器 打印机和绘图仪等 上进行与设备无关的图形输出 Windows的图形大部分是由GDI DLL动态链接库输出的函数来处理的 GDI动态链接库通过调用在不同设备驱动程序模块中的例程来控制输出设备 例如 显示设备驱动程序用于访问与视频显示器有关的硬件 通过GDI Windows可以确定驱动程序能够进行什么工作 并且由于应用程序只与GDI进行交互 所以GDI通过将应用程序与不同的输出设备隔离 使得应用程序可以在支持Windows的任意图形输出设备上工作 这就实现了图形输出的与设备无关性 设备描述表 设备描述表 DeviceContext 简称为DC 是GDI内部保存的数据结构 设备描述表与特定的显示设备 如显示器 打印机等 相关 对于显示器 设备描述表总是与显示器上特定的窗口相关 设备描述表中保存了显示图形所需使用的各种参数值 例如 显示的颜色 显示的坐标 显示的方式和背景的颜色等 Windows GDI函数实际上是在设备描述表里显示正文及绘图的 当程序显示文字或绘图时 首先必须获得一个设备描述表句柄 完成输出文字或绘图之后 还必须及时释放该句柄 否则会大大减少Windows的存储单元 释放之后的句柄就不会再有效了 一般说来 在处理某条消息时 获取和释放设备描述表句柄必须成对出现 而且不同设备描述表的获取与释放的方法也不同 而这只是所使用的函数不同而已 DC设备 这个 万能驱动 就是Windows给我们提供的一个DC 由DC去和设备驱动程序打交道 完成图形的绘制 至于图形的效果 就要由所使用的图形设备来决定了 其实 DC也是一种资源 它也不是什么 万能驱动 但是无论是显示 还是打印 我们都可以获取HC的句柄 然后在DC上操作 由DC映射到这些物理设备上就行了 设备描述表 在Windows系统中 设备描述表大致可分为四种类型 分别与视频显示器 打印机 内存和信息设备相关联 获取和释放设备描述表的函数也相应地分为四类 获取设备描述表句柄 当应用程序需要绘图的时候 必须先获得设备描述表句柄 在获得了该句柄以后 Windows会以默认的属性值填充内部的属性表结构 随后 应用程序需要调用相应的GDI函数 以指定的属性值代替需要改变的默认值 当绘图完毕后 应用程序必须释放设备描述表句柄 通常 应用程序使用两种方法来获取设备描述表句柄 在处理WM PAINT消息时 特别注意 设备描述表句柄的取得和释放必须成对使用 否则会引起严重问题 1 使用BeginPaint 和EndPaint 调用 hdc BeginPaint hwnd 获取设备描述表句柄 变量ps是型态为PAINTSTRUCT的结构 见MSDN 该结构的hdc字段是BeginPaint传回的设备内容句柄 PAINTSTRUCT结构又包含一个名为rcPaint的RECT 矩形 结构 rcPaint定义一个包围窗口显示区域无效范围的矩形 使用从BeginPaint获得的设备描述表句柄 只能在这个区域内绘图 BeginPaint调用使该区域有效 注意 若要响应WM PAINT消息 则无论如何都要使BeginPaint和EndPaint被执行 否则程序会出问题 CPU占用近100 因为 如果不调用BeginPaint函数 WM PAINT消息不会从消息队列中移出 需要注意的是 如果窗口函数不处理WM PAINT消息 则将WM PAINT消息传递给Windows的默认窗口函数 DefWindowProc 处理 DefWindowProc函数中处理WM PAINT消息的代码如下 WM PAINT消息处理 caseWM PAINT hdc BeginPaint hwnd 如果当前窗口用户区的某一部分变为无效 则Windows会将一个WM PAINT消息放到消息队列中 如果不调用BeginPaint和EndPaint函数 同时 也不调用ValidateRect函数 该无效区域不会变为有效 于是 Windows将会发送另一个WM PAINT消息 并且会一直发送下去 WM PAINT消息 其实系统会在很多的不同的机制下发送WM PAINT消息 比如调用UpdateWindow函数 第一次创建窗口 改变了窗口的大小 最大化 最小化等等 这些动作的产生都是有系统来控制的 应用程序只是接收消息 并处理消息 当Window检测到窗口被覆盖的地方需要恢复的时候 它会向用户程序发送一个WM PAINT消息 消息中包括了需要恢复的区域 然后由用户程序来决定如何恢复被覆盖的内容 窗口过程收到WM PAINT消息后 并不代表整个客户区都需要被刷新 有可能客户区被覆盖的区域只有一小块 这个区域叫做 无效区域 程序只需要更新这个区域 WM PAINT消息的响应和处理 首次创建窗口后 Windows将发送WM PAINT消息到窗口过程 实现窗口客户区的绘制 这是WM PAINT消息的第一个用处 另外 Windows是一个多任务环境 显示设备是为多个应用程序公用的 某个应用程序的窗口上面可能被对话框或窗口覆盖 当撤销这些对话框或窗口时 这个应用程序窗口中就有一个 空洞 这个 空洞 就是一块无效的客户区域 像这种情况还很多 比如改变窗口尺寸后 客户区的部分内容被遮盖 窗口最小化 客户区的滚动等都会造成无效的客户区域 为重新显示无效客户区域 Windows发送WM PAINT消息 要求根据调整后的窗口尺寸重新绘制窗口 这是WM PAINT消息的第二个用处 WM PAINT消息 WM PAINT消息在Windows消息队列中的优先级很低 这就使其他许多消息能够先于WM PAINT消息被送交给窗口过程处理 只有在没有其他消息的情况下 才从队列中取出WM PAINT消息进行处理 这样做是为了让应用程序首先完成影响窗口显示结果的其他操作 不致因为频繁地执行输出操作而引起显示器的闪烁 Windows并非WM PAINT消息的惟一来源 使用InvalidateRect或InvalidateRgn函数也可以产生绘图窗口的WM PAINT消息 这两个函数把客户区部分或全部标记成无效区域而要求重新显示 获取设备描述表句柄 方法二 GetDC和ReleaseDC虽然通常在处理WM PAINT消息时更新窗口的用户区 但有时也需要在处理非WM PAINT消息时绘制用户区的部分或者全部 在处理非WM PAINT消息时可以通过调用GetDC函数来获取设备描述表句柄 GetDC函数的定义如下 HDCGetDC HWNDhWnd 所属窗口的句柄 该函数仅需一个参数 即窗口函数所属窗口的句柄 该函数返回设备描述表句柄 当使用完毕后 应当调用ReleaseDC函数释放该设备描述表句柄 ReleaseDC函数定义如下 intReleaseDC HWNDWnd 所属窗口的句柄HDChDC 需要释放的设备描述表句柄同样 GetDC与ReleaseDC函数必须成对使用 并且 不应当在处理一个消息时调用GetDC函数而在处理另一个消息时调用ReleaseDC函数 GetDC函数与BeginPaint的区别 GetDC函数与BeginPaint有两点不同 通过BeginPaint函数所获得的操作区域是用户区中的无效矩形区域 后继的绘图操作只能在该无效矩形区域内进行 而该区域以外的操作将被忽略 GetDC所获得的操作区域则是整个用户区 其后继操作可以在用户区的任意部分进行 而不只是在无效矩形区域内 BeginPaint函数会自动将无效矩形区域变为有效 而GetDC函数则不会将任何无效矩形区域变为有效 如果需要使整个用户区变为有效 则可以调用ValidateRect函数 并将其第二个参数设为NULL BeginPaint函数处理 BeginPaint函数只做了两件事情 使窗口无效区域变得有效 从而使Windows不再发送WM PAINT消息 直到窗口大小改变等 使窗口再次变得无效 如果窗口一直无效 则Windows会不停地发送WM PAINT消息 填充PAINTSTRUCT结构 填充这个结构的目的 是让程序员可以根据ps变量中的标志值进行某些操作 窗口无效 当拖动窗口的一个顶点改变了窗口的大小 窗口由最小化恢复到最大化 窗口的一部分被其它窗口遮住又重新显示 调用MoveWindow函数改变了窗口大小 窗口移动到桌面之外的 部分被拖回重新显示时 窗口就会变得无效 无效区域是整个客户区 因此默认窗口处理函数DefWindowProc会擦除整个客户区 注 拖动窗口标题栏移动窗口 只要窗口没有移动到屏幕之外 那么这两个消息都不产生 背景擦除 当窗口无效时 Windows会给窗口发出WM ERASEBKGND消息和WM PAINT消息 而且WM ERASEBKGND先发出一次或者几次 紧接着是WM PAINT 窗口背景的擦除 窗口的背景色是由默认的消息处理函数DefWindowProc擦除的 即这个函数使用注册窗口类时使用的背景刷擦除窗口背景 什么时候绘制 在窗口函数收到WM ERASEBKGND消息 DefWindowProc函数以WM ERASEBKGND为参数 才会绘制窗口背景 注 当WM ERASEBKGND消息产生后 窗口一定有一部分变得无效 背景擦除 例外 InvalidateRect函数的调用会使窗口变得无效 并产生WM ERASEBKGND消息和WM PAINT消息 而WM ERASEBKGND是否产生取决于参数bErasevoidInvalidateRect LPCRECTlpRect BOOLbErase TRUE 当参数bErase为true时 WM ERASEBKGND消息产生 当bErase为false时WM ERASEBKGND消息不产生 则InvalidateRect函数的最后一个参数会指定是否擦除背景 如果为FALSE则windows不会擦除背景 当WM PAINT不是由InvalidateRect产生时 即由最大化 最小化等产生时 或者移动产生 移动有时只会产生WM ERASEBKGND消息 系统先发送WM ERASEBKGND消息 再发送WM PAINT消息 如果处理WM ERASEBKGND消息时返回FALSE BeginPaint标记pt fErase为TRUE 如果处理WM ERASEBKGND时返回TRUE BeginPaint标记pt fErase为FALSE 如果pt fErase标记为TRUE 指示应用程序应该处理背景 但是应用程序不一定需要处理 pt fErase只是作为一个标记 背景擦除 在这个消息中如果调用了hdc BeginPaint hWnd WM ERASEBKGND返回TRUE和返回FALSE是一个规范 一般情况下没有什么区别 但是如果什么时候用到了 会根据函数返回值判断后续处理 因此最好按照要求返回数据 WM PAINT的处理经验 在处理WM PAINT消息时 为了在更新的矩形外绘图 可以在调用BeginPaint之前使用如下函数 InvalidateRect hwnd NULL TRUE 它使整个显示区域变为无效 并擦除背景 但是 如果最后一个参数等于FALSE 则不擦除背景 原有的东西将保留在原处 通常这是Windows程序在无论何时收到WM PAINT消息而不考虑rcPaint结构的情况下简单地重画整个客户区最方便的方法 例如 如果在客户区的显示输出中包括了一个圆 但是只有圆的一部分落到了无效矩形中 它就仅绘制圆在无效矩形中的部分 这对于画整个圆来说是无意义的 注意 使用从BeginPaint返回的设备描述表句柄时 Windows不会绘制rcPaint矩形外的任何部分 在BeginPaint调用之前使用上面那个函数 可使rcPaint结构中的无效矩形为整个客户区 就不愁绘制圆了 在处理WM PAINT消息时 必须成对地调用BeginPaint和EndPaint 如果窗口过程不处理WM PAINT消息 则它必须将WM PAINT消息传递给Windows中DefWindowProc 默认窗口过程 WM PAINT的处理经验 DefWindowProc以下列代码处理WM PAINT消息 caseWM PAINT BeginPaint hwnd WRONG Windows将一个WM PAINT消息放到消息队列中 是因为客户区的一部分无效 如果不调用BeginPaint和EndPaint 或者ValidateRect 则Windows不会使该区域变为有效 若一直保持无效 Windows将会再发送另一个WM PAINT消息 且一直发送下去 获取设备描述表句柄 方法三 GetWindowDC GetDC传回用于写入窗口显示区域 客户区 的设备内容句柄 而GetWindowDC传回写入整个窗口的设备内容句柄 而不仅限于窗口的客户区 例如 您的程序可以使用从GetWindowDC传回的设备内容句柄在窗口的标题列上写入文字 然而 程序同样也应该处理WM NCPAINT 非显示区域绘制 消息 hdc GetWindowDC hwnd GetWindowRect hwnd 获取设备描述表句柄 方法四 取得设备描述表句柄的更常用的函数是CreateDC hdc CreateDC pszDriver pszDevice pszOutput pData DeleteDC hdc 注意上面的释放句柄函数是DeleteDC 可以通过下面的调用来取得整个屏幕的设备描述表句柄 可以作出汉王手写板的效果 hdc CreateDC TEXT DISPLAY NULL NULL NULL 获取设备描述表句柄 使用位图时 取得一个 内存设备描述表 hdcMem CreateCompatibleDC hdc BitBlt DeleteDC hdcMem 设备描述表属性 Windows使用设备描述表来保存控制GDI函数如何在显示设备上工作的 当前属性 例如 在使用TextOut函数时 应用程序只需指定设备表述表句柄 文本显示的起始位置坐标 需要显示的文本及其长度 而不需指定文本的字体 颜色 背景色和字符间距等 Windows可以从设备描述表中获取这些信息 默认值 当应用程序使用GetDC或BeginPaint函数获得一个设备描述表句柄时 Windows会自动用默认值设置其所有的属性 应用程序可以通过相应的GDI函数调用获取 修改所有的属性值 通常 在调用GetDC或BeginPaint函数以获取设备描述表句柄时 Windows会自动用默认值填充设备描述表的各个字段 应用程序需要随后更改其中那些希望更改的字段 但是 在应用程序调用ReleaseDC或EndPaint函数以释放设备描述表句柄时 所作的所有更改都会丢失 这就意味着 如果应用程序需要使用非默认的设备描述表属性 则必须在每次获取设备描述表句柄时显示地初始化设备描述表 通常的操作如下 设备描述表属性 HDChdc HWNDhwnd PAINTSTRUCTps caseWM PAINT hdc BeginPaint hwnd 设备描述表属性 属性背景模 位图 画刷 画刷 起始位置 剪裁域 颜色调色板 绘图方式 字体 字符间距 映射方式 画笔 多边形填充方式 缩放模式 文本颜色 视图范围 视图原点 窗口范围 窗口原点等景色WHITEGetBkColorSetBkColor背景模式OPAQUEGetBkModeSetBkMode位图NONECreateBitMapCreateBitMapIndirectCreateCompatibleBitmapSelectObject 设备坐标系和逻辑坐标系 为了在输出设备上输出文本和绘制图形 必须引入一定的坐标系 以确定显示的位置和范围 Windows的各种设备所使用的坐标系称为设备坐标 通常为笛卡儿坐标系 在这些设备坐标系中 单位通常为像素 称为设备单位 X方向上坐标自左向右增大 Y方向上自上向下增大 应用程序可以获取3种不同的显示设备描述表句柄 每种句柄所标识的显示设备对象代表屏幕上的不同区域 应用程序可以将这3种句柄所标识的对象看作3种不同的抽象显示设备 但对于不同的抽象设备 其坐标原点不一样 这样 当使用相同的起始坐标而使用不同的设备描述表句柄调用TextOut等GDI函数进行输出文本 绘制图形等操作时 信息显示的位置就不一样 设备坐标系的种类 第一种抽象显示设备是用户区对象 就是前面一直使用的窗口用户区 其坐标原点在用户区的左上角 定位该区域的设备坐标系称为用户区坐标系 可以通过调用GetDC或BeginPaint函数得到标识窗口用户区的设备描述表句柄 当使用标识该区域的句柄作为GDI函数的参数时 GDI函数所使用的坐标值是相对于用户区坐标系的 第二种抽象显示设备是窗口对象 不仅包括用户区 还包括标题栏 菜单 滚动条和窗口框架等 定位该区域的坐标系称为窗口坐标系 其原点在整个窗口的左上角 可以使用GetWindowDC函数获得该设备对象的句柄 程序就可以通过该句柄 使用窗口坐标系在整个窗口的任意位置绘图 第三种抽象设备是整个屏幕对象 hdc CreateDC Display NULL NULL NULL 定位该区域的设备坐标系称为屏幕坐标系 其坐标原点在整个屏幕的左上角 通过使用该句柄 应用程序可以在整个屏幕的任意位置显示信息 设备坐标系演示示例 caseWM PAINT 获取用户区对象的设备描述表句柄hdc GetDC hwnd TextOut hdc 0 0 TextInClientRect strlen TextInClientRect 使整个用户区有效 从而刷新整个用户区ValidateRect hwnd NULL 释放用户区对象的设备描述表句柄ReleaseDC hwnd hdc 获取窗口对象的设备描述表句柄hdc GetWindowDC hwnd TextOut hdc 0 0 TextInWindow strlen TextInWindow 释放窗口对象的设备描述表句柄ReleaseDC hwnd hdc 创建屏幕对象的设备描述表句柄hdc CreateDC Display NULL NULL NULL TextOut hdc 0 0 TextInScreen strlen TextInScreen 删除屏幕对象的设备描述表句柄DeleteDC hdc return0 逻辑坐标系 这3种坐标系方便地满足了应用程序在不同的区域绘制图形的需要 例如 使用了用户区坐标系 即使窗口在屏幕上被移动到了其他的地方 用户区中显示的信息也会相对于用户区坐标系的坐标不变 使用坐标系 解决了显示内容的定位问题 但是 以像素为单位所建立的坐标系不符合用户和程序员的习惯 而且在不同分辨率的输出设备上 同样一个像素的大小也不相同 这样 应用程序在不同的机器上会得到不同的结果 为了解决这个问题 Windows引入了逻辑坐标系 应用程序使用逻辑坐标系中的坐标值 而由Windows根据不同的映射模式将逻辑坐标系中的坐标值转换成设备坐标系中的坐标值 对于显示设备而言 具体映射到3种坐标系中的哪一种上取决于GDI函数所使用的抽象显示对象设备描述表句柄 映射模式同时也决定着逻辑坐标值的单位 简称逻辑单位 和逻辑坐标轴的正方向 例如 在TextOut函数和DrawText函数中使用的是逻辑单位 用户区坐标和屏幕坐标 设备单位 之间的转换 Winows提供两个函数用于用户区坐标和屏幕坐标 使用设备单位 之间的转换 分别为ClientToScreen和ScreenToClient 前者用于将用户区坐标转换为屏幕坐标 后者用于将屏幕坐标转换为用户区坐标 两者定义分别如下 BOOLClientToScreen HWNDhWnd 用户区所属的窗口句柄LPPOINTlpPoint 指向一个POINT结构类型的变量 其中存储了一个点的用户区坐标 在执行完ClientToScreen函数后 将被转换所得的屏幕坐标取代 BOOLScreenToClient HWNDhWnd 用户区所属的窗口句柄LPPOINTlpPoint 指向一个POINT结构类型的变量 其中存储了一个点的屏幕坐标 在执行完ScreenToClient函数后 将被转换所得的用户区坐标取代 Windows还提供函数GetWindowRect 用以获取屏幕坐标系下整个窗口的位置和大小 其定义如下 BOOLGetWindowRect HWNDhWnd 窗口句柄LPRECTlpRect 窗口坐标 其中 参数hWnd用于指定窗口 参数lpRect所指向的RECT结构类型的变量用于存放指定窗口的左 右边的Y坐标和上 下边的X坐标 从而确定了所指定窗口的位置和大小 屏幕坐标系下整个窗口的位置和大小 关于色彩 现在的彩色显示器一般都支持 真彩色 即以24位表示一个像素点 通常用32位长整数存储 其中红色 绿色 蓝色各占8位 32位中高8位全为0 红 绿 蓝三色即 三原色 这三种颜色按照不同的比例值进行混合就可以得到各种不同的颜色 所使用的位数越多 能表现的色彩就越多 现在的Windows系统中 大多数的GDI函数都使用COLORREF值来表示一种色彩 COLORREF是一个32位的无符号长整数 按照红色 绿色和蓝色的不同组合代表了不同的颜色 通常称为 RGB色彩 关于色彩 Windows提供了使用该方法表示颜色的宏RGB Red Green Blue 例如 RGB 255 0 0 表示红色 RGB 0 255 0 表示绿色 RGB 0 0 255 表示蓝色 RGB 0 0 0 表示白色 RGB 255 255 255 表示黑色 Windows还提供了宏GetRValue COLORREF GetGValue COLORREF 和GetBValue COLORREF 分别用于提取颜色COLORREF中红色 绿色和蓝色的值 GDI的画图函数 图形设备接口 GDI 模块中包含了大量用于绘制点 线 圆和矩形等图形元素的函数 这一节介绍如何画点和线条 通常使用画笔来绘制线条 如椭圆 矩形等封闭图形的轮廓线 而绘制像素点是最基本的操作 绘制像素点GDI函数SetPixel用来在指定位置绘制一个特定颜色的像素点 函数GetPixel返回指定坐标处像素点的颜色 函数SetPixel定义如下 COLORREFSetPixel HDChdc 设备描述表句柄intX 像素点的横坐标值intY 像素点的纵坐标值COLORREFcrColor 像素点的颜色 其中 参数X和Y是所要绘制的像素点的逻辑坐标值 参数crColor用于指定所画像素点的颜色 可以是RGB值 GDI的画图函数 绘制线条画一条直线需要用到两个函数 一个用于指定线段的起始点位置 另一个用于直到线段 BOOLMoveToEx HDChdc 设备描述表句柄intX 新当前位置的横坐标intY 新当前位置的纵坐标LPPOINTlpPoint 原先的当前位置坐标 其中 参数X和Y用于指定新的当前位置的坐标 该当前位置也就是所绘线段的起点位置 同样 MoveToEx同样为其他几个GDI函数指定起始位置 设备描述表中默认的当前位置为原点 0 0 在调用GDI函数进行绘图操作之前没有设置新的当前位置 则绘图操作将从用户区的左上角开始 GDI的画图函数 应用程序可以通过调用函数GetCurrentPositionEx来获得当前位置 其定义如下 BOOLGetCurrentPositionEx HDChdc 设备描述表句柄LPPOINTlpPoint 当前位置 其中 参数lpPoint指向一个POINT结构类型的变量 用于返回当前位置坐标 函数LineTo执行实际的绘图操作 其定义如下 BOOLLineTo HDChdc 设备描述表句柄intnXEnd 终点横坐标intnYEnd 终点纵坐标 该函数将绘制一条线段 起始点由函数MoveToEx指定 默认为原点 终点坐标由参数nXEnd和nYEnd指定 需要注意的是 如果函数LineTo调用成功 则该函数会将当前位置更改为由参数nXEnd和nYEnd所指定的线段终点 GDI的画图函数 绘图操作当然离不开画笔和刷子 前者主要用来绘制线条 后者主要用来填充封闭区域 当使用画笔绘制点划线或者用影线刷子填充封闭区域时 点和短划线之间以及刷子的影线之间会产生空隙 这就涉及到空隙的填充问题 当应用程序需要绘制线条或者图形轮廓的时候 就需要用到画笔 Windows使用设备描述表中当前选定的画笔来画线 画笔决定了线的颜色 宽度和线型 例如实线 点划线和虚线等 Windows定义了3种备用的画笔 分别为BLACK PEN 黑笔 WHITE PEN 白笔 和NULL PEN 空笔 NULL PEN什么都不画 默认设备描述表中的画笔为BLACK PEN 画笔由类型为HPEN的画笔句柄来标识 画笔句柄变量的通常定义如下 HPENhPen 通过调用函数GetStockObject可以得到现有画笔的句柄 GDI的画图函数 例如 以下语句可以得到白色画笔的句柄 HPENhPen hPen GetStockObject WHITE PEN 如果需要使用白色画笔 还必须将其选入设备描述表 可以使用SelectObject函数 SelectObject hdc hPen 当前的画笔是白色画笔 在该语句执行完毕后 直到应用程序将另外的画笔选入设备描述表或者释放设备描述表句柄 否则将始终使用白色画笔绘制线条 也可以不显示地定义hPen变量 如下 SelectObject hdc GetStockObject WHITE PEN 通常 在使用完新选入设备描述表的画笔后 还原当前画笔为原先的画笔是个好习惯 常用的方式如下 HPENhPen hPen SelectObject hdc GetStockObject WHITE PEN 使用WHITE PEN画笔SelectObject hdc hPen 还原原先的画笔其中 hPen为原先的画笔 GDI的画图函数 使用由系统提供的备用画笔十分方便 但是只有实心黑笔和实心白笔两种效果 如果想得到更多颜色 粗细和线型的线条 则需要自己创建画笔 可以使用函数CreatePen或者函数CreatePenIndirect来实现 函数CreatePen定义如下 HPENCreatePen intfnPenStyle 笔型intnWidth 笔宽COLORREFcrColor 笔色 其中 参数fnPenStyle用于确定笔的类型 Windows中定义有7种笔型 均以PS PenStyle 为前缀PS SOLID PS DOT GDI的画图函数 需要注意的是 函数CreatePen所创建的画笔是一种逻辑画笔 它并未与设备描述表相关联 所以这两个函数不需要设备描述表句柄作为参数 直到随后通过调用SelectObject将所创建的画笔选入设备描述表 画笔才与设备描述表相关联 因此 对不同的设备 如显示器和打印机 可以使用相同的逻辑画笔 逻辑画笔是一种GDI图形对象 通过SelectObject函数选入设备描述表的 在使用完所创建的画笔后 需要调用DeleteObject函数予以删除 该函数定义如下 BOOLDeleteObject HGDIOBJhObject GDI图形对象句柄 如果需要删除一个逻辑画笔对象 语句如下 DeleteObject hPen 需要注意的是 应用程序不能删除系统定义的备用画笔 并且 当前被选入设备描述表的画笔不能被删除 创建画笔 结构LOGPEN存储了逻辑画笔的三个参数 画笔样式 宽度 颜色typedefstructtagLOGPEN UINTlopnStyle 样式POINTlopnWidth 宽度COLORREFlopnColor 颜色 LOGPEN PLOGPEN LOGPENlogpen hPen CreatePenIndirect 创建画笔 LOGPENlogpen HPENp HGDIOBJhOld HDChdc GetDC m hWnd logpen lopnWidth x 1 logpen lopnColor RGB 255 0 0 logpen lopnStyle PS SOLID p CreatePenIndirect 输出模式 输出的字符串时 发现存在背景色 这样的输出是破坏背景的 那需要使用什么方法来保持背景不变 而又能输出红色的字符串呢 比如按钮的文字颜色是黑色的 而背景是灰色的 这就需要使用SetBkMode函数来设置DrawText函数的输出方式 显示设备共有两种输出方式 OPAQUE和TRANSPARENT OPAQUE的方式是用当前背景的画刷的颜色输出显示文字的背景 而TRANSPARENT是使用透明的输出 也就是文字的背景是不改变的 您可以通过如下呼叫来改变Windows用来填入空隙的背景色SetBkColor hdc crColor 通过将背景模式转换为TRANSPARENT 可以阻止Windows填入空隙 显示模式 SetBkMode hdc TRANSPARENT 此后 Windows将忽略背景色 并且不填入空隙 可以通过呼叫GetBkMode来取得目前背景模式 TRANSPARENT或者OPAQUE 例程Background 1 绘图方式 可以通过以下呼叫在设备内容中设定新的绘图模式 SetROP2 hdc iDrawMode iDrawMode参数是表中 绘图模式 一栏中给出的值之一 您可以用函数 iDrawMode GetROP2 hdc 如果您想画一个没有边界框的图形 可以将NULL PEN选进设备内容 SelectObject hdc GetStockObject NULL PEN 如果您想画出图形的边界框 但不填入内部 则将NULL BRUSH选进设备内容 SelectObject hdc GetStockobject NULL BRUSH GDI将像素点输出到逻辑平面上时 它不只是简单地输出像素点颜色 相反 它能过一系列的布尔运算将输出像素点的颜色和目标位置上像素点的颜色合成一起 它所使用的逻辑关系由设备描述表当前的绘图模式确定 绘图方式 函数的主要的作用是根据nDrawMode设置的方式重新设定绘图的方式 下面就不同的nDrawMode值具体解释绘图模式是如何改变的 首先就nDrawMode的取值有以下的情况 R2 BLACKPixelisalwaysblack 所有绘制出来的像素为黑色R2 WHITEPixelisalwayswhite 所有绘制出来的像素为白色R2 NOPPixelremainsunchanged 任何绘制将不改变当前的状态R2 NOTPixelistheinverseofthescreencolor 当前绘制的像素值设为屏幕像素值的反 这样可以覆盖掉上次的绘图 自动擦除上次绘制的图形 R2 COPYPENPixelisthepencolor 使用当前的画笔的颜色R2 NOTCOPYPENPixelistheinverseofthepencolor 当前画笔的反色 前景色的混合模式 用于设定当前前景色的混合模式 R2 NOT就是取反的意思 即前景色为背景色的反色 经常用R2 NOT来画橡皮线 因为两次取反可以还原背景色 经常用于擦除工作 见例程Font SetNOPintdrawMode dc SetROP2 R2 NOTXORPEN dc Rectangle startPoint x startPoint y m endPoint x m endPoint y dc Rectangle startPoint x startPoint y point x point y m endPoint x point x m endPoint y point y 字体设置 hFont CreateFont height 字体的逻辑高度width 逻辑平均字符宽度angle 与水平线的角度0 基线方位角度FW REGULAR 字形 常规FALSE 字形 斜体FALSE 字形 下划线FALSE 字形 粗体GB2312 CHARSET 字符集OUT DEFAULT PRECIS 输出精度CLIP DEFAULT PRECIS 剪截精度PROOF QUALITY 输出品质FIXED PITCH FF MODERN 倾斜度face 字体 字体设置 hFont SetMyFont hDC LPCTSTR 宋体 0 32 450 创建字体SelectObject hDC hFont 选择字体SetTextColor hDC RGB 255 0 0 TextOut hDC 16 0 str3 int strlen str3 SelectObject hDC hFontOld 选择旧字体DeleteObject hFont 删除新字体 利用GDI显示文字 TCHARstr 30 longlen len wsprintf str 姓名 s 年龄 d 张三 20 TextOut hdc 100 100 str len GDI显示多行文字 由于在一次Windows对话期间系统字体的尺寸不会发生改变 因此在程序运行过程中我们只需要调用一次GetTextMetrics 最好是在窗口过程中处理WM CREATE消息时进行此调用 WM CREATE消息是窗口过程接收的第一个消息 当在WinMain 中调用CreateWindow 时 Window向窗口过程发送一个WM CREATE消息 想在客户区显示几行文本 这需要先获取字符宽度和高度 我们可以在窗口过程内定义两个变量来保存平均字符宽度 cxChar 和字符高度 cyChar staticintcxChar cyChar 变量名的前缀c代表 count 在这里指像素数 与x和y结合 分别指宽和高 这些变量定义为static 因为它们在窗口过程中处理其它
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- GB/T 46627-2025管法兰用垫片高温密封性能试验方法
- 高压釜温控工持续改进强化考核试卷含答案
- 棉花收获机操作工岗位职业健康技术规程
- 脑卒中常见症状及护理手段培训
- 中职宠物营养原理课件
- 无线电监测设备测试员安全检查竞赛考核试卷含答案
- 脊柱侧弯术后出院宣教
- 2025年瓮安县教师招聘笔试参考试题及答案解析
- 2025年宁化县中小学教师招聘笔试备考试题及答案解析
- 起搏器的健康宣教
- 2025中国高净值人群金融投资需求与趋势白皮书
- 《涂刷类墙面》课件
- 幼儿园冬季流感预防知识教育
- 医院药房停电应急预案
- 石油建设项目可行性研究投资估算编制规定
- 辽宁建设工程施工新监理表格【实用文档】doc
- 相声《五官争功》台词
- GA 884-2018公安单警装备催泪喷射器
- House-Brackmann面神经功能分级标准
- 中新天津生态城居民信息登记表
- 2021年贵州省现代种业集团有限公司招聘笔试试题及答案解析
评论
0/150
提交评论