Udostępnij przez


Używanie pędzli

Możesz użyć pędzla do malowania wnętrza praktycznie dowolnego kształtu za pomocą funkcji interfejsu urządzenia graficznego (GDI). Obejmuje to wnętrza prostokątów, elips, wielokątów i ścieżek. W zależności od wymagań aplikacji można użyć solidnego pędzla o określonym kolorze, szczotki stockowej, szczotki kreskowej lub szczotki do deseń.

Ta sekcja zawiera przykłady kodu, które pokazują tworzenie niestandardowego okna dialogowego pędzla. Okno dialogowe zawiera siatkę reprezentującą mapę bitową, której systemu używa jako pędzla. Użytkownik może użyć tej siatki do utworzenia mapy bitowej pędzla wzoru, a następnie wyświetlić niestandardowy wzorzec, klikając przycisk Wzorzec testu.

Poniższa ilustracja przedstawia wzorzec utworzony przy użyciu okna dialogowego niestandardowego pędzla.

zrzut ekranu okna dialogowego pędzla niestandardowego

Aby wyświetlić okno dialogowe, należy najpierw utworzyć szablon okna dialogowego. Poniższy szablon okna dialogowego definiuje okno dialogowe niestandardowego pędzla.

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 

Okno dialogowe niestandardowego pędzla zawiera pięć kontrolek: okno siatki mapy bitowej, okno podglądu wzorców i trzy przyciski oznaczone jako Wzorzec testu, OKi Anuluj. Przycisk Test Pattern umożliwia użytkownikowi wyświetlanie wzorca. Szablon okna dialogowego określa ogólne wymiary okna dialogowego, przypisuje wartość do każdej kontrolki, określa lokalizację każdej kontrolki itd. Aby uzyskać więcej informacji, zobacz okna dialogowe .

Wartości kontrolek w szablonie okna dialogowego są stałymi, które zostały zdefiniowane w następujący sposób w pliku nagłówkowym aplikacji.

#define IDD_GRID      120 
#define IDD_RECT      121 
#define IDD_PAINTRECT 122 
#define IDD_OK        123 
#define IDD_CANCEL    124 

Po utworzeniu szablonu okna dialogowego i dołączeniu go do pliku definicji zasobów aplikacji należy napisać procedurę okna dialogowego. Ta procedura przetwarza komunikaty wysyłane przez system do okna dialogowego. Poniższy fragment kodu źródłowego aplikacji przedstawia procedurę dla okna dialogowego niestandardowego pędzla oraz dwie funkcje zdefiniowane przez aplikację, które ono wywołuje.

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; 
} 

Procedura okna dialogowego dla okna dialogowego Niestandardowy Pędzel przetwarza cztery komunikaty, zgodnie z opisem w poniższej tabeli.

Komunikat Akcja
WM_INITDIALOG Pobiera uchwyt i wymiary okna dla kontrolek okna siatki i kontrolek pędzla wzorcowego, oblicza wymiary pojedynczej komórki w kontrolce okna siatki i inicjuje tablicę współrzędnych komórek siatki.
WM_PAINT Rysuje wzorzec siatki w kontrolce okna siatki.
WM_LBUTTONDOWN Określa, czy kursor znajduje się w kontrolce okna siatki, gdy użytkownik naciska lewy przycisk myszy. Jeśli tak, procedura okna dialogowego odwraca odpowiednią komórkę siatki i rejestruje stan tej komórki w tablicy bitów używanych do tworzenia mapy bitowej dla pędzla niestandardowego.
WM_COMMAND Przetwarza dane wejściowe dla trzech przycisków sterujących. Jeśli użytkownik kliknie przycisk Wzorzec testu, procedura w oknie dialogowym pomaluje kontrolkę Wzorzec testu używając nowego niestandardowego wzorca pędzla. Jeśli użytkownik kliknie przycisk OK lub Przycisk Anuluj, procedura okna dialogowego wykonuje odpowiednie akcje.

 

Aby uzyskać więcej informacji na temat komunikatów i przetwarzania komunikatów, zobacz Komunikaty i kolejki komunikatów.

Po zapisaniu procedury okna dialogowego dołącz definicję funkcji dla procedury w pliku nagłówkowym aplikacji, a następnie wywołaj procedurę okna dialogowego w odpowiednim punkcie w aplikacji.

Poniższy fragment pliku nagłówka aplikacji przedstawia definicję funkcji dla procedury okna dialogowego i dwie wywoływane przez nią funkcje.

BOOL CALLBACK BrushDlgProc(HWND, UINT, WPARAM, LPARAM); 
int GetStrLngth(LPTSTR); 
DWORD RetrieveWidth(LPTSTR, int); 

Na koniec poniższy kod pokazuje, jak procedura okna dialogowego jest wywoływana z pliku kodu źródłowego aplikacji.

    DialogBox((HANDLE)GetModuleHandle(NULL), 
        (LPTSTR)"CustBrush", 
        hWnd, 
        (DLGPROC) BrushDlgProc); 

To wywołanie jest zwykle wykonywane w odpowiedzi na użytkownika wybierającego opcję z menu aplikacji.