建立和绘制区域
一个区域是对显示器一块空间的描叙,这个空间可以是矩形,多边形和椭圆的组合。
可以使用区域进行绘图或者剪裁。将区域选入设备环境,就可以使用这个区域来剪裁(也就是说,将绘制动作限制在客户区的一个特定部分)。同画笔和画刷一样,区域也是 GDI 对象,应当通过调用 DeleteObject() 拉力删除所建立的区域。
当建立一个区域时,Windows 返回一个类型为 HRGN 的区域句柄。最简单的区域类型是一个矩形。
建立一个矩形区域:
hRgn = CreateRectRgn(xLeft, yTop, xRight, yBottom) ; 或者 hRgn = CreateRectRgn(&rect) ;
返回值:如果函数成功,返回该区域的句柄。如果函数失败,返回NULL。
建立椭圆区域:
hRgn = CreateEllipticRgn(xLeft, yTop, xRight, yBottom) ; 或者 hRgn = CreateEllipticRgnIndirect(&rect) ;
返回值:如果函数成功,返回该区域的句柄。如果函数失败,返回NULL。
建立圆角矩形区域:
hRgn = CreateRoundRectRgn(xLeft, yTop, xRight, yBottom, Width, Height) ;
一旦有了一个区域的句柄,就可以使用下面四个绘图函数了:
FrameRgn(hdc, hRgn, hBrush,Width, Height) ;
功能:用 指定刷子 围绕 指定区域 画一个外框。
返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。
FillRgn(hdc, hRgn, hBrush) ;
功能:用 指定刷子 填充 指定区域。
返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。
InvertRgn(hdc, hRgn) ;
功能:翻转 指定区域 内所有的像素,将 1 变为 0,0 变为 1。(例:最直观的颠倒黑白...等等)。
返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。
PaintRgn(hdc, hRgn) ;
功能:使用当前被选入设备环境的画刷填充区域。
返回值:如果函数调用成功,返回值非零;如果函数调用失败,返回值是0。
用完一个区域后,可以用与删除其他 GDI 对象相同的函数来删除它:
DeleteObject(hRgn) ;
区域与区域的剪裁:
区域在剪裁中扮演者重要角色。InvalidRect() 使显示的矩形区域无效,并产生一个 WW_PAINT 消息。
可以通过调用 GetUpdateRect() 获取无效矩形的坐标,并且使用 ValidateRect() 使客户区的矩形有效.
类似的有:InvalidateRgn() 和 ValidateRgn()。
可以通过将一个区域选入到设备环境来创建自己的剪裁区域,将区域选入设备环境可以使用
SelectObject(hdc, hRgn) ; 或 SelectClipRgn(hdc, hRgn) ;
还有几个操纵剪裁区域的函数,例如 ExcludeClipRect() 用来从剪裁区域中去除一个矩形;
InterSectClipRect() 用来建立一个新的剪裁区域,这个新的剪裁区域是先前的剪裁区域和某个矩形的交集;
OffsetClipRgn() 用来把一个剪裁区域移动到客户区的另外一部分。
InvalidateRect(hWnd, &rect, BOOL) ;
功能:该函数向指定的窗体更新区域添加一个矩形,然后窗口客户区域的这一部分将被重新绘制。
参数:如果第一个参数为 NULL,则系统将在函数返回前重新绘制所有的窗口,
然后发送 WM_ERASEBKGND 和 WM_PAINT 给窗口过程处理函数。
如果第二个参数为 NULL,全部的窗口客户区域将被增加到更新区域中。
第三个参数是 BOOL 型变量。指出无效矩形被标记为有效后,是否重画该区域。
返回值:函数成功则返回非零值,否则返回零值。
GetupdateRect(hWnd, &rect, BOOL) ;
功能:获取完全封闭更新区域的最小矩形的坐标。
参数:BOOL 型变量。指定更新区域中的背景是否要被擦除。
返回值:如果更新区域不为空,则返回值为非零值;否则为0。
ValidateRect(hWnd, &rect) ;
功能:该函数更新指定窗口的无效矩形区域,使之有效。
返回值:函数成功则返回非零值,否则返回零值。
InvalidateRgn(hWnd, hRgn, BOOL) ;
功能:通过添加一个区域到一个窗口的更新区域中来使指定矩形的客户区域无效;
这个无效的区域和所有更新区域中的其他区域将被标记用来在下一个WM_PAINT消息发生的时候描绘。
参数:BOOL 型变量:说明当更新区域被处理的时候更新区域内的背景是否要擦除。
返回值:返回值总是 0。
ValidateRgn(hWnd, hRgn) ;
功能:激活窗口中指定区域,把它从刷新区移走。
返回值:函数成功则返回非零值,否则返回零值。
ExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom) ;
功能:函数的功能是创建一个新的剪切区域,该区域由一个现存的剪切区域减去一个特定的矩形区域而构成。
返回值:该返回值表明了新的剪切区域的复杂度,它可是如下几种形式:(int 型)
功能:该函数创建了一个新的剪切区域,该区域是当前剪切区域和一个特定矩形的交集。
CLOVER 程序:
#include <windows.h> #include <math.h> #define TWO_PI (2.0 * 3.14159) LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("Clover") ; HWND hwnd ; MSG msg ; WNDCLASS wndclass ; wndclass.style = CS_HREDRAW | CS_VREDRAW ; wndclass.lpfnWndProc = WndProc ; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ; wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName = szAppName ; if (!RegisterClass (&wndclass)) { MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; return 0 ; } hwnd = CreateWindow (szAppName, TEXT ("Draw a Clover"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL) ; ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ; while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg) ; DispatchMessage (&msg) ; } return msg.wParam ; } LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) { static HRGN hRgnClip ; static int cxClient, cyClient ; double fAngle, fRadius ; HCURSOR hCursor ; HDC hdc ; HRGN hRgnTemp[6] ; int i ; PAINTSTRUCT ps ; switch (iMsg) { case WM_SIZE: cxClient = LOWORD (lParam) ; cyClient = HIWORD (lParam) ; hCursor = SetCursor (LoadCursor (NULL, IDC_WAIT)) ; ShowCursor (TRUE) ; if (hRgnClip) DeleteObject (hRgnClip) ; hRgnTemp[0] = CreateEllipticRgn (0, cyClient / 3, cxClient / 2, 2 * cyClient / 3) ; hRgnTemp[1] = CreateEllipticRgn (cxClient / 2, cyClient / 3, cxClient, 2 * cyClient / 3) ; hRgnTemp[2] = CreateEllipticRgn (cxClient / 3, 0, 2 * cxClient / 3, cyClient / 2) ; hRgnTemp[3] = CreateEllipticRgn (cxClient / 3, cyClient / 2, 2 * cxClient / 3, cyClient) ; hRgnTemp[4] = CreateRectRgn (0, 0, 1, 1) ; hRgnTemp[5] = CreateRectRgn (0, 0, 1, 1) ; hRgnClip = CreateRectRgn (0, 0, 1, 1) ; CombineRgn (hRgnTemp[4], hRgnTemp[0], hRgnTemp[1], RGN_OR) ; CombineRgn (hRgnTemp[5], hRgnTemp[2], hRgnTemp[3], RGN_OR) ; CombineRgn (hRgnClip, hRgnTemp[4], hRgnTemp[5], RGN_XOR) ; for (i = 0 ; i < 6 ; i++) DeleteObject (hRgnTemp[i]) ; SetCursor (hCursor) ; ShowCursor (FALSE) ; return 0 ; case WM_PAINT: hdc = BeginPaint (hwnd, &ps) ; SetViewportOrgEx (hdc, cxClient / 2, cyClient / 2, NULL) ; SelectClipRgn (hdc, hRgnClip) ; fRadius = _hypot (cxClient / 2.0, cyClient / 2.0) ; for (fAngle = 0.0 ; fAngle < TWO_PI ; fAngle += TWO_PI / 360) { MoveToEx (hdc, 0, 0, NULL) ; LineTo (hdc, (int) ( fRadius * cos (fAngle) + 0.5), (int) (-fRadius * sin (fAngle) + 0.5)) ; } EndPaint (hwnd, &ps) ; return 0 ; case WM_DESTROY: DeleteObject (hRgnClip) ; PostQuitMessage (0) ; return 0 ; } return DefWindowProc (hwnd, iMsg, wParam, lParam) ; }

浙公网安备 33010602011771号