第三章:Windows图形基础
一:设备描述表
设备描述表是Windows应用程序、设备驱动程序和输出设备之间的桥梁,它与一个特定的设备相关联。例如,对显示器来说,设备描述表通常指显示器上的某个窗口。设备描述表描述了所选定的绘图工具、字体、字体颜色、工具在设备上绘制(或者说是映射)的方式及设备上可使用的输出区域等属性。WindowsGDI函数实际上是在设备描述表里显示正文及绘图的。 当程序显示文字或绘图时,首先必须获得一个设备描述表句柄,完成输出文字或绘图之后,还必须及时释放该句柄,否则会大大减少Windows的存储单元。释放之后的句柄就不会再有效了。一般说来,在处理某条消息时,获取和释放设备描述表句柄必须成对出现,而且不同设备描述表的获取与释放的方法也不同。而这只是所使用的函数不同而已。
二:显示缓冲区
Windows环境是基于图形操作的,图形设备接口(GDI)是一个在Windows应用程序中执行与设备无关的函数库。这些函数在不同的输出设备上产生图形及文字输出。
显示缓冲区是一种“设备缓冲区”,特别用于窗口用户区的输出。设备缓冲区定义设备,绘图工具及有关设备的完整信息。显示缓冲区只定义与窗口用户区有关的内容,包括输出设备、当前绘图工具、颜色,以及其它一些GDI输出函数产生输出所需的信息。在窗口中绘图,需要使用窗口的句柄,根据窗口句柄,可以得到窗口用户区的显示缓冲区句柄,所有GDI输出函数都需要一个显示缓冲区句柄,没有它就无法完成输出。
可以根据输出的需要选择获得显示缓冲区句柄的方法。画和写操作可以存在于应用程序中的任何地方(包括WinMain函数中),大多数应用程序把它们放在窗口函数中。每当对窗口的操作可能影响用户区内容时,Windows发送WM_PAINT消息给窗口函数。应用程序通常在响应WM_PAINT消息时,完成画和写。Windows发送WM_PAINT消息给窗口函数,并由它刷新用户区,因为只有应用程序才知道用户区的内容。
通常用BeginPaint函数来响应WM_PAINT消息。如果要在没有WM_PAINT消息的时刻画用户区,必须使用GetDC函数得到显示缓冲区的句柄。
当应用程序需要得到窗口的显示缓冲区时,Windows把它暂时借给应用程序。显示缓冲区是一种共享资源,一个应用程序占有它之后,其它应用程序就无法得到它。因此,应用程序在利用显示缓冲区画完窗口内容之后,就必须使用ReleaseDC函数释放它。同理,要求用EndPaint函数释放由BeginPaint函数获得的显示缓冲区。
显示缓冲区中有缺省的画笔、画刷和缺省字体。
1:GetDC函数
在处理非WM_PAINT消息时,应用程序获取窗口用户区设备描述表句柄使用GetDC函数,它常常用来对用户的某些动作提供反馈。例如,当用户移动鼠标光标穿越窗口时,在屏幕上画一条线。GetDC函数返回一个显示缓冲区句柄,它可以用于任何GDI输出函数。
请看下面这个程序段:
case WM_PAINT:
hDC=GetDC(hWnd);
TextOut(hDC,10,10, "Hello",5);
ReleaseDC(hWnd,hDC);
Break;
在这里,我们用设备环境句柄hDC定义了一个设备描述表句柄hDC,然后利用函数GetDC取得hWnd参数所标识窗口的显示缓冲区的显示描述表赋给hDC,再通过TextOut函数在窗口用户区(10,10)位置显示包含5个字符的字符串,使用完之后,及时用函数RealeaseDC释放这个显示描述句柄hDC。
使用GetDC函数获得显示缓冲区句柄,在窗口函数中处理WM_PAINT消息。当窗口函数接收到影响用户区内容的WM_PAINT消息时,用户区中先前已画的内容可能被擦掉。这是因为在处理WM_PAINT消息的过程中,Windows发送WM_ERASEBKGND消息给窗口函数,如果把WM_ERASEBKGND消息交给DefWindowProc函数处理,DefWindowProc函数使用这种窗口类的背景色填满受影响的区域,并擦掉原先已经画的内容。
2: WM_PAINT消息
在前面我们已经认识了WM_PAINT,让我们再来看一下。由于Windows是一个多任务环境,某个应用程序的窗口上面可能被对话框或窗口覆盖,当撤消这些对话框或窗口时,这个应用程序窗口中就有一个”空洞”,这个”空洞”就是一块无效的用户区域。为重新显示无效用户区域,Windows发送WM_PAINT消息实现。要求Windows发送WM_PAINT的情况有:改变窗口大小,覆盖用户区的菜单或对话框关闭,使用UpdateWindow和ScrollWindow函数等。
Windows发送WM_PAINT消息时,把它放到应用程序队列的最后,使得其它的输入能够先于WM_PAINT消息被处理。GetMessage函数也得到队列中WM_PAINT消息之后的其它消息,即只有没有其它消息的情况下,才从队列中取出WM_PAINT消息进行处理。这样做是为了让应用程序首先完成影响窗口显示结果的其它操作,不致因为频繁地执行输出操作而引起显示器的闪烁。Windows把WM_PAINT消息放在队列最后就是这个原因。
Windows并非WM_PAINT消息的唯一来源,使用InvalidateRect或InvalidateRgn函数也可以产生绘图窗口的WM_PAINT消息。这两个函数把用户区全部或部分标记成无效用户区而要求重新显示。下面的函数调用是把整个用户区标记成无效:
InvalidateRect(hWnd,NULL,TRUE);
这个例子把hWnd句柄参数指定的窗口用户区标记成无效。作为矩形结构的NULL参数指定整个用户区。TRUE参数表示擦除背景。
InvalidateRect和InvalidateRgn函数并不实际产生WM_PAINT消息。当用户区无效时,Windows就发送一个WM_PAINT消息,如果用户区的其它部分也被标记成无效,Windows就不再发送另一条WM_PAINT消息,而是把已有的无效区域合并,以便根据同一条WM_PAINT消息处理所有这些区域。
如果想改变重新显示的用户区,可以调用ValidateRect和ValidateRgn函数使相应的用户区有效,这两个函数取消原有的无效区,并在没有无效区的情况下取消队列中的WM_PAINT消息。
如果不想等待应用程序队列中的WM_PAINT消息,使用UpdateWindow函数直接发送WM_PAINT消息给指定窗口的窗口函数。如果还存在无效的用户区,UpdateWindow函数从队列中取出WM_PAINT消息,并把它直接发送给指定窗口的窗口函数。UpdateWindow函数通常用在窗口需要立即更新它的用户区,如在窗口刚被创建时使用。
用BeginPaint函数获得输出文字等的显示缓冲区句柄:
PAINTSTRUCT ps;
…
case WM_PAINT:
hdc=BeginPaint(hWnd,&ps);
/* 输出操作 */
EndPaint(hWnd,&ps);
Break;
结构PAINTSTRUCT函数原型如下:
typedef struct tagPAINTSTRUCT
{
HANDLE hDC; //设备描述表句柄
BOOL rErase; //确定背景是否已被重画
RECT rePaint; //给出无效矩形的边界
BOOL fRestore; //内部使用的保留字段
BOOL fIncUpdate; //保留字段
BYTE rgbReserved; //保留字段
}PAINTSTRUCT;
无效区域是一个矩形区域,它是一个RECT结构,其在window.h定义为
typedef struct tagRECT
{
int left; //矩形左上角的X坐标
int top; //矩形左上角的Y坐标
int right; //矩形右下角的X坐标
int bottow; //矩形右下角的Y坐标
}RECT
例中BeginPaint函数返回一个显示缓冲区句柄,它可用于其它的GDI输出函数中。
EndPaint函数通知Windows所有输出操作均已处理完毕,并释放显示缓冲区。
三:坐标系统
为了准备显示缓冲区,Windows调整设备的原点,使它位于用户区而不是显示器的左上角,并且还设置了一个剪辑区,使显示缓冲区的输出被”剪辑”到用户区。也就是说,用户区范围之外的输出并不送到显示器上。
显示缓冲区默认的坐标系统很简单,用户区的左上角是原点,即点(0,0)。向右的每个像素表示X轴方向的一个单位,向下的每个像素表示Y轴方向的一个单位。
通过修改映射模式和显示原点,可以改变坐标系统。映射模式定义坐标系统单位。Windows应用程序可通过调用SetMapMode函数来设定映射模式,其中参数定义了所采取的坐标系统单位,即将一个逻辑单位映射为设备单位的比例。设备单位可为任意个像素,英寸或毫米,还定义了设备的X轴和Y轴方向。默认的映射模式为MM_TEXT,即默认的坐标系统。当前设备描述表的映射方式可通过调用GetMapMode函数得到。通过调用SetViewPortOrg函数,可以把坐标系统原点移到任何位置。
1:SetMapMode函数
语法: int SetMapMode(HDC hdc,int nMapMode);
说明: 参数hDC是设备描述表,参数nMapMode是映射模式。映射共有8种映射模式,取值及含义如下:
值 | 含 义 |
MM_ANISOTROPIC | 逻辑单位被映射成任意的物理单位,X轴和Y轴成任意比例 |
MM_HIENGLISH | 一个逻辑单位被映射成0.001英寸,正X向右,正Y向上 |
MM_HIMETRIC | 一个逻辑单位被映射成0.01英寸,正X向上,正Y向上 |
MM_ISOTROPIC | 逻辑单位被映射成任意的物理单位,X轴和Y轴的变换比例相同 |
MM_LOENGLISH | 一个逻辑单位被映射成0.01英寸,正X向右,正Y向上 |
MM_LOMETRIC | 一个逻辑单位被映射成0.1毫米,正X向右,正Y向上 |
MM_TEXT | 一个逻辑单位被映射成一个设备像素,正X向右,正Y向下 |
MM_TWIPS | 一个逻辑单位被映射成打印机点的二十分之一,正X向右,正Y向上 |
本例用MM_ANISOTROPIC模式。这种模式把逻辑单位映射成任意的物理单位,X轴和Y轴成任意比例。
2:GetMapMode函数
语法: DWORD SetViewPortOrg(HDC hDC)
说明: 该函数取得当前设备描述表的映射模式。
3:SetViewPortOrg函数
语法: DWORD SetViewPortOrg(HDC hDC,int x,int y)
说明: 该函数为hDC设置视口原点。返回低字节是原点X坐标,高字节为原点Y坐标。
四:画图函数
GDI提供各种各样的输出操作,从画线到写字应有尽有。为了画线、矩形、圆、扇形和写字,可相应地调用一些函数。这些函数使用已选择的笔和刷画边框,并填写图形内部区,以及使用已选择的字体写字。
1:画点函数SetPixel
原型为: COLORREF SetPixel(HDC hDC,int x,int y,COLORREF cclrref);
该函数把X和Y指定的点置为clrref指定的颜色。
2: 画线函数LineTo与MoveTo
LineTo函数用来画线,并且通常与MoveTo函数配合使用,
如画一条从点(10,70)到点(250,100)的线:
MoveTo(hDC,10,70);
LineTo(hDC,250,100);
3: 矩形函数Rectangle
Rectangle函数用来画矩形。它使用已选择的笔画边框,使用已选择的刷子填满矩形内部。下面的例子画一个左上角位于点(10,20),右下角位于点(40,100)的矩形:
Rectangle(hDC,10,20,40,100);
4: 画圆或椭圆函数Ellipse
Ellipse函数用来画圆或椭圆。它使用已选择的笔画框,使用已选择的刷填满圆或椭圆的内部。下面的例子画一个用点(10,20)和点(40,100)构成矩形框中的椭圆:
Ellipse(hDC,10,20,40,100);
5: 画圆弧函数Arc
Arc函数用来画一段弧,这段弧由包围它的矩形和弧的开始点和结束点共同定义。下面的例子在点(10,90)和点(360,120)所指定的矩形中画一段弧,它的起点和终点分别是点(15,90)和点(360,90):
Arc(hDC,10,90,360,120,15,90,360,110);
弧的起点坐标和终点坐标精确地位于弧上。
6: 画扇形函数Pie
Pie函数用来画扇形。扇形由一段弧和两条从弧焦点到弧端点的半径组成。Pie函数使用已选择的笔画框,使已选择的刷子填满扇形内部。下面的例子画一个用点(310,30)和点(360,80)构成的矩形围成的扇形。其起点和终点分别为点(360,30)和点(360,80):
Pie(hDC,310,30,360,80,310,30,360,80);
弧的起点和终点不必精确地位于弧线上
五: 创建、选择和删除绘图工具
GDI提供了种类丰富的绘图工具,包括画线的笔、填满空区的刷子和写字用的字体。可以用CreatePen和CreateSolidBrush之类的函数创建这些工具,并用SelectObject函数把它们选择到显示缓冲区。用过一种绘图工具之后,应及时通过DeleteObject函数把它们删除。
1: 画 笔
画笔决定了线条的颜色、宽度和线型(实线、点线或点划线等)。Windows使用当前在设备描述表中已选择的画笔来画线。程序中可以选择Windows的预定义画笔,也可以选择自定义的画笔。
预定义画笔有三种:BLACK_PEN(黑色笔) 、WHITE_PEN(白色笔)和NULL_PEN(空笔),这些都在windows.h中已经定义好了,程序员可使用GetStockObject函数来选择其中的一种,系统缺省的画笔为黑色笔。Windows.h包含了HPEN的数据类型定义,使用该类型可以定义画笔句柄的变量。
仅靠系统提供的预定义画笔远远不能满足需求,应用程序可根据实际需要创建一种自定义的逻辑画笔。其步骤一般为:首先用CreatePen或CreatePenIndirect函数建立一支画笔,再调用SelectObject函数将其选入设备描述表,此后就可使用该画笔在选定的设备描述表中进行绘图操作。任何时候某一设备描述表只能有一支画笔被选入作为当前画笔,当一支画笔被选入时,原先已选入的画笔便不再有效。完成绘图操作后,可以通过调用DeleteObject来释放已建立的画笔。
①: 函数CreatePen()
语法:HPEN CreatePen(int fnPenStyle,int nWidth,COLORREF clrref);
说明:该函数创建一个逻辑画笔。其中fnPenStyle参数指定画笔的线型,该参数可取由windows.h定义的七个标识符之一,其含义为:
PS_SOLID | 实线 |
PS_DASH | 虚线 |
PS_DOT | 点线 |
PS_DASHDOT | 夹一点虚线 |
PS_DASHDOTDOT | 夹二点虚线 |
PS_NULL | 无 |
PS_INSIDEFRAME | 线画在所有构件框架内 |
nWidth参数是用逻辑单位表示的画笔的宽度;clrref参数是一个COLORREF类型的颜色值,指定画笔的颜色,可用宏指令RGB构造这个值,如:
Clrref=RGB(byRed,byGreen,byBlue);
在使用CreatPen函数时,要检查其返回值,确保它是一个有效的句柄。
下面给出一段程序,说明建立、选择和释放画笔的一般方法,假定程序要用一支宽度为3的黑色笔作图,则程序如下:
HPEN hPen,hOldPen:
HPen=CreatePen(PS_SOLD,3,RGB(0,0,0));
if(hPen)
{
hOldPen=SelectObject(hDC,hPen); //将hPen作为当前画笔
… … //这里进行绘图操作
SelectObject(hDC,hOldPen); //恢复原画笔
}
DelectObject(hPen); //删除hPen画笔,释放空间
②: 函数CreatePenIndirect()
语法:HPEN CreatePenIndirect(LOGPEN FAR* lpLogPen);
说明:该函数用lpLogPen所指的LOGPEN结构中的信息创建一个逻辑画笔。LOGPEN的结构如下:
typedef struct tagLOGPEN
(
WORD lopnStyle;
POINT lopnWidth;
COLORREF lopnColor;
)LOGPEN;
其中lopnStyle指定画笔线型,该参数可取下列值之一:
PS_SOLID | 0 |
PS_DASH | 1 |
PS_DOT | 2 |
PS_DASHDOT | 3 |
PS_DASHDOTDOT | 4 |
PS_NULL | 5 |
PS_INSIDEFRAME | 6 |
nWidth参数是用逻辑单位表示的画笔的宽度;clrref参数是一个COLORREF类型的颜色值,指定画笔的颜色,可用宏指令RGB构造这个值。
2: 刷 子
当我们在绘制一些区域图形时,其内部往往需要以某种图案进行填充,这就需要选定”刷子”作为绘图工具。Windows系统不仅为用户提供了预定义刷子,而且还允许应用程序自定义刷子。
Windows系统中预定义的刷子有如下七种:
BLACK_BRUSH | 黑色刷子 |
DKGRAY_BRUSH | 深灰色刷子 |
GRAY_BRUSH | 灰色刷子 |
HOLLOW_BRUSH | 中空刷子,画边界而不填充 |
LTGRAY_BRUSH | 浅灰色刷子 |
NULL_BRUSH | 空刷子 |
WHITE_BRUSH | 白色刷子 |
应用程序可以调用GetStockObject函数选用其中一个,系统缺省的刷子是白色刷子。Window.h包含了HBRUSH数据类型的定义,使用该类型就可定义刷子句柄的变量。
仅靠这七种刷子往往不能满足要求,应用程序通过调用如下几种函数创建逻辑刷子,这些函数返回值均为刷子句柄。
①: 函数CreateHatchBrush()
语法:HBRUSH CreateHatchBrush(int fnStyle,COLORREF clrref);
说明: 该创建一个带阴影的逻辑刷子。
FnStyle指定的阴影格式如下:
HS_BDLAGONAL | 45度向上斜线组成的阴影图案(自左到右) |
HS_CROSS | 水平和垂直交叉组成的阴影图案 |
HS_DIAGCROSS | 45度斜线交叉组成的阴影图案 |
HS_FDIAGONAL | 45度向下斜线组成的阴影图案(自左到右) |
HS_HORZONAL | 水平线组成的阴影图案 |
HS_VERTICAL | 垂直线组成的阴影图案 |
Clrref是具有COLORREF类型定义的刷子颜色值,可用宏指令RGB构造这个值。
②: 函数CreateSolidBrush()
语法:HBRUSH CreateSolidBrush(COLORREF,clrre);
说明:该函数创建的是一种实颜色的逻辑刷子。Clrref是具有COLORREF类型定义的刷子颜色值,可用宏指令RGB构造这个值。
同样,使用创建刷子的函数时,要检查其返回,确保它是一个有效的句柄。
一旦创建了绘图工具之后,可以SelectObject函数把它选择到显示缓冲区里。在使用显示缓冲区之前,并不一定非要创建和选择绘图工具,Windows为每个显示缓冲区提供默认的绘图工具。例如:黑色笔,白色刷子和系统字体。
DeleteObject函数用来删除不再需要的绘图工具,但不能删除一个已选进显示缓冲区的绘图工具,而是应该使用SelectObject函数恢复原有的绘图工具,然后再删除需要删除的工具。
3: 填 充 图 形
绘制一些需要以某种图案进行填充的区域图形时,需要选定”刷子”作为绘图工具Windows系统中预定义的刷子有七种,应用程序可以调用GetStockObject函数选用其中一个,系统缺省的刷子是白色刷子。
当靠这七种刷子不能满足要求时,应用程序通过调用Windows函数创建逻辑刷子,这些函数返回值均为刷子句柄.
六: 文字与字体
Windows是使用定义好的与设备无关的字符集,它没有DOS的文本方式与图形方式之分。Windows的”文本”字符也是图形,所以屏幕上所显示的用打印机或绘图仪等输出品的文本完全一样,做到”所见即所得”.
1: 文本绘图函数
文本绘制函数见下表:
函 数 | 含 义 |
DrawText | 在一个特定矩形区中绘制某一格式的文本 |
ExtTextOut | 在一个特定矩形区中,以当前字体写一字符串 |
GrayString | 用灰色文本写一字符串 |
TabbedTextOut | 写一带扩展字符的字符串 |
TextOut | 以当前的字体写一字符串 |
要输出文本就离不开字体。描述一个字体的值叫做字体的文本度量(Text Metric)。TEXTMETRIC定义了结构变量tm供文本度量用。
函数GetTextMetrics可以获取一个字体文本度量并将它放入一个类型为TEXTMETRIC的数据结构中,该结构如下所示:
typedef struct tagTEXTMETRIC
{
LONG tmHeight; //
字符高度
LONG tmAscent; //
字符上部高度(基线以上)
LONG tmDescent; //
字符下部高度(基线以下)
LONG tmInternalLeading; //
由tmHeight定义的字符高度的顶部空间数目
LONG tmExternalLeading; //
加在两行之间的空间数目
LONG tmAveCharWidth; //
平均字符宽度
LONG tmMaxCharWidth; //
最宽字符的宽度
LONG tmWeight; //
字体的粗细轻重程度
LONG tmOverhang; //
加入某些拼接字体上的附加高度
LONG tmDigitizedAspectX; //
字体设计所针对的设备水平方向
LONG tmDigitizedAspectY; //
字体设计所针对的设备垂直方向
BCHAR tmFirstChar; //
为字体定义的第一个字符
BCHAR tmLastChar; //
为字体定义的最后一个字符
BCHAR tmDefaultChar; //
字体中所没有字符的替代字符
BCHAR tmBreakChar; //
用于拆字的字符
BYTE tmItalic; //
字体为斜体时非零
BYTE tmUnderlined; //
字体为下划线时非零
BYTE tmStruckOut; //
字体被删去时非零
BYTE tmPitchAndFamily; //
字体间距(低4位)和族(高4位)
BYTE tmCharSet; //
字体的字符集
} TEXTMETRIC;
2:
GDI字体族和字样
GDI字体族和字样表如下表所示:
字体族 | 字体族常量 | 字样 | 说明 |
Dontcare | FF_DONTCARE | System | 当不能提供字体信息或字体并不重要时使用 |
Decorative | FF_DECORATIVE | Symbol | 新奇字体 |
Modern | FF_MODERN | Courer,ModernIerminal | 笔画大小固定的字体,但衬线可有可无 |
Roman | FF_ROMAN | Roman,TimeRoman | 有衬线的、笔画大小可变的罗马字体 |
Script | FF_SCRIPT | Script | 仿手写体 |
Swiss | FF_SWISS | Helvetical,System | 无衬线的、笔画大小可变的字体 |
①: CreateFontIndirect函数
语法:HFONT CreateFontIndirect
(
CONST LOGFONT *lplf // pointer to logical font structure
);
说明:参数lplf是LOGFONT结构的指针。结构中含有逻辑字体的特征信息。该函数用lplf所指的LOGFONT结构中的信息创建一种逻辑字体。
LOGFONT结构的定义如下:
typedef struct tagLOGFONT
{
LONG lfHeight; //
字高度
LONG lfWidth; //
字符平均宽度
LONG lfEscapement; //
行与水平页角度
LONG lfOrientation; //
基线与水平角度
LONG lfWeight; //
笔划的粗细
BYTE lfItalic; //
非零为斜体
BYTE lfUnderline; //
非零为下划线
BYTE lfStrikeOut; //
非零为中划线
BYTE lfCharSet; //
指定字符集
BYTE lfOutPrecision; //
输出精度
BYTE lfClipPrecision; //
裁剪精度
BYTE lfQuality; //
输出质量
BYTE lfPitchAndFamily; //
字体的字距和族
TCHAR lfFaceName[LF_FACESIZE]; //
含字体名的字符串
} LOGFONT;
下面的例子用函数GreatFontIndirect来产生TimesRoman和Helevtrica逻辑字体。
case WM_PAINT:
LOGFONT LogFont;
HFONT hHelv,hTmsRmn;
memset(&LogFont,0,sizeof(LOGFONT));
LogFont.lfHeight = 25;
LogFont.lfWidth = 15;
LogFont.lfUnderline = 1;
LogFont.lfItalic = 1;
lstrcpy(LogFont.lfFaceName,"Helv");
hHelv=CreateFontIndirect(&LogFont);
memset(&LogFont,0,sizeof(LOGFONT));
LogFont.lfHeight = 25;
LogFont.lfWidth = 15;
LogFont.lfUnderline = 1;
LogFont.lfItalic = 1;
lstrcpy(LogFont.lfFaceName,"TmsRmn");
hTmsRmn=CreateFontIndirect(&LogFont);
hdc = BeginPaint(hWnd, &ps);
SelectObject(hdc,hHelv);
TextOut(hdc,20,20,"Hello",5);
SelectObject(hdc,hTmsRmn);
TextOut(hdc,5,100,"Times Roman_Underlined and Itatics",34);
EndPaint(hWnd, &ps);
break;
②
:
函数
SetTextAlign
大多数文本函数传递的参数表都要求有一个点坐标参数以定义写文本的参考点。当前文本对齐属性规定了字符串如何相对于所传递的坐标进行写。SetTextAlign函数用以设置当前文本对齐属性。
语法
: UINT SetTextAlign(
HDC hdc, // handle to device context
UINT fMode // text-alignment flag
);
说明: 该函数设置文本对齐方式。Hdc是参数描述表,fuAlign是文本对齐方式,下表给出该函数的水平、垂直及更新标志。
TA_LEFT(
水平
)
、
TA_TOP(
垂直
)
、及
TA_NOUPDATECP(
不更新
)
是文本对齐标志的缺省设置
返回值:低字节是原水平对齐方式,高字节是原垂直对齐方式。
文本对齐标志
| |
| |
|
|
|
|
|
|
| |
| |
| |
| |
| |
| |
| |
③
: GetClientRect
函数
语法: BOOL GetClientRect(
HWND hWnd, // handle to window
LPRECT lpRect // address of structure for client coordinates
);
说明: hWnd是与用户区域相关的窗口,lpRect是指向RECT结构的指针。该函数把hWnd指定的用户区域坐标(以用户坐标表示)放到lpRect指向的结构中。用户坐标是以用户区域的左上角为原点定义的。
RECT数据结构定义如下:
typedef struct _RECT
{
LONG left; //
矩形左上角的
X
坐标
LONG top; //
矩形左上角的
Y
坐标
LONG right; //
矩形右下角的
X
坐标
LONG bottom; //
矩形右下角的
Y
坐标
} RECT;
[例]在窗口屏幕的中心显示文本.
char sname[]="Welcome you!";
int strsize=strlen(sname);
。。。。。。
switch (message)
{
。。。。。。
case WM_PAINT:
RECT rect;
hdc = BeginPaint(hWnd, &ps);
SetTextAlign(hdc,TA_CENTER);
GetClientRect(hWnd,(LPRECT)&rect);
TextOut(hdc,rect.right/2,rect.bottom/2,sname,strsize);
EndPaint(hWnd, &ps);
break;