Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

373

Рисование в окне диалога

Помимо всего прочего, программа ABOUT2 делает и кое-что необычное: рисует в окне диалога. Давайте разберемся как. Внутри шаблона окна диалога в файле ABOUT2.RC определяется пустое текстовое окно управления с размерами и положением, определяющими область, в которой предполагается рисование:

CTEXT "" IDD_PAINT, 68, 54, 60, 60

Ширина этой области равна 15 символов, а высота 7,5 символов. Поскольку в этом окне управления текста нет, все, что делает оконная процедура класса "static" состоит в обновлении фона при перерисовке дочернего окна управления.

Когда текущий цвет или фигура изменяется, или когда окно диалога получает сообщение WM_PAINT, процедура диалога вызывает функцию PaintTheBlock, вызов которой в программе ABOUT2.С выглядит так:

PaintTheBlock(hCtrlBlock, iColor, iFigure);

Описатель окна hCtrlBlock, являющийся первым параметром функции, был получен при обработке сообщения

WM_INITDIALOG:

hCtrlBlock = GetDlgItem(hDlg, IDD_PAINT);

Далее представлено тело функции PaintTheBlock:

void PaintTheBlock(HWND hCtrl, int iColor, int iFigure)

{

InvalidateRect(hCtrl, NULL, TRUE); UpdateWindow(hCtrl); PaintWindow(hCtrl, iColor, iFigure);

}

Таким образом, функция делает недействительным дочернее окно управления, помечает его как обновленное, а затем вызывает другую функцию программы ABOUT2 с именем PaintWindow.

Функция PaintWindow получает описатель контекста устройства окна hCtrl и рисует выбранную фигуру, закрашивая ее кистью выбранным пользователем цветом. Размер дочернего окна управления получен с помощью функции GetClientRect. Хотя в шаблоне окна диалога размер дочернего окна управления определяется в символах, GetClientRect возвращает размеры в пикселях. Кроме нее, можно использовать функцию MapDialogRect, которая преобразует символьные координаты окна диалога в пиксельные координаты рабочей области.

Фактически, мы рисуем не в рабочей области окна диалога, а в рабочей области дочернего окна элемента управления. Когда бы окно диалога ни получило сообщение WM_PAINT, дочернее окно управления является недействительным, затем обновляется и его рабочая область становится действительной, что позволяет рисовать в нем.

Использование с окном диалога других функций

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

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

EnableWindow(hwndCtrl, bEnable);

делает окно элемента управления доступным, когда параметр bEnable равен TRUE (ненулевое значение) и недоступным, когда bEnable равен FALSE (0). Если окно элемента управления недоступно, то оно не реагирует ни на клавиатуру, ни на мышь. Нельзя делать недоступным окно элемента управления, имеющее фокус ввода.

Определение собственных окон управления

Хотя Windows предлагает массу возможностей для поддержки окна диалога и дочерних окон элементов управления, имеются различные методы, позволяющие вставлять в этот процесс фрагменты собственного кода. Только что рассматривался метод, дающий возможность рисовать в окне диалога. Можно также использовать технику введения новой оконной процедуры (о котором рассказывалось в главе 8) для изменения поведения дочерних окон элементов управления.

Также можно определять собственные дочерние окна элементов управления и использовать их в окне диалога. Например, предположим, что пользователь предпочитает не прямоугольные кнопки, а эллипсоидные. Создать их

374

можно путем регистрации класса окна и использования собственной оконной процедуры для обработки сообщений от такого специального дочернего окна. Затем этот класс окна задается в инструкции CONTROL шаблона окна диалога. Именно это делается в программе ABOUT3, представленной на рис. 11.5.

ABOUT3.MAK

#----------------------

# ABOUT3.MAK make file

#----------------------

about3.exe : about3.obj about3.res

$(LINKER) $(GUIFLAGS) -OUT:about3.exe about3.obj about3.res $(GUILIBS)

about3.obj : about3.c about3.h $(CC) $(CFLAGS) about3.c

about3.res : about3.rc about3.h about3.ico

$(RC) $(RCVARS) about3.rc

ABOUT3.C

/*------------------------------------------

ABOUT3.C -- About Box Demo Program No. 3

(c) Charles Petzold, 1996

------------------------------------------*/

#include <windows.h> #include "about3.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

BOOL CALLBACK AboutDlgProc(HWND, UINT, WPARAM, LPARAM);

LRESULT CALLBACK EllipPushWndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

{

 

static char

szAppName[] = "About3";

MSG

msg;

HWND

hwnd;

WNDCLASSEX

wndclass;

wndclass.cbSize

= sizeof(wndclass);

wndclass.style

= CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc

= WndProc;

wndclass.cbClsExtra

= 0;

wndclass.cbWndExtra

= 0;

wndclass.hInstance

= hInstance;

wndclass.hIcon

= LoadIcon(hInstance, szAppName);

wndclass.hCursor

= LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground

=(HBRUSH) GetStockObject(WHITE_BRUSH);

wndclass.lpszMenuName

= szAppName;

wndclass.lpszClassName

= szAppName;

wndclass.hIconSm

= LoadIcon(hInstance, szAppName);

RegisterClassEx(&wndclass);

wndclass.cbSize

= sizeof(wndclass);

wndclass.style

= CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc

= EllipPushWndProc;

wndclass.cbClsExtra

= 0;

wndclass.cbWndExtra

= 0;

wndclass.hInstance

= hInstance;

wndclass.hIcon

= NULL;

wndclass.hCursor

= LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground

=(HBRUSH)(COLOR_BTNFACE + 1);

wndclass.lpszMenuName

= NULL;

375

wndclass.lpszClassName

=

"EllipPush";

wndclass.hIconSm

=

NULL;

RegisterClassEx(&wndclass);

hwnd = CreateWindow(szAppName, "About Box Demo Program", 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 HINSTANCE hInstance;

switch(iMsg)

{

case WM_CREATE :

hInstance =((LPCREATESTRUCT) lParam)->hInstance; return 0;

case WM_COMMAND : switch(LOWORD(wParam))

{

case IDM_ABOUT :

DialogBox(hInstance, "AboutBox", hwnd,

AboutDlgProc);

return 0;

}

break;

case WM_DESTROY : PostQuitMessage(0); return 0;

}

return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

BOOL CALLBACK AboutDlgProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

switch(iMsg)

{

case WM_INITDIALOG : return TRUE;

case WM_COMMAND : switch(LOWORD(wParam))

{

case IDOK : EndDialog(hDlg, 0); return TRUE;

}

break;

}

376

return FALSE;

}

LRESULT CALLBACK EllipPushWndProc(HWND hwnd, UINT iMsg, WPARAM wParam,

 

LPARAM lParam)

{

 

char

szText[40];

HBRUSH

hBrush;

HDC

hdc;

PAINTSTRUCT

ps;

RECT

rect;

switch(iMsg)

{

case WM_PAINT : GetClientRect(hwnd, &rect);

GetWindowText(hwnd, szText, sizeof(szText)); hdc = BeginPaint(hwnd, &ps);

hBrush = CreateSolidBrush(GetSysColor(COLOR_WINDOW)); hBrush =(HBRUSH) SelectObject(hdc, hBrush); SetBkColor(hdc, GetSysColor(COLOR_WINDOW)); SetTextColor(hdc, GetSysColor(COLOR_WINDOWTEXT));

Ellipse(hdc, rect.left, rect.top, rect.right, rect.bottom); DrawText(hdc, szText, -1, &rect,

DT_SINGLELINE | DT_CENTER | DT_VCENTER);

DeleteObject(SelectObject(hdc, hBrush));

EndPaint(hwnd, &ps); return 0;

case WM_KEYUP :

if(wParam != VK_SPACE) break;

// fall through

case WM_LBUTTONUP : SendMessage(GetParent(hwnd), WM_COMMAND,

GetWindowLong(hwnd, GWL_ID),(LPARAM) hwnd); return 0;

}

return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

ABOUT3.RC

/*---------------------------

ABOUT3.RC resource script

---------------------------*/

#include <windows.h> #include "about3.h"

about3 ICON about3.ico

About3 MENU

{

POPUP "&Help"

{

MENUITEM "&About About3...", IDM_ABOUT

}

}

#define TABGRP(WS_TABSTOP | WS_GROUP)

377

AboutBox DIALOG 20, 20, 160, 80

 

 

 

 

STYLE WS_POPUP | WS_DLGFRAME

 

 

 

 

{

 

 

 

 

 

CTEXT

"About3"

-1,

0, 12, 160,

8

ICON

"About3"

-1,

8, 8,

0,

0

CTEXT

"About Box Demo Program"

-1,

0, 36, 160,

8

CTEXT

"(c) Charles Petzold, 1996"

-1,

0, 48, 160,

8

CONTROL "OK" IDOK, "EllipPush", TABGRP,

64, 60,

32, 14

}

 

 

 

 

 

ABOUT3.H

/*----------------------

ABOUT3.H header file

----------------------

*/

#define IDM_ABOUT

1

ABOUT3.ICO

Рис. 11.5 Программа ABOUT3

Класс окна, который мы будем регистрировать называется "EllipPush" эллипсоидная кнопка (elliptical push button). В шаблоне окна диалога вместо инструкции DEFPUSHBUTTON для задания класса окна используется инструкция

CONTROL:

CONTROL "OK" IDOK, "EllipPush", TABGRP, 64, 60, 32, 14

Менеджер окна диалога использует этот класс окна при вызове функции CreateWindow, когда в окне диалога создается дочернее окно управления.

В файле ABOUT3.С класс окна "EllipPush" регистрируется в WinMain:

wndclass.cbSize

= sizeof(wndclass);

wndclass.style

= CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc

= EllipPushWndProc;

wndclass.cbClsExtra

= 0;

wndclass.cbWndExtra

= 0;

wndclass.hInstance

= hInstance;

wndclass.hIcon

= NULL;

wndclass.hCursor

= LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground

=(HBRUSH)(COLOR_BTNFACE +1);

wndclass.lpszMenuName

= NULL;

wndclass.lpszClassName

= "EllipPush";

wndclass.hIconSm

= NULL;

RegisterClassEx(&wndclass);

В этом классе окна задается, что оконной процедурой является функция EllipPushWndProc, которая также находится в файле ABOUT3.С.

Оконная процедура EllipPushWndProc обрабатывает только три сообщения: WM_PAINT, WM_KEYUP и WM_LBUTTONUP. При обработке сообщения WM_PAINT она при помощи функции GetClientRect получает размер своего окна, а при помощи функции GetWindowText — текст, отображаемый на кнопке. Для рисования эллипса и текста используются функции Windows Ellipse и DrawText.

Сообщения WM_KEYUP и WM_LBUTTONUP обрабатываются очень просто:

case WM_KEYUP:

if(wParam != VK_SPACE)

break;

// идем дальше

case WM_LBUTTONUP:

 

SendMessage(GetParent(hwnd), WM_COMMAND, GetWindowLong(hwnd, GWL_ID),(LPARAM)hwnd); return 0;

Соседние файлы в предмете Операционные системы