这一节主要是书商设备内容的第二部分,地址在这里:http://www.ai86.cn/book/windows_programming/5.htm#205002
设备内容里面包含了很多写字、画画使用的属性,这些如果不指定直接都是可以用的,那么就是默认值了。但是,如果被改变了,这些属性会在释放设备句柄时失去。所以记得随改随用,在释放前用了。具体拥有的属性在下面这个表里面有:
设备内容属性 | 默认值 | 修改该值的函数 | 取得该值的函数 |
Mapping Mode | MM_TEXT | SetMapMode | GetMapMode |
Window Origin | (0, 0) | SetWindowOrgEx OffsetWindowOrgEx | GetWindowOrgEx |
Viewport Origin | (0, 0) | SetViewportOrgEx OffsetViewportOrgEx | GetViewportOrgEx |
Window Extents | (1, 1) | SetWindowExtEx SetMapMode ScaleWindowExtEx | GetWindowExtEx |
Viewport Extents | (1, 1) | SetViewportExtEx SetMapMode ScaleViewportExtEx | GetViewportExtEx |
Pen | BLACK_PEN | SelectObject | SelectObject |
Brush | WHITE_BRUSH | SelectObject | SelectObject |
Font | SYSTEM_FONT | SelectObject | SelectObject |
Bitmap | None | SelectObject | SelectObject |
Current Position | (0, 0) | MoveToEx LineTo PolylineTo PolyBezierTo | GetCurrentPositionEx |
Background Mode | OPAQUE | SetBkMode | GetBkMode |
Background Color | White | SetBkColor | GetBkColor |
Text Color | Black | SetTextColor | GetTextColor |
Drawing Mode | R2_COPYPEN | SetROP2 | GetROP2 |
Stretching Mode | BLACKONWHITE | SetStretchBltMode | GetStretchBltMode |
Polygon Fill Mode | ALTERNATE | SetPolyFillMode | GetPolyFillMode |
Intercharacter Spacing | 0 | SetTextCharacterExtra | GetTextCharacterExtra |
Brush Origin | (0, 0) | SetBrushOrgEx | GetBrushOrgEx |
Clipping Region | None | SelectObject SelectClipRgn IntersectClipRgn OffsetClipRgn ExcludeClipRect SelectClipPath | GetClipBox |
保存设备内容
通常,在您呼叫GetDC或BeginPaint时,Windows用默认值建立一个新的设备内容,您对属性所做的一切改变在设备内容用ReleaseDC或EndPaint呼叫释放时,都会丢失。如果您的程序需要使用非内定的设备内容属性,则您必须在每次取得设备内容句柄时初始化设备内容:
hdc = BeginPaint (hwnd, & ps) ;
// 设备内容属性
// 绘制窗口显示区域
EndPaint (hwnd, & ps) ;
return 0 ;
虽然在通常情况下这种方法已经很令人满意了,但是您还可能想要在释放设备内容之后,仍然保存程序中对设备内容属性所做的改变,以便在下一次呼叫GetDC和BeginPaint时它们仍然能够起作用。为此,可在登录窗口类别时,将CS_OWNDC旗标纳入窗口类别的一部分:
现在,依据这个窗口类别所建立的每个窗口都将拥有自己的设备内容,它一直存在,直到窗口被删除。如果使用了CS_OWNDC风格,就只需初始化设备内容一次,可以在处理WM_CREATE消息处理期间完成这一操作:
hdc = GetDC (hwnd) ;
// 初始化设备内容属性
ReleaseDC (hwnd, hdc) ;
这些属性在改变之前一直有效。
CS_OWNDC风格只影响GetDC和BeginPaint获得的设备内容,不影响其它函数(如GetWindowDC)获得的设备内容。以前不提倡使用CS_OWNDC风格,因为它需要内存;现在,在处理大量图形的Windows NT应用程序中,它可以提高性能。即使用了CS_OWNDC,您仍然应该在退出窗口消息处理程序之前释放设备内容。
某些情况下,您可能想改变某些设备内容属性,用改变后的属性进行绘图,然后恢复原来的设备内容。要简化这一过程,可以通过如下呼叫来保存设备内容的状态:
idSaved = SaveDC (hdc) ;
现在,可以改变一些属性,在想要回到呼叫SaveDC前存在的设备内容时,呼叫:
RestoreDC (hdc, idSaved) ;
您可以在呼叫RestoreDC之前呼叫SaveDC数次。
大多数程序写作者以不同的方式使用SaveDC和RestoreDC。然而,更像汇编语言中的PUSH和POP指令,当您呼叫SaveDC时,不需要保存传回值:
SaveDC (hdc) ;
然后,您可以更改某些属性并再次呼叫SaveDC。要将设备内容恢复到一个已经保存的状态,呼叫:
RestoreDC (hdc, - 1 ) ;
这就将设备内容恢复到最近由SaveDC函数保存的状态中。
设置画笔(后面的内容文章本身写的就很简单了,没有什么写的必要了,就把关键的留下来吧)
①使用标准画笔:
BLACK_PEN是Windows提供的三种现有画笔之一,其它两种是WHITE_PEN和NULL_PEN,NULL_PEN什么都不画。您也可以自己自订画笔。
Windows程序以句柄来使用画笔。
HPEN hPen ;
呼叫GetStockObject,可以获得现有画笔的句柄。例如,假设您想使用名为WHITE_PEN的现有画笔,可以如下取得画笔的句柄:
hPen = GetStockObject (WHITE_PEN) ;
现在必须将画笔选进设备内容:
SelectObject (hdc, hPen) ;
目前的画笔是白色。在这个呼叫后,您画的线将使用WHITE_PEN,直到您将另外一个画笔选进设备内容或者释放设备内容句柄为止。
您也可以不定义hPen变量,而将GetStockObject和SelectObject呼叫合并成一个叙述:
SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
如果想恢复到使用BLACK_PEN的状态,可以用一个叙述取得这种画笔的句柄,并将其选进设备内容:
SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
SelectObject的传回值是此呼叫前设备内容中的画笔句柄。如果启动一个新的设备内容并呼叫
hPen = SelectObject (hdc, GetStockobject (WHITE_PEN)) ;
则设备内容中的目前画笔将为WHITE_PEN,变量hPen将会是BLACK_PEN的句柄。以后通过呼叫
SelectObject (hdc, hPen) ;
就能够将BLACK_PEN选进设备内容。
②自定义画笔
在使用画笔等GDI对象时,应该遵守以下三条规则:
- 最后要删除自己建立的所有GDI对象。
- 当GDI对象正在一个有效的设备内容中使用时,不要删除它。
- 不要删除现有对象。
这些规则当然是有道理的,而且有时这道理还挺微妙的。下面我们将举些例子来帮助理解这些规则。
CreatePen函数的语法形如:
hPen = CreatePen (iPenStyle, iWidth, crColor) ;
七种画笔样式 |
SetBkColor (hdc, crColor) ;
与画笔色彩所使用的crColor参数一样,Windows将这里的背景色转换为纯色。可以通过用GetBkColor来取得设备内容中定义的目前背景色。
通过将背景模式转换为TRANSPARENT,可以阻止Windows填入空隙:
SetBkMode (hdc, TRANSPARENT) ;
可以通过以下呼叫在设备内容中设定新的绘图模式:
SetROP2 (hdc, iDrawMode) ;
各种绘图模式如下表:
画笔(P):目标(D): | 1 1 | 1 0 | 0 1 | 0 0 | 布尔操作 | 绘图模式 |
结果: | 0 | 0 | 0 | 0 | 0 | R2_BLACK |
0 | 0 | 0 | 1 | ~(P | D) | R2_NOTMERGEPEN | |
0 | 0 | 1 | 0 | ~P & D | R2_MASKNOTPEN | |
0 | 0 | 1 | 1 | ~P | R2_NOTCOPYPEN | |
0 | 1 | 0 | 0 | P & ~D | R2_MASKPENNOT | |
0 | 1 | 0 | 1 | ~D | R2_NOT | |
0 | 1 | 1 | 0 | P ^ D | R2_XORPEN | |
0 | 1 | 1 | 1 | ~(P & D) | R2_NOTMASKPEN | |
1 | 0 | 0 | 0 | P & D | R2_MASKPEN | |
1 | 0 | 0 | 1 | ~(P ^ D) | R2_NOTXORPEN | |
1 | 0 | 1 | 0 | D | R2_NOP | |
1 | 0 | 1 | 1 | ~P | D | R2_MERGENOTPEN | |
1 | 1 | 0 | 0 | P | R2_COPYPEN(内定) | |
1 | 1 | 0 | 1 | P | ~D | R2_MERGEPENNOT | |
1 | 1 | 1 | 0 | P | D | R2_MERGEPEN | |
1 | 1 | 1 | 1 | 1 | R2_WHITE |
③画刷
画刷决定了一个填充区域(比入说一个正方形的中间)的样式:
您可以用HBRUSH hBrush ;
hBrush = GetStockObject (GRAY_BRUSH) ;
SelectObject (hdc, hBrush) ;
来使用包含如下6个的系统画刷:WHITE_BRUSH、LTGRAY_BRUSH、GRAY_BRUSH、DKGRAY_BRUSH、BLACK_BRUSH和NULL_BRUSH
也可以自定义:
HBRUSH CreateSolidBrush(
COLORREF crColor // brush color value
);
或者更改一下样式:
hBrush = CreateHatchBrush (iHatchStyle, crColor) ;