来源是VS2010的MSDN。
通过图形设备接口函数(GDI),我们可以使用画刷去画填充任何一种图形,包括矩形,椭圆,多边形,路径等。根据程序的要求,可以使用一个特定颜色的Solid Brush,Stock Brush,Hatch Brush,或者格式刷(Pattern Brush)。
这篇内容包含一个典型的创建画刷对话框的代码实现。该对话框里面有一个网格,它表示系统用作Brush的位图。使用者能够使用这个网格去创建一个格式刷形式的位图,并且点击"Test Pattern"按钮就能看到效果。
下面就展示一个使用Custom Brush对话框创建的格式刷。
为了显示一个Dialog Box,必须首先创建一个Dialog Box模板。下面定义了一个Custom Brush Dialog Box。
CustBrush DIALOG 6, 18, 160, 118
STYLE WS_DLGFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Custom Brush"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "", IDD_GRID, "Static", SS_BLACKFRAME |
WS_CHILD, 3, 2, 83, 79
CONTROL "", IDD_RECT, "Static", SS_BLACKFRAME |
WS_CHILD, 96, 11, 57, 28
PUSHBUTTON "Test Pattern", IDD_PAINTRECT, 96, 47, 57, 14
PUSHBUTTON "OK", IDD_OK, 29, 98, 40, 14
PUSHBUTTON "Cancel", IDD_CANCEL, 92, 98, 40, 14
END
Custom Brush dialog box包含五种控制:位图网格窗,模式显示窗,三个按钮(分别表示Test Pattern,OK, and Cancel)。这个模板确定了dialog box window的总维数,给每个control都赋了值,安排好每个control的位置等等。
每个control的值都在头文件中被定义:
#define IDD_GRID 120
#define IDD_RECT 121
#define IDD_PAINTRECT 122
#define IDD_OK 123
#define IDD_CANCEL 124
创建好dialog box模板之后,把它包含在应用程序资源定义的文件中,然后就要写对话框的处理过程。它里面会处理系统发送给dialog box的消息,下面是关于 Custom Brush dialog box的一段源码:
dialog box处理的四种消息介绍如下:BOOL CALLBACK BrushDlgProc( HWND hdlg, UINT message, LONG wParam, LONG lParam) { static HWND hwndGrid; // grid-window control static HWND hwndBrush; // pattern-brush control static RECT rctGrid; // grid-window rectangle static RECT rctBrush; // pattern-brush rectangle static UINT bBrushBits[8]; // bitmap bits static RECT rect[64]; // grid-cell array static HBITMAP hbm; // bitmap handle HBRUSH hbrush; // current brush HBRUSH hbrushOld; // default brush HRGN hrgnCell; // test-region handle HDC hdc; // device context (DC) handle int x, y, deltaX, deltaY; // drawing coordinates POINTS ptlHit; // mouse coordinates int i; // count variable switch (message) { case WM_INITDIALOG: // Retrieve a window handle for the grid-window and // pattern-brush controls. hwndGrid = GetDlgItem(hdlg, IDD_GRID); hwndBrush = GetDlgItem(hdlg, IDD_RECT); // Initialize the array of bits that defines the // custom brush pattern with the value 1 to produce a // solid white brush. for (i=0; i<8; i++) bBrushBits[i] = 0xFF; // Retrieve dimensions for the grid-window and pattern- // brush controls. GetClientRect(hwndGrid, &rctGrid); GetClientRect(hwndBrush, &rctBrush); // Determine the width and height of a single cell. deltaX = (rctGrid.right - rctGrid.left)/8; deltaY = (rctGrid.bottom - rctGrid.top)/8; // Initialize the array of cell rectangles. for (y=rctGrid.top, i=0; y < rctGrid.bottom; y += deltaY) { for(x=rctGrid.left; x < (rctGrid.right - 8) && i < 64; x += deltaX, i++) { rect[i].left = x; rect[i].top = y; rect[i].right = x + deltaX; rect[i].bottom = y + deltaY; } } return FALSE; case WM_PAINT: // Draw the grid. hdc = GetDC(hwndGrid); for (i=rctGrid.left; i<rctGrid.right; i+=(rctGrid.right - rctGrid.left)/8) { MoveToEx(hdc, i, rctGrid.top, NULL); LineTo(hdc, i, rctGrid.bottom); } for (i=rctGrid.top; i<rctGrid.bottom; i+=(rctGrid.bottom - rctGrid.top)/8) { MoveToEx(hdc, rctGrid.left, i, NULL); LineTo(hdc, rctGrid.right, i); } ReleaseDC(hwndGrid, hdc); return FALSE; case WM_LBUTTONDOWN: // Store the mouse coordinates in a POINT structure. ptlHit = MAKEPOINTS((POINTS FAR *)lParam); // Create a rectangular region with dimensions and // coordinates that correspond to those of the grid // window. hrgnCell = CreateRectRgn(rctGrid.left, rctGrid.top, rctGrid.right, rctGrid.bottom); // Retrieve a window DC for the grid window. hdc = GetDC(hwndGrid); // Select the region into the DC. SelectObject(hdc, hrgnCell); // Test for a button click in the grid-window rectangle. if (PtInRegion(hrgnCell, ptlHit.x, ptlHit.y)) { // A button click occurred in the grid-window // rectangle; isolate the cell in which it occurred. for(i=0; i<64; i++) { DeleteObject(hrgnCell); hrgnCell = CreateRectRgn(rect[i].left, rect[i].top, rect[i].right, rect[i].bottom); if (PtInRegion(hrgnCell, ptlHit.x, ptlHit.y)) { InvertRgn(hdc, hrgnCell); // Set the appropriate brush bits. if (i % 8 == 0) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x80; else if (i % 8 == 1) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x40; else if (i % 8 == 2) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x20; else if (i % 8 == 3) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x10; else if (i % 8 == 4) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x08; else if (i % 8 == 5) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x04; else if (i % 8 == 6) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x02; else if (i % 8 == 7) bBrushBits[i/8] = bBrushBits[i/8] ^ 0x01; // Exit the "for" loop after the bit is set. break; } // end if } // end for } // end if // Release the DC for the control. ReleaseDC(hwndGrid, hdc); return TRUE; case WM_COMMAND: switch (wParam) { case IDD_PAINTRECT: hdc = GetDC(hwndBrush); // Create a monochrome bitmap. hbm = CreateBitmap(8, 8, 1, 1, (LPBYTE)bBrushBits); // Select the custom brush into the DC. hbrush = CreatePatternBrush(hbm); hbrushOld = SelectObject(hdc, hbrush); // Use the custom brush to fill the rectangle. Rectangle(hdc, rctBrush.left, rctBrush.top, rctBrush.right, rctBrush.bottom); // Clean up memory. SelectObject(hdc, hbrushOld); DeleteObject(hbrush); DeleteObject(hbm); ReleaseDC(hwndBrush, hdc); return TRUE; case IDD_OK: case IDD_CANCEL: EndDialog(hdlg, TRUE); return TRUE; } // end switch break; default: return FALSE; } } int GetStrLngth(LPTSTR cArray) { int i = 0; while (cArray[i++] != 0); return i-1; } DWORD RetrieveWidth(LPTSTR cArray, int iLength) { int i, iTmp; double dVal, dCount; dVal = 0.0; dCount = (double)(iLength-1); for (i=0; i<iLength; i++) { iTmp = cArray[i] - 0x30; dVal = dVal + (((double)iTmp) * pow(10.0, dCount--)); } return (DWORD)dVal; }
Message | Action |
---|---|
WM_INITDIALOG | Retrieves a window handle and dimensions for the grid-window and pattern-brush controls, computes the dimensions of a single cell in the grid-window control, and initializes an array of grid-cell coordinates. |
WM_PAINT | Draws the grid pattern in the grid-window control. |
WM_LBUTTONDOWN | Determines whether the cursor is within the grid-window control when the user presses the left mouse button. If so, the dialog box procedure inverts the appropriate grid cell and records the state of that cell in an array of bits that is used to create the bitmap for the custom brush. |
WM_COMMAND | Processes input for the three push button controls. If the user clicks the Test Pattern button, the dialog box procedure paints the Test Pattern control with the new custom brush pattern. If the user clicks theOK or Cancel button, the dialog box procedure performs actions accordingly. |