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

254

посылает сообщения дочерним окнам управления, а дочерние окна управления посылают сообщения обратно оконной процедуре.

Для создания обычного окна приложения, во-первых, определите класс окна и зарегистрируйте его в Windows с помощью функции RegisterClassEx. Затем с помощью функции CreateWindow создайте окно на основе этого класса. Однако, если вы используете одно из предопределенных дочерних окон управления, то для этого дочернего окна класс окна регистрировать не надо. Такой класс уже существует в Windows и имеет одно из следующих имен: "button" (кнопка), "static" (статическое), "scrollbar" (полоса прокрутки), "edit" (окно редактирования), "listbox" (окно списка) или "combobox" (окно комбинированного списка). Вы просто используете имя в качестве параметра класса окна в функции CreateWindow. Параметр стиля окна функции CreateWindow более точно определяет вид и свойства дочернего окна управления. Windows включает в себя оконные процедуры, обрабатывающие сообщения тех дочерних окон, которые созданы на основе перечисленных классов.

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

Класс кнопок

Наше изучение класса окна button мы начнем с программы BTNLOOK "вид кнопки" (button look), которая представлена на рис. 8.1. В программе BTNLOOK создается 10 дочерних окон управления в виде кнопок, по одному на каждый из 10 стандартных стилей кнопок.

BTNLOOK.MAK

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

# BTNLOOK.MAK make file

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

btnlook.exe : btnlook.obj

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

btnlook.obj : btnlook.c

$(CC) $(CFLAGS) btnlook.c

BTNLOOK.C

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

 

 

BTNLOOK.C --

Button Look Program

 

 

(c) Charles Petzold,

1996

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

 

*/

#include <windows.h>

struct

{

long style; char *text;

}

button[] =

{

BS_PUSHBUTTON, "PUSHBUTTON",

BS_DEFPUSHBUTTON, "DEFPUSHBUTTON",

BS_CHECKBOX, "CHECKBOX",

BS_AUTOCHECKBOX, "AUTOCHECKBOX",

BS_RADIOBUTTON, "RADIOBUTTON",

BS_3STATE, "3STATE",

BS_AUTO3STATE, "AUTO3STATE",

BS_GROUPBOX, "GROUPBOX",

BS_AUTORADIOBUTTON, "AUTORADIO",

BS_OWNERDRAW, "OWNERDRAW"

255

};

#define NUM(sizeof button / sizeof button[0])

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

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

{

static char szAppName[] = "BtnLook";

HWND

hwnd;

MSG

msg;

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(NULL, IDI_APPLICATION);

wndclass.hCursor

= LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground

=(HBRUSH) GetStockObject(WHITE_BRUSH);

wndclass.lpszMenuName

= NULL;

wndclass.lpszClassName

= szAppName;

wndclass.hIconSm

= LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&wndclass);

hwnd = CreateWindow(szAppName, "Button Look", 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 char

szTop[]

= "iMsg

wParam

lParam",

 

szUnd[]

= "____

______

______",

 

szFormat[] = "%-16s%04X-%04X

%04X-%04X",

 

szBuffer[50];

 

 

static HWND

hwndButton[NUM];

 

 

static RECT

rect;

 

 

 

static int

cxChar, cyChar;

 

 

HDC

hdc;

 

 

 

PAINTSTRUCT

ps;

 

 

 

int

i;

 

 

 

TEXTMETRIC

tm;

 

 

 

switch(iMsg)

{

case WM_CREATE :

hdc = GetDC(hwnd);

SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

256

GetTextMetrics(hdc, &tm); cxChar = tm.tmAveCharWidth;

cyChar = tm.tmHeight + tm.tmExternalLeading; ReleaseDC(hwnd, hdc);

for(i = 0; i < NUM; i++)

hwndButton[i] = CreateWindow("button", button[i].text, WS_CHILD | WS_VISIBLE | button[i].style, cxChar, cyChar *(1 + 2 * i),

20 * cxChar, 7 * cyChar / 4, hwnd,(HMENU) i,

((LPCREATESTRUCT) lParam) -> hInstance, NULL);

return 0;

 

 

 

case WM_SIZE :

 

 

 

rect.left

= 24

* cxChar;

rect.top

=

2

* cyChar;

rect.right

=

LOWORD(lParam);

rect.bottom = HIWORD(lParam); return 0;

case WM_PAINT :

InvalidateRect(hwnd, &rect, TRUE);

hdc = BeginPaint(hwnd, &ps);

SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

SetBkMode(hdc, TRANSPARENT);

TextOut(hdc, 24 * cxChar, cyChar, szTop, sizeof(szTop) - 1);

TextOut(hdc, 24 * cxChar, cyChar, szUnd, sizeof(szUnd) - 1);

EndPaint(hwnd, &ps); return 0;

case WM_DRAWITEM : case WM_COMMAND :

ScrollWindow(hwnd, 0, -cyChar, &rect, &rect);

hdc = GetDC(hwnd);

SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));

TextOut(hdc, 24 * cxChar, cyChar *(rect.bottom / cyChar - 1), szBuffer,

wsprintf(szBuffer, szFormat,

iMsg == WM_DRAWITEM ? "WM_DRAWITEM" : "WM_COMMAND", HIWORD(wParam), LOWORD(wParam),

HIWORD(lParam), LOWORD(lParam)));

ReleaseDC(hwnd, hdc);

ValidateRect(hwnd, &rect);

break;

case WM_DESTROY : PostQuitMessage(0); return 0;

}

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

}

Рис. 8.1 Программа BTNLOOK

При щелчке на любой из кнопок она посылает сообщение WM_COMMAND оконной процедуре родительского окна WndProc. WndProc программы BTNLOOK выводит на экран параметры wParam и lParam этого сообщения в правой половине рабочей области, как показано на рис. 8.2.

257

Рис. 8.2 Вывод на экран программы BTNLOOK

Кнопка со стилем BS_OWNERDRAW выводится в окне только в виде затенения фона, поскольку стиль этой кнопки рассчитан на то, что за рисование отвечает сама программа. Эта кнопка показывает, что ее необходимо рисовать при обработке сообщения WM_DRAWITEM с параметром lParam, являющимся указателем на структуру типа DRAWITEMSTRUCT. Эти сообщения также выводятся на экран в программе BTNLOOK. (Более подробно о кнопках, определяемых пользователем, будет рассказано далее в этой главе.)

Создание дочерних окон

В программе BTNLOOK определяется структура с именем button, в которой содержатся стили окон кнопок и строки текста для каждой из 10 типов кнопок. Все стили окон кнопок начинаются с префикса BS, что означает

"button style" (стиль кнопки).

Десять дочерних окон в виде кнопок создаются в цикле for при обработке сообщения WM_CREATE в WndProc. При вызове функции CreateWindow используются следующие параметры:

Имя класса Текст окна Стиль окна Положение по х Положение по у Ширина Высота

Родительское окно Идентификатор дочернего окна Описатель экземпляра Дополнительные параметры

"button"

button[i].text

WS_CHILD | WS_VISIBLE | button[i].style cxChar

cyChar * (1 + 2 * i) 20 * cxChar

7 * cyChar / 4 hwnd

(HMENU)i

((LPCREATESTRUCT) lParam) -> hInstance NULL

Параметр "имя класса" — его предопределенное имя. При задании стиля окна используются стили WS_CHILD, WS_VISIBLE и один из десяти стилей кнопок (BS_PUSHBUTTON, BS_DEFPUSHBUTTON и т. д.), которые определены в структуре button. Параметр "текст окна" (который у обычного окна появляется в строке заголовка) — это текст, который будет выводиться вместе с каждой кнопкой. Здесь просто использовался текст, идентифицирующий стиль кнопки.

Параметры "положение по х" и "положение по у" показывают положение верхнего левого угла дочернего окна относительно верхнего левого угла рабочей области родительского окна. Параметры "ширина" и "высота" задают ширину и высоту каждого дочернего окна.

Параметр "идентификатор дочернего окна" должен быть для каждого окна уникальным. Этот идентификатор помогает оконной процедуре при обработке сообщений WM_COMMAND определить дочернее окно — источник сообщений. Обратите внимание, что идентификатор дочернего окна передается в функцию CreateWindow в виде параметра, который обычно используется для задания меню программы, поэтому его тип должен быть преобразован к HMENU.

Параметр "описатель экземпляра" функции CreateWindow выглядит несколько странно, но при этом во время обработки сообщения WM_CREATE параметр lParam фактически равен указателю на структуру типа CREATESTRUCT ("creation structure" — структура создания), членом которой является hInstance. Поэтому мы приводим тип параметра lParam к типу указатель на структуру CREATESTRUCT и извлекаем hInstance.

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