windows sdk编程系列文章03 ---- 绘制文本

上传人:hjk****65 文档编号:178022876 上传时间:2022-12-27 格式:DOC 页数:15 大小:58.50KB
收藏 版权申诉 举报 下载
windows sdk编程系列文章03 ---- 绘制文本_第1页
第1页 / 共15页
windows sdk编程系列文章03 ---- 绘制文本_第2页
第2页 / 共15页
windows sdk编程系列文章03 ---- 绘制文本_第3页
第3页 / 共15页
资源描述:

《windows sdk编程系列文章03 ---- 绘制文本》由会员分享,可在线阅读,更多相关《windows sdk编程系列文章03 ---- 绘制文本(15页珍藏版)》请在装配图网上搜索。

1、windows sdk编程系列文章 - 绘制文本2008-04-08 20:20本课中,我们将学习如何在窗口的客户区“绘制”字符串。我们还将学习关于“设备环境”的概念。理论:Windows 中的文本是一个GUI(图形用户界面)对象。每一个字符实际上是由许多的像素点组成,这些点在有笔画的地方显示出来,这样就会出现字符。这也是为什么我说“绘制”字符,而不是写字符。通常您都是在您应用程序的客户区“绘制”字符串(尽管您也可以在客户区外“绘制”)。Windows 下的“绘制”字符串方法和 Dos 下的截然不同,在 Dos 下,您可以把屏幕想象成 85 x 25 的一个平面,而 Windows 下由于屏幕

2、上同时有几个应用程序的画面,所以您必须严格遵从规范。Windows 通过把每一个应用程序限制在他的客户区来做到这一点。当然客户区的大小是可变的,您随时可以调整。在您在客户区“绘制”字符串前,您必须从 Windows 那里得到您客户区的大小,确实您无法像在 DOS 下那样随心所欲地在屏幕上任何地方“绘制”,绘制前您必须得到 Windows 的允许,然后 Windows 会告诉您客户区的大小,字体,颜色和其它 GUI 对象的属性。您可以用这些来在客户区“绘制”。什么是“设备环境”(DC)呢? 它其实是由 Windows 内部维护的一个数据结构。一个“设备环境”和一个特定的设备相连。像打印机和显示器

3、。对于显示器来说,“设备环境”和一个个特定的窗口相连。“设备环境”中的有些属性和绘图有关,像:颜色,字体等。您可以随时改动那些缺省值,之所以保存缺省值是为了方便。您可以把“设备环境”想象成是Windows 为您准备的一个绘图环境,而您可以随时根据需要改变某些缺省属性。当应用程序需要绘制时,您必须得到一个“设备环境”的句柄。通常有几种方法。 在 WM_PAINT 消息中使用 BeginPaint 在其他消息中使用 GetDC CreateDC 建立你自己的 DC 您必须牢记的是,在处理单个消息后你必须释放“设备环境”句柄。不要在一个消息处理中获得 “设备环境”句柄,而在另一个消息处理中在释放它。

4、我们在Windows 发送 WM_PAINT 消息时处理绘制客户区,Windows 不会保存客户区的内容,它用的是方法是“重绘”机制(譬如当客户区刚被另一个应用程序的客户区覆盖),Windows 会把 WM_PAINT 消息放入该应用程序的消息队列。重绘窗口的客户区是各个窗口自己的责任,您要做的是在窗口过程处理 WM_PAINT 的部分知道绘制什么和何如绘制。您必须了解的另一个概念是“无效区域”。Windows 把一个最小的需要重绘的正方形区域叫做“无效区域”。当 Windows 发现了一个”无效区域“后,它就会向该应用程序发送一个 WM_PAINT 消息,在 WM_PAINT 的处理过程中,

5、窗口首先得到一个有关绘图的结构体,里面包括无效区的坐标位置等。您可以通过调用BeginPaint 让“无效区”有效,如果您不处理 WM_PAINT 消息,至少要调用缺省的窗口处理函数 DefWindowProc ,或者调用 ValidateRect 让“无效区”有效。否则您的应用程序将会收到无穷无尽的 WM_PAINT 消息。下面是响应该消息的步骤:1. 取得“设备环境”句柄 2. 绘制客户区 3. 释放“设备环境”句柄 注意,您无须显式地让“无效区”有效,这个动作由 BeginPaint 自动完成。您可以在 BeginPaint 和 Endpaint 之间,调用所有的绘制函数。几乎所有的GD

6、I 函数都需要“设备环境”的句柄作为参数。例子: (见光盘FirstWindow2)下面我们将写一个应用程序,它会在客户区的中心显示一行 Win32 program, Simple and powerful !#include Windows.h#include tchar.hHWND hWinMain;TCHAR szClassName = _T(MyClass);TCHAR szCaptionMain = _T(My First Window!);TCHAR szText = _T(Win32 program, Simple and powerful !);WNDCLASSEX stdWn

7、dClass;LRESULT CALLBACK ProcWinMain( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ) PAINTSTRUCT stPs; RECT stRect; HDC hDC; switch(Msg) case WM_PAINT: hDC = BeginPaint(hWnd,&stPs); GetClientRect(hWnd,&stRect); DrawText(hDC, szText,-1,&stRect,DT_SINGLELINE|DT_CENTER|DT_VCENTER); EndPaint(hWnd,&s

8、tPs); break; case WM_CLOSE: DestroyWindow(hWinMain); PostQuitMessage(NULL); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam ); return 0;int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) MSG stMsg; WNDCLASSEX stdWndClass; RtlZeroMemory(&st

9、dWndClass, sizeof(stdWndClass); stdWndClass.hCursor = LoadCursor(0,IDC_ARROW); stdWndClass.cbSize = sizeof(stdWndClass); stdWndClass.style = CS_HREDRAW|CS_VREDRAW; stdWndClass.lpfnWndProc = ProcWinMain; stdWndClass.hbrBackground = (HBRUSH)COLOR_WINDOW; stdWndClass.lpszClassName = szClassName; stdWnd

10、Class.hInstance = hInstance; RegisterClassEx(&stdWndClass); hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,szClassName,szCaptionMain, WS_OVERLAPPEDWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL); if(!hWinMain) return 0; ShowWindow(hWinMain,SW_SHOWNORMAL); UpdateWindow(hWinMain); while(GetMessage(&stMsg

11、,NULL,0,0) TranslateMessage(&stMsg); DispatchMessage(&stMsg); return stMsg.wParam;分析: 这里的大多数代码和第三课中的一样。我只解释其中一些不相同的地方。 PAINTSTRUCT stPs; RECT stRect; HDC hDC;这些局部变量由处理 WM_PAINT 消息中的 GDI 函数调用。hdc 用来存放调用 BeginPaint 返回的“设备环境”句柄。ps 是一个 PAINTSTRUCT 数据类型的变量。通常您不会用到其中的许多值,它由 Windows 传递给 BeginPaint,在结束绘制后再原

12、封不动的传递给 EndPaint。rect 是一个 RECT 结构体类型参数,它的定义如下:typedef struct tagRECT LONG left; LONG top; LONG right; LONG bottom;RECT;left 和 top 是正方形左上角的坐标。right 和 bottom 是正方形右下角的坐标。客户区的左上角的坐标是 x=0,y=0,这样对于 x=0,y=10 的坐标点就在它的下面。 hDC = BeginPaint(hWnd,&stPs); GetClientRect(hWnd,&stRect); DrawText(hDC, szText,-1,&stR

13、ect,DT_SINGLELINE|DT_CENTER|DT_VCENTER); EndPaint(hWnd,&stPs);在处理 WM_PAINT 消息时,您调用BeginPaint函数,传给它一个窗口句柄和未初始化的 PAINTSTRUCT 型参数。调用成功后在 hDC中得到返回“设备环境”的句柄。下一次,调用 GetClientRect 以得到客户区的大小,大小放在 rect 中,然后把它传给 DrawText。DrawText 的语法如下:WINUSERAPI int WINAPI DrawTextA( HDC hDC, LPCSTR lpString, int nCount, LPR

14、ECT lpRect, UINT uFormat);DrawText是一个高层的调用函数。它能自动处理像换行、把文本放到客户区中间等这些杂事。所以您只管集中精力“绘制”字符串就可以了。我们会在下一课中讲解低一层的函数 TextOut,该函数在一个正方形区域中格式化一个文本串。它用当前选择的字体、颜色和背景色。它处理换行以适应正方形区域。它会返回以设备逻辑单位度量的文本的高度,我们这里的度量单位是像素点。让我们来看一看该函数的参数: hdc: “设备环境”的句柄。 lpString:要显示的文本串,该文本串要么以NULL结尾,要么在nCount中指出它的长短。 nCount:要输出的文本的长度。

15、若以NULL结尾,该参数必须是-1。 lpRect: 指向要输出文本串的正方形区域的指针,该方形必须是一个裁剪区,也就是说超过该区域的字符将不能显示。 uFormat:指定如何显示。我们可以用 or 把以下标志或到一块: o DT_SINGLELINE:是否单行显示。 o DT_CENTER:是否水平居中。 o DT_VCENTER :是否垂直居中。 结束绘制后,必须调用 EndPaint 释放“设备环境”的句柄。 好了,现在我们把“绘制”文本串的要点总结如下:1. 必须在开始和结束处分别调用 BeginPaint 和 EndPaint; 2. 在 BeginPaint 和 EndPaint

16、之间调用所有的绘制函数; 3. 如果在其它的消息处理中重新绘制客户区,您可以有两种选择:4. (1)用GetDC和ReleaseDC代替BeginPaint和EndPaint;5. (2)调用InvalidateRect或UpdateWindow让客户区无效,这将迫使WINDOWS把WM_PAINT放入应用程序消息队列,从而使得客户区重绘。 技术成就梦想windows sdk编程系列文章 - 学习更多关于“绘制”文本串的知识2008-04-08 20:21我们将做更多的实践去了解有关文本的诸多属性如字体和颜色等。理论:Windows 的颜色系统是用RGB值来表示的,R 代表红色,G 代表绿色,

17、B 代表兰色。如果您想指定一种颜色就必须给该颜色赋相关的 RGB 值,RGB 的取值范围都是从 0 到 255,譬如您想要得到纯红色,就必须对RGB赋值(255,0,0),纯白色是 (255,255,255)。从我们下面的例子中您可以看出来要想运用好这套基于数字的颜色系统并不容易,这要求您必须对混色和颜色匹配有良好的感觉。您可以用函数 SetTextColor 和 SetBkColor 来“绘制”背景色和字符颜色,但是必须传递一个“设备环境”的句柄和 RGB 值作为参数。COLORREF类型用来描绘一个RGB颜色。其定义如下:typedef DWORD COLORREF;typedef DWO

18、RD *LPCOLORREF;COLORREF类型变量值描绘一个颜色时对应于下面16进制的格式:0x00bbggrr 可以用这样一个结构体来描述。RGB_value struct byte unused ; byte blue ; byte green ; byte red;其中第一字节为 0 而且始终为 0,其它三个字节分别表示兰色、绿色和红色,刚好和 RGB 的次序相反。这个结构体用起来挺别扭。对于COLORREF,我们通常使用宏RGB对其进行赋值。宏的定义如下:COLORREF RGB( BYTE byRed, / red component of color BYTE byGreen,

19、 / green component of color BYTE byBlue / blue component of color );您可以调用 CreateFont 和 CreateFontIndirect 来创建自己的字体,这两个函数的差别是前者要求 您传递一系列的参数,而后着只要传递一个指向 LOGFONT 结构的指针。这样就使得后者使用起来更方便,尤其当您需要频繁创建字体时。在我们的例子中由于只要创建一种字体,故用 CreateFont 就足够了。在调用该函数后会返回所创建的字体的句柄,然后把该句柄选进“设备环境”使其成为当前字体,随后所有的“绘制”文本串的函数在被调用时都要把该句柄

20、作为一个参数传递。例子: (见光盘FirstWindow3)#include Windows.h#include tchar.hHWND hWinMain;TCHAR szClassName = _T(MyClass);TCHAR szCaptionMain = _T(My First Window!);TCHAR szText = _T(Win32 program, Simple and powerful !);TCHAR FontName = _T(script);WNDCLASSEX stdWndClass;LRESULT CALLBACK ProcWinMain( HWND hWnd,

21、 UINT Msg, WPARAM wParam, LPARAM lParam ) PAINTSTRUCT stPs; HDC hDC; HFONT hFont,hOldFont; switch(Msg) case WM_PAINT: hDC = BeginPaint(hWnd,&stPs); hFont = CreateFont(24,16,0,0,400,0,0,0,OEM_CHARSET,OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH | FF_SCRIPT,FontName); hOldFont

22、 = (HFONT)SelectObject(hDC,hFont); SetTextColor(hDC,RGB(200,200,50); SetBkColor(hDC,RGB(0,0,255); TextOut(hDC,0,0,szText,sizeof(szText); SelectObject(hDC,hOldFont); EndPaint(hWnd,&stPs); break; case WM_DESTROY: PostQuitMessage(NULL); break; default: return DefWindowProc(hWnd, Msg, wParam, lParam );

23、return 0;int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) MSG stMsg; WNDCLASSEX stdWndClass; RtlZeroMemory(&stdWndClass, sizeof(stdWndClass); stdWndClass.hCursor = LoadCursor(0,IDC_ARROW); stdWndClass.cbSize = sizeof(stdWndClass); stdWndClass.style = C

24、S_HREDRAW|CS_VREDRAW; stdWndClass.lpfnWndProc = ProcWinMain; stdWndClass.hbrBackground = (HBRUSH)COLOR_WINDOW; stdWndClass.lpszClassName = szClassName; stdWndClass.hInstance = hInstance; RegisterClassEx(&stdWndClass); hWinMain = CreateWindowEx(WS_EX_CLIENTEDGE,szClassName,szCaptionMain, WS_OVERLAPPE

25、DWINDOW,100,100,600,400,NULL,NULL,hInstance,NULL); if(!hWinMain) return 0; ShowWindow(hWinMain,SW_SHOWNORMAL); UpdateWindow(hWinMain); while(GetMessage(&stMsg,NULL,0,0) TranslateMessage(&stMsg); DispatchMessage(&stMsg); return stMsg.wParam;分析:CreateFont 函数产生一种逻辑字体,它尽可能地接近参数中指定的各相关值。这个函数大概是所有 Windows

26、 API函数中所带参数最多的一个。它返回一个指向逻辑字体的句柄供调用 SelectObject 函数使用。下面我们详细讲解该函数的参数:HFONT CreateFont( int nHeight, / height of font int nWidth, / average character width int nEscapement, / angle of escapement int nOrientation, / base-line orientation angle int fnWeight, / font weight DWORD fdwItalic, / italic attri

27、bute option DWORD fdwUnderline, / underline attribute option DWORD fdwStrikeOut, / strikeout attribute option DWORD fdwCharSet, / character set identifier DWORD fdwOutputPrecision, / output precision DWORD fdwClipPrecision, / clipping precision DWORD fdwQuality, / output quality DWORD fdwPitchAndFam

28、ily, / pitch and family LPCTSTR lpszFace / typeface name);nHeight: 希望使用的字体的高度,0为缺省。nWidth: 希望使用的字体的宽度,一般情况下最好用0, 这样 Windows 将会自动为您选择一个和高度匹配的值。因为在我们的例子中那样做的话会使得字符因太小而无法显示,所以 我 们设定它为16。nEscapement: 每一个字符相对前一个字符的旋转角度,一般设成0。900代表转90度,1800转180度,2700转270度。nOrientation: 字体的方向。nWeight: 字体笔画的粗细。Windows 为我们预定

29、义了如下值:FW_DONTCARE 等于 0FW_THIN 等于 100FW_EXTRALIGHT 等于 200FW_ULTRALIGHT 等于 200FW_LIGHT 等于 300FW_NORMAL 等于 400FW_REGULAR 等于 400FW_MEDIUM 等于 500FW_SEMIBOLD 等于 600FW_DEMIBOLD 等于 600FW_BOLD 等于 700FW_EXTRABOLD 等于 800FW_ULTRABOLD 等于 800FW_HEAVY 等于 900FW_BLACK 等于 900cItalic: 0为正常,其它值为斜体。 cUnderline: 0为正常,其它值

30、为有下划线。cStrikeOut: 0为正常,其它值为删除线。cCharSet: 字体的字符集。一般选择OEM_CHARSET,它使得 Windows 会选用和操作系统相关的字符集。cOutputPrecision: 指定我们选择的字体接近真实字体的精度。 一般选用OUT_DEFAULT_PRECIS,它决定了缺省的映射方式。cClipPrecision: 指定我们选择的字体在超出裁剪区域时的裁剪精度。 一般选用CLIP_DEFAULT_PRECIS,它决定了裁剪精度。cQuality: 指定输出字体的质量。它指出GDI应如何尽可能的接近真实 字体,一共有三种方式:DEFAULT_QUALIT

31、Y, PROOF_QUALITY 和DRAFT_QUALITY。cPitchAndFamily:字型和字体家族。lpFacename: 指定字体的名称。上面的描述不一定好理解,您如果要的到更多的信息,应参考 MSDN。hOldFont = (HFONT)SelectObject(hDC,hFont);在我们得到了指向逻辑字体的句柄后必须调用 SelectObject 函数把它选择进“设备环境”,我们还可以调用该函数把诸如此类的像颜色、笔、画刷 等GDI对象选进“设备环境”。该函数会返回一个旧的“设备环境”的句柄。您必须保存该句柄,以便在完成“绘制”工作后再把它选回。在调用 SelectObject 函数后一切的绘制函数都是针对该“设备环境”的。 SetTextColor(hDC,RGB(200,200,50); SetBkColor(hDC,RGB(0,0,255);我们用宏 RGB 产生颜色,然后分别调用 SetTextColor 和 SetBkColor。 TextOut(hDC,0,0,szText,sizeof(szText);我们调用 TextOut 在客户区用我们前面选定的字体和颜色“绘制”文本串。 SelectObject(hDC,hOldFont);在我们“绘制”完成后,必须恢复“设备环境”。我们必须每一次都这么做。技术成就梦想

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!