Windows编程学习笔记(五)
第二章 图形基础(下)
用画刷填入内部
画刷是一个8*8的位图,他水平和垂直地重复使用来填入内部区域。
Windows还有五个函数,让我们建立逻辑画刷,然后就可以使用SelectObject选入,建立的逻辑画刷最后必须要删除。
1. hBrush = CreateSolidBrush(crColor); 其中Solid并不是指画刷为纯色。
2. hBrush = CreateHatchBrush(iHatchStyle,crColor); 这是由各种颜色线条组成的画刷,如果背景方式为OPAQUE,则用背景色(它也被转换为纯色)来填入线之间的空间。在这种情况下,影线和填入色都不能是混色而成的颜色。如果背景方式为TRANSPARENT,则Windows只画出影线,不填入它们之间的区域。
3. hBrush = CreatePatternBrush 和 CreateDIBPatternBrushPt 建立自己的位图的画刷。
4. hBrush = CreateBrushIndirect(&logbrush);LOGBRUSH的三个字段的结构如下表所示:
/****************************************************/
GDI映像方式
到目前为止,所有的程序都是相对于显示区域的左上角,以图素为单位的,这是内定情况,担不是唯一的。Windows定义了8种映像方式,可以使用SetMapMode(hdc,iMapMode);来设定映射方式,也可使用iMapMode = GetMapMode(hdc)来获得当前设备的映射方式。
设备坐标系
有三种坐标系:
1. 整个屏幕为基准的坐标系
2. 以整个窗口为基准的坐标系
3. 以显示区域为基准的坐标系
三者的左上角都是(0,0);
我们可使用 SetViewportOrgEx和SetWindowOrgEx用来改变视端窗口的原点,这两个函数都有改变轴的效果 ,比如想要将逻辑点(0,0)设定为显示区域的中心,可以这样使用:
SetViewportOrgEx(hdc,cxClient/2,cyClient/2,NULL);
我们也可以使用下列函数来得到目前视端口和窗口的原点:
POINT pt;
GetViewportOrgEx(hdc,&pt);
GetWindowOrgEx(hdc,&pt);
/*************************************************************/
矩形、区域
矩形函数 FillRect(hdc,&rect,hBrush);FrameRect(hdc,&rect,hBrush);InverRect(hdc,&rect);
第一个函数就是填充举行,第二个函数是用指定画刷画矩形的边界,第三个翻转矩形中的像素。
Windows还提供了9个函数来让我们更加方便的对RECT结构进行操作,下面就一一来看:
SetRect(&rect,xleft,ytop,xright,ybottom); 设定rect值
OffsetRect(&rect,x,y); 将矩形沿x、y移动单元
InflateRect(&rect,x,y); 增减矩形的尺寸
SetRectEmpty(&rect); 清空矩形
CopyRect(&dest_rect,&src_rect); 将矩形赋值给里一个矩形
bEmpty = IsRectEmpty(&rect); 确定矩形是否为空
bInRect = PtInRect(&rect,pt); 确定点是否在矩形内部
也可以使用 dest_rect = src_rect;
/************************************************************/
lbStyle (UINT) |
lbColor (COLORREF) |
lbHatch (LONG) |
BS_SOLID |
画刷的色彩 |
忽略 |
BS_HOLLOW |
忽略 |
忽略 |
BS_HATCHED |
影线的色彩 |
影线画刷风格 |
BS_PATTERN |
忽略 |
位图的句柄 |
BS_DIBPATTERNPT |
忽略 |
指向DIB的指标 |
PeekMessage OR GetMessage
PeekMessage(&msg,NULL,0,0,PM_REMOVE);
前面四个参数(msg指针,wnd句柄,两个值指示消息范围)与GetMessage相同。如果想要函数有传回所有的消息时,可以设定为0,如果是所有窗口的消息,可以设定为NULL,最后一个参数是决定是否删除消息,PM_REMOVE PM_NOREMOVE,如果又符合条件的消息,那么将传回TRUE,否则传回FALSE,于是PeekMessage可一窃取消息,但要记住,此函数是不会删除WM_PAINT消息的。
GetMessage则不一样,他不能返回直到从程序的消息队列中取得消息。
这使得我们可以改写普通的消息循环。我们可以将如下所示的循环:
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
替换为下面的循环:
while (TRUE)
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break ;
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
} else
{
// 完成某些工作的其它行程序
}
}
return msg.wParam ;
/**************************************************/
建立和绘制剪裁区域
剪裁区域是对显示器伤的一个范围的描述,这个区域是矩形,多边形和椭圆的集合,剪裁区域是GDI对象,使用完后应该呼叫DeleteObject来删除对象。
有两种方法建立矩形剪裁区域:hRgn = CreateRectRgn(xleft,ytop,xright,ybottom)或者hRgn = CreateRectRgn(&rect);同理我们可以建立椭圆形和多边形的剪裁区域 hRgn = CreatePolygonRgn(&point,iCount,iPolyFillMode);
合并剪裁区域:CombineRgn
iRgnType = CombineRgn(hDestRgn,hSrcRgn1,hSrcRgn2,iCombine);
其中第四个参数指示两区域是怎样合并:RGN_AND RGN_OR RGN_XOR RGN_DIFF RGN_COPY
还有对剪裁区域作用的几个绘图函数:
FillRgn(hdc,hRgn,hBrush);
FrameRgn(hdc,hRgn,xFrame,yFrame);
InvertRgn(hdc,hRgn);
PaintRgn(hdc,hRgn);
我们可以使用InvalidateRgn(hwnd,hRgn,bErase)和ValidateRgn(hwnd,hRgn)来使区域有效或无效。