Windows Api教案4.docx
《Windows Api教案4.docx》由会员分享,可在线阅读,更多相关《Windows Api教案4.docx(20页珍藏版)》请在冰豆网上搜索。
WindowsApi教案4
⒊填充空隙
问题:
在使用点式画笔和虚线画笔时,点和虚线之间的空隙会怎样呢?
这取决于DC的两个属性━━背景模式和背景颜色。
默认背景模式为OPAQUE,在这种方式下,Windows使用背景色来填充空隙,默认的背景色为白色。
1SetBkColor函数
COLORREFSetBkColor(
HDChdc,//handleofdevicecontext
COLORREFcrColor//backgroundcolorvalue
);
2GetBkColor函数
COLORREFGetBkColor(
HDChdc//handleofdevicecontext
);
3SetBkMode函数
intSetBkMode(
HDChdc,//handleofdevicecontext
intiBkMode//flagspecifyingbackgroundmode
);
其中iBkMode为TRANSPARENT或者OPAQUE
4GetBkMode函数
intGetBkMode(
HDChdc//handletodevicecontextofinterest
);
说明:
通过SetBkColor函数可以改变填充空隙的背景色,通过SetBkMode将背景模式转换为TRANSPARENT,可以阻止Windows填充空隙。
⒋绘图方式
1光栅运算
像素间的按位布尔运算叫做“光栅运算”,简记为“ROP”。
由于绘图只涉及两种像素(画笔和目标),因此又称为“ROP2”运算。
即当Windows使用画笔来画线时,它实际上执行画笔像素与目标位置处原来像素之间的某种按位布尔运算。
2绘图模式种类
绘图模式布尔操作
R2_BLACK0
R2_NOTMERGEPEN~(P|D)
R2_MASKNOTPEN~P&D
R2_NOTCOPYPEN~P
R2_MASKPENNOTP&~D
R2_NOT~D
R2_XORPENP^D
R2_NOTMASKPEN~(P&D)
R2_MASKPENP&D
R2_NOTXORPEN~(P^D)
R2_NOPD
R2_MERGENOTPEN~P|D
R2_COPYPEN(默认)P
R2_MERGEPENNOTP|~D
R2_MERGEPENP|D
R2_WHITE1
注意:
以上模式指在单色系统中绘图的模式。
3SetROP2函数
intSetROP2(
HDChdc,//handleofdevicecontext
intfnDrawMode//drawingmode
);
4GetROP2函数
intGetROP2(
HDChdc//handleofdevicecontext
);
六绘制填充区域
图形以当前设备描述表中选择的刷子来填充。
⒈现有画刷
WHITE_BRUSH
LTGRAY_BRUSH
GRAY_BRUSH
DKGRAY_BRUSH
BLACK_BRUSH
NULL_BRUSH(HOLLOW_BRUSH)
⒉选择现有画刷
HBRUSHhBrush;
hBrush=GetStockObject(GRAY_BRUSH);
SelectObject(hdc,hBrush);
用下面语句画一个没有边界框的图形。
SelectObject(hdc,GetStockObject(NULL_PEN));
用下面语句画一个没有填充的图形。
SelectObject(hdc,GetStockObject(NULL_BRUSH));
⒊Polygon函数和多边形填充方式
1Polygon函数
BOOLPolygon(
HDChdc,//handletodevicecontext
CONSTPOINT*lpPoints,//pointertopolygon'svertices
intnCount//countofpolygon'svertices
);
其中nCount是点的数目,如果该数组中的最后一个点与第一个点不同,则Windows将会再加一条线,将最后一个点与第一个点连起来。
(在Polyline函数中,Windows不会这么做)。
2SetPolyFillMode函数
intSetPolyFillMode(
HDChdc,//handletodevicecontext
intiPolyFillMode//polygonfillmode
);
其中,iPolyFillMode取值ALTERNATE或WINDING。
说明:
ALTERNATE方式,即假设从一个无穷大的封闭区域内部的点画线,只有假想的线穿过了奇数条边界线时,才填充封闭区域。
WINDING方式,即假设从一个无穷大的封闭区域内部的点画线,如果假想的线穿过了奇数条边界线,区域就被填充。
如果假想的线穿过了偶数条边界线,则如果一个方向的边界线数与另一个方向的边界线数不相等,就填充区域,否则不填充。
例如,见上图中的物体。
线上的箭头指出了画线的方向。
两种方式都会填充三个封闭的L形区域,号码为1~3。
号码为4和5的两个小内部区域,在ALTERNATE方式下不会被填充。
但是,在WINDING方式下,号码为5的区域会被填充,因为从区域内必须穿过两条相同方向的线才能到达图形外部。
号码为4的区域不会被填充,因为必须穿过两条方向相反的线。
④ALTWIND程序关键部分
LRESULTCALLBACKWndProc(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAMlParam)
{staticPOINTaptFigure[10]={10,70,50,70,50,10,90,10,90,50,
30,50,30,90,70,90,70,30,10,30};
staticintcxClient,cyClient;
HDChdc;
inti;
PAINTSTRUCTps;
POINTapt[10];
switch(message)
{
caseWM_SIZE:
cxClient=LOWORD(lParam);
cyClient=HIWORD(lParam);
return0;
caseWM_PAINT:
hdc=BeginPaint(hwnd,&ps);
SelectObject(hdc,GetStockObject(GRAY_BRUSH));
for(i=0;i<10;i++)
{
apt[i].x=cxClient*aptFigure[i].x/200;
apt[i].y=cyClient*aptFigure[i].y/100;
}
SetPolyFillMode(hdc,ALTERNATE);
Polygon(hdc,apt,10);
for(i=0;i<10;i++)
{
apt[i].x+=cxClient/2;
}
SetPolyFillMode(hdc,WINDING);
Polygon(hdc,apt,10);
EndPaint(hwnd,&ps);
return0;
caseWM_DESTROY:
PostQuitMessage(0);
return0;
}
returnDefWindowProc(hwnd,message,wParam,lParam);
}
⒋创建画刷
1CreateSolidBrush函数
HBRUSHCreateSolidBrush(
COLORREFcrColor//brushcolorvalue
);
说明:
函数中的Solid并不是指画刷为纯色。
在将画刷选入DC中时,Windows创建一个抖动色的位图,并为画刷使用该位图。
2CreateHatchBrush函数
HBRUSHCreateHatchBrush(
intfnStyle,//hatchstyle
COLORREFclrref//colorvalue
);
说明:
其中,iHatchStyle参数描述影线标记的外观。
取值如下:
③CreateBrushIndirect函数
HBRUSHCreateBrushIndirect(
CONSTLOGBRUSH*lplb//pointertostructuredescribingbrush
);
typedefstructtagLOGBRUSH{//lb
UINTlbStyle;
COLORREFlbColor;
LONGlbHatch;
}LOGBRUSH;
lbStyle
lbColor
lbHatch
BS_SOLID
BS_HOLLOW
BS_HATCHED
BS_PATTERN
BS_DIBPATTERNPT
画刷的色彩
忽略
影线的色彩
忽略
忽略
忽略
忽略
影线画刷风格
位图的句柄
指向DIB的指针
④选择、删除和获得画刷
SelectObject(hd,hBrush);
DeleteObject(hBrush);
GetObject(hBrush,sizeof(LOGBRUSH),(LPVOID)&logbrush);
七GDI映射方式
“映射方式”是一种几乎影响任何客户区绘图的设备描述表属性。
另外有4种设备描述表属性━━窗口原点、视口原点、窗口范围和视口范围与映射方式密切相关。
大多数GDI绘图函数都需要使用坐标值,这种坐标值使用的都是一种“逻辑单位”。
Windows必须将逻辑单位转换为“设备单位”,即像素。
这种转换是由映射方式、窗口和视口的原点,以及窗口和视口的范围所控制的。
映射方式还隐含地给出了x轴和y轴的指向。
⒈映射方式种类
映射方式
逻辑单位
增加值
x值
y值
MM_TEXT
MM_LOMETRIC
MM_HIMETRIC
MM_LOENGLISH
MM_HIENGLISH
MM_TWIPS
MM_ISOTROPIC
MM_ANISOTROPIC
像素
0.1mm
0.01mm
0.01in.
0.001in.
1/1440in.
任意(x=y)
任意(x!
=y)
右
右
右
右
右
右
可选
可选
下
上
上
上
上
上
可选
可选
默认映射方式为MM_TEXT
⒉SetMapMode函数
intSetMapMode(
HDChdc,//handleofdevicecontext
intfnMapMode//newmappingmode
);
⒊GetMapMode函数
intGetMapMode(
HDChdc//handleofdevicecontext
);
注意:
虽然在GDI函数中指定的坐标是32位的值,但是仅有WindowsNT能够处理全32位。
在Windows98中,坐标被限制为16位,范围从-32768到32767。
⒋设备坐标和逻辑坐标
①使用设备坐标的情况
Windows对所有消息(如WM_MOVE、WM_SIZE和WM_MOUSEMOVE),对所有非GDI函数,甚至对一些GDI函数,永远使用设备坐标。
GetSystemMetrics不是GDI函数,所以它总是以设备单位为量度来返回大小的。
尽管GetDeviceCaps是GDI函数,但是Windows仍然对HORZRES和VERTRES以设备单位作为返回值,因为该函数的目的之一就是给程序提供以像素为单位的设备大小。
②使用逻辑坐标的情况
基本上大多数GDI函数使用逻辑坐标。
而且GetTextMetrics调用中返回的TEXTMETRIC结构的值是使用逻辑单位的。
⒌设备坐标系
Windows将GDI函数中指定的逻辑坐标映射为设备坐标。
①屏幕坐标
当我们使用整个屏幕时,就根据“屏幕坐标”进行操作。
屏幕的左上角为(0,0)点,屏幕坐标用在WM_MOVE消息(对于非子窗口)以及下列Windows函数中:
CreateWindow和MoveWindow(都是对于非子窗口)、GetMessagePos、GetCursorPos、SetCursorPos、GetWindowRect、WindowsFromPoint等。
它们或者是与窗口无关的函数,或者是必须相对于整个屏幕点来移动(或者寻找)窗口的函数。
如果以DISPLAY为参数调用CreateDC,以获取整个屏幕的设备描述表,则默认情况下GDI调用中指定的逻辑坐标将被映射为屏幕坐标。
②整窗口坐标
“整窗口坐标”以程序的整个窗口为基准,如标题栏、菜单、滚动条和窗口框都包括在内。
整窗口坐标在Windows极少使用,但是如果用GetWindowDC获取设备描述表,GDI函数中的逻辑坐标就会转换为整个窗口坐标。
③客户区坐标
客户区坐标是最常使用的坐标系,点(0,0)是客户区的左上角。
当使用GetDc或BeginPaint获取设备表述表时,GDI函数中的逻辑坐标就会默认地转换为客户区坐标。
④ClientToScreen函数
BOOLClientToScreen(
HWNDhWnd,//windowhandleforsourcecoordinates
LPPOINTlpPoint//pointertostructurecontainingscreencoordinates
);
⑤ScreenToClient函数
BOOLScreenToClient(
HWNDhWnd,//windowhandleforsourcecoordinates
LPPOINTlpPoint//addressofstructurecontainingcoordinates
);
⑥GetWindowRect函数
BOOLGetWindowRect(
HWNDhWnd,//handletowindow
LPRECTlpRect//addressofstructureforwindowcoordinates
);
说明:
该函数用于获取屏幕坐标下的整个窗口的位置和大小。
⒍视口和窗口
①视口
“视口”是基于设备坐标(像素)的。
通常,视口和客户区相同,但是,如果用户已经用GetWindowDC或CreateDC获取了一个设备描述表,则视口也可以指整窗口坐标或者屏幕坐标。
点(0,0)是客户区(或者整个窗口或屏幕)的左上角,x的值向右增加,y的值向下增加。
②窗口
“窗口”是基于逻辑坐标的,逻辑坐标可以是像素、mm、英寸,或者用户想要的任何其他单位。
③转换公式
◆从窗口坐标转化为视口坐标:
其中,(xWindow,yWindow)是待转换的逻辑点;(xViewport,yViewport)是转换后的设备坐标点,更像客户区坐标;(xWinOrg,yWinOrg)是逻辑坐标的窗口原点;(xViewOrg,yViewOrg)是设备坐标的视口原点。
在默认的设备描述表中,这两个点均被设置为(0,0),但是它们可以改变。
这表明,逻辑点(xWinOrg,yWinOrg)总被映射为设备点(xViewOrg,yViewOrg)。
如果窗口和视口的原点是默认值(0,0),则公式简化为:
在上公式中,(xWinExt,yWinExt)是逻辑坐标的窗口范围;(xViewExt,yViewExt)是设备坐标的窗口范围。
在多数映射方式中,范围是映射方式所隐含的,不能够改变。
每个范围自身没有什么意义,但是视口范围与窗口范围的比是逻辑单位转换为设备单位的换算因子。
例如,当用户设置MM_LOENGLISH映射方式时,Windows将xViewExt设置为某个像素而将xWinExt设置为xViewExt像素占据的一英寸内有几百像素的长度。
比值给出了一英寸内有几百个像素的数值。
注意:
范围可以为负,逻辑x轴上的不一定非得在向右时增加;逻辑y轴上的值不一定非得在向下时增加。
◆从视口坐标转换为窗口坐标
④DPtoLP函数
BOOLDPtoLP(
HDChdc,//handletodevicecontext
LPPOINTlpPoints,//pointertoarrayofpoints
intnCount//countofpoints
);
⑤LPtoDP函数
BOOLLPtoDP(
HDChdc,//handleofdevicecontext
LPPOINTlpPoints,//arrayofpoints
intnCount//countofpoints
);
例如:
GetClientRect(hwnd,&rect);
DPtoLP(hdc,(PPOINT)&rect,2);
⒎处理MM_TEXT
①默认值
窗口原点:
(0,0)可以改变
视口原点:
(0,0)可以改变
窗口范围:
(1,1)不可改变
视口范围:
(1,1)不可改变
②简化公式
③SetViewportOrgEx函数
BOOLSetViewportOrgEx(
HDChdc,//handleofdevicecontext
intX,//newx-coordinateofviewportorigin
intY,//newy-coordinateofviewportorigin
LPPOINTlpPoint
//addressofstructurereceivingoriginalorigin
);
说明:
用于改变视口的原点。
④SetWindowOrgEx函数
BOOLSetWindowOrgEx(
HDChdc,//handleofdevicecontext
intX,//newx-coordinateofwindoworigin
intY,//newy-coordinateofwindoworigin
LPPOINTlpPoint
//addressofstructurereceivingoriginalorigin
);
说明:
用于改变窗口的原点。
如果将视口原点改变为(xViewOrg,yViewOrg),则逻辑点(0,0)就会映射为设备点(xViewOrg,yViewOrg)。
如果将窗口原点改变为(xWinOrg,yWinOrg),则逻辑点(xWinOrg,yWinOrg)将会映射为设备点(0,0)。
例如,假设客户区为cxClient个像素宽和cyClient个像素高。
如果将逻辑点(0,0)定义为客户区的中心,则进行如下调用:
SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);
则客户区的坐标系变成如下形状:
这时在客户区的左上角开始显示文本,需进行如下调用:
TextOut(hdc,-cxClient/2,-cyClient/2,”HELLO”,5);
用以下调用代替上述调用:
(效果相同)
SetWindowOrgEx(hdc,-cxClient/2,-cyClient/2,NULL)
TextOut(hdc,-cxClient/2,-cyClient/2,”HELLO”,5);
一般情况下,不会将这两个函数一起用,除非知道这么做的结果:
SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);
SetWindowOrgEx(hdc,-cxClient/2,-cyClient/2,NULL);
⑤GetViewportOrgEx函数
BOOLGetViewportOrgEx(
HDChdc,//handleofdevicecontext
LPPOINTlpPoint
//addressofstructurereceivingtheviewportorigin
);
⑥GetWindowOrgEx函数
BOOLGetWindowOrgEx(
HDChdc,//handleofdevicecontext
LPPOINTlpPoint
//addressofstructurereceivingthewindoworigin
);
⒏“度量”映射方式
Windows包含5种以物理尺寸来表示逻辑坐标的映射方式。
由于x轴和y轴的逻辑坐标映射为相同的物理单位,这些映射方式能使用户画出不变形的圆和矩形。
映射方式
逻辑单位
英寸
mm
MM_LOENGLISH
MM_LOMETRIC
MM_HIENGLISH
MM_TWIPS
MM_HIMETRIC
0.01英寸
0.1mm
0.001英寸
1/1400英寸
0.01mm
0.01
0.00394
0.001
0.000694
0.000394
0.254
0.1
0.0254
0.0176
0.01
①默认值
窗口原点:
(0,0)可以改变
视口原点:
(0,0)可以改变
窗口范围:
(?
,?
)不可改变
视口范围:
(?
,?
)不可改变
对于MM_LOENGLISH,Windows计算的范围如下:
例如:
假设Windows98使用96dpi的系统字体,这样对MM_LOENGLISH来说,96除以100的比值是0.01英寸装像素数。
对MM_LOMETRIC来说,96除以254的比值是0.1mm中的像素数。
Windows98下的映射方式:
映射方式
视口范围(x,y)
窗口范围(x,y)
MM_LOMETRIC
MM_HIMETRIC
MM_LOENGLISH
MM_HIENGLISH
MM_TWIPS
(96,96)
(96,96)
(96,96)
(96,96)
(96,96)
(254,-254)
(2540,-2540)
(100,-100)
(1000,-1000)
(1440,-1440)
WindowsNT下的映射方式:
映射方式
视口范围(x,y)
窗口范围(x,y)
MM_LOMETRIC
MM_HIMETRIC
MM_LOENGLISH
MM_HIENGLISH
MM_TWIP