Использование кистей


Вы можете использовать кисть, чтобы окрасить внутреннюю часть фактически любой формы, используя  функции графических устройств (GDI). Это включает внутренние части прямоугольников, эллипсов, многоугольников и путей. В зависимости от требований вашего приложения, Вы можете использовать сплошную кисть заданного цвета, стандартную, штриховую или узорную кисти.

Этот раздел содержит примеры кода, которые демонстрируют создание диалогового окна изготовленной кисти. Диалоговое окно содержит сетку, которая представляет точечный рисунок используемый  системой как кисть. Пользователь может использовать эту сетку, чтобы создать точечный рисунок узорной кисти, а затем просмотреть изготовленный узор, щелкая по кнопке Проверка узора (Test Pattern).

Нижеследующая иллюстрация показывает узор, созданный при помощи использования диалогового окна Изготовленная кисть (Custom Brush).

Custom brush dialog box

Чтобы показать на экране диалоговое окно, Вы должны сначала создать шаблон диалогового окна. Нижеследующий шаблон диалогового окна определяет диалоговое окно Custom Brush (Изготовленная кисть).

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 (Изготовленная кисть) содержит пять органов управления: окно растровой сетки, окно просмотра узора и три командные кнопки, помеченные как Test Pattern (Проверка узора), OK и Отмена (Cancel). Кнопка команды  Test Pattern (Проверка узора) дает возможность пользователю рассмотреть узор. Шаблон диалогового окна задает полные размеры диалогового окна, назначает величину каждого органа управления, устанавливает местоположение каждого элемента управления и т.д. Для получения дополнительной информации, см.  тему Диалоговые окна.

Значения органов управления в шаблоне диалогового окна - это константы, которые определяются как ниже указано в заголовочном файле приложения.

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

После того, как Вы создадите шаблон диалогового окна и включите его в файл определения ресурса приложения, Вы должны записать процедуру диалогового окна. Эта процедура обрабатывает сообщения, которые система отправляет в диалоговое окно. Нижеследующий фрагмент из исходного кода прикладной программы показывает процедуру для диалогового окна Custom Brush (Изготовленная кисть) и двух определяемых программой функций, которые она вызывает.

BOOL CALLBACK BrushDlgProc( HWND hdlg, UINT message, LONG wParam, 
                            LONG lParam) 
{ 
    static HWND hwndGrid;       // орган управления окном с сеткой 
    static HWND hwndBrush;      // орган управления узорной кистью 
    static RECT rctGrid;        // прямоугольник окна с сеткой 
    static RECT rctBrush;       // прямоугольник узорной кисти 
    static UINT bBrushBits[8];  // биты точечного рисунка
    static RECT rect[64];       // массив ячеек сетки 
    static HBITMAP hbm;         // дескриптор точечного рисунка 
    HBRUSH hbrush;              // текущая кисть 
    HBRUSH hbrushOld;           // заданная по умолчанию кисть 
    HRGN hrgnCell;              // дескриптор участка проверки 
    HDC hdc;                    // дескриптор контекста устройства (DC) 
    int x, y, deltaX, deltaY;   // координаты рисования 
    POINTS ptlHit;              // координаты мыши 
    int i;                      // переменная счета 
 
    switch (message) 
        { 
        case WM_INITDIALOG: 
 
            // Извлечем дескрипторы органов управления окна с сеткой и 
            // узорной кисти. 
 
            hwndGrid = GetDlgItem(hdlg, IDD_GRID); 
            hwndBrush = GetDlgItem(hdlg, IDD_RECT); 
 
            // Инициализируем массив битов,который определяет 
            // узор изготовляемой кисти значением 1, чтобы изготовить 
            // сплошную белую кисть. 

            for (i=0; i<8; i++) 
                bBrushBits[i] = 0xFF; 
 
            // Извлечем размеры органов управления окна с сеткой и 
            // узорной кисти. 
 
            GetClientRect(hwndGrid, &rctGrid); 
            GetClientRect(hwndBrush, &rctBrush); 
 
            // Определим ширину и высоту отдельной ячейки. 
 
            deltaX = (rctGrid.right - rctGrid.left)/8; 
            deltaY = (rctGrid.bottom - rctGrid.top)/8; 
 
            // Инициализируем массив прямоугольников ячеек. 
 
            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: 

            // Рисуем сетку. 
 
            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: 
 
            // Сохраним координаты мыши в структуре POINT. 
 
            ptlHit = MAKEPOINTS((POINTS FAR *)lParam); 
 
            // Создадим прямоугольный участок с размерами и 
            // координатами, которые соответствуют этому окну 
            // сетки. 
 
            hrgnCell = CreateRectRgn(rctGrid.left, rctGrid.top, 
                        rctGrid.right, rctGrid.bottom); 
 
            // Извлечем дескриптор для окна сетки. 
 
            hdc = GetDC(hwndGrid); 
 
            // Выберем участок в DC. 
 
            SelectObject(hdc, hrgnCell); 
 
            // Проверим был ли щелчок в клетке сетки. 
 
            if (PtInRegion(hrgnCell, ptlHit.x, ptlHit.y))
            { 
                // В клетке окна с сеткой произошел щелчок кнопки; 
                // выделим ячеку, в которой это произошло. 
 
                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); 
 
                        // Установим соответствующие биты кисти. 
 
                         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; 
 
                      // После установки битов выйдем из цикла "for". 
 
                         break; 
                    } // конец if 
 
                } // конец for 
 
            } // конец if 
 
            // Освободим DC органа управления. 
 
            ReleaseDC(hwndGrid, hdc); 
            return TRUE; 
 
 
        case WM_COMMAND: 
            switch (wParam)
            { 
               case IDD_PAINTRECT: 
 
                    hdc = GetDC(hwndBrush); 
 
                    // Создадим монохромный точечный рисунок. 
 
                    hbm = CreateBitmap(8, 8, 1, 1, 
                          (LPBYTE)bBrushBits); 
 
                    // Выберем изготовленную кисть в DC. 
 
                    hbrush = CreatePatternBrush(hbm); 
 
                    hbrushOld = SelectObject(hdc, hbrush); 
 
                    // Используем изготовленную кисть для закрашивания прямоугольника. 
 
                    Rectangle(hdc, rctBrush.left, rctBrush.top, 
                              rctBrush.right, rctBrush.bottom); 
 
                    // Очистим память. 
                    SelectObject(hdc, hbrushOld); 
                    DeleteObject(hbrush); 
                    DeleteObject(hbm); 
 
                    ReleaseDC(hwndBrush, hdc); 
                    return TRUE; 
 
                case IDD_OK: 
 
                case IDD_CANCEL: 
                    EndDialog(hdlg, TRUE); 
                    return TRUE; 
 
            } // конец 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; 
} 

Процедура диалогового окна  Custom Brush (Изготовленная кисть) обрабатывает четыре сообщения, как описано в следующей ниже таблице.

Сообщение Действие
WM_INITDIALOG Извлекает дескриптор и размеры органов управления окна с сеткой и  узорной кисти, вычисляет размеры отдельной ячейки в органе управления окна с сеткой и инициализирует массив координат ячеек сетки.
WM_PAINT Рисует шаблон сетки в органе управления окна с сеткой.
WM_LBUTTONDOWN Выясняет, находится ли курсор внутри органа управления окна с сеткой, когда пользователь нажимает левую кнопку мыши. Если это так, процедура диалогового окна инвертирует соответствующую ячейку сетки и фиксирует состояние этой ячейки в массиве битов, который используется, чтобы создать точечный рисунок для изготавливаемой кисти.
WM_COMMAND Обрабатывает вводимые данные от трех командных кнопок органов управления. Если пользователь щелкает по кнопке Test Pattern (Проверка узора), процедура диалогового окна окрашивает это окно новым изготовленным узором кисти. Если пользователь щелкает по кнопке OK или Отменить (Cancel), процедура диалогового окна выполняет соответствующие действия.
 

Для получения дополнительной информации о сообщениях и их обработке, см. раздел Сообщения и  очереди сообщений.

После того, как Вы запишите процедуру диалогового окна, включите определение функции для процедуры в заголовочный файл приложения, а затем вызываете процедуру диалогового окна в соответствующем пункте в прикладной программе.

Нижеследующий фрагмент из заголовочного файла приложения показывает определение функции для процедуры диалогового окна и двух функций, которые она вызывает.

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

Наконец, нижеследующий код показывает, как процедура диалогового окна вызывается из файла исходного кода прикладной программы.

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

Этот вызов обычно делается в ответ на выбор пользователем пункта из меню приложения.

 

Назад в оглавление темы
На главную страницу темы

Hosted by uCoz