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

276

дочерних окон, когда получает сообщение WM_SIZE. Поэтому, когда бы вы ни изменили размер окна программы COLORS1, пропорционально меняются и размеры полос прокрутки.

Когда оконная процедура WndProc получает сообщение WM_VSCROLL, то старшим словом параметра lParam является описатель дочернего окна. Для получения идентификатора дочернего окна можно использовать функцию

GetWindowLong:

i = GetWindowLong(lParam, GWW_ID);

Мы задали идентификаторы трех полос прокрутки как три последовательных числа 0, 1 и 2, поэтому WndProc может информировать о том, какая из полос является источником сообщения.

Поскольку описатели дочерних окон при создании этих окон были сохранены в массиве, WndProc может обработать сообщение полосы прокрутки и установить новое положение соответствующей полосы прокрутки с помощью вызова функции SetScrollPos:

SetScrollPos(hwndScrol[i], SB_CTL, color[i], TRUE);

WndProc также изменяет текст дочернего окна под полосой прокрутки:

SetWindowText(hwndValue[i], itoa(color[i], szbuffer, 10));

Интерфейс клавиатуры, поддерживаемый автоматически

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

Клавиши управления курсором

Значение wParam сообщения

 

полосы прокрутки

Home

SB_TOP

End

SB_BOTTOM

Page Up

SB_PAGEUP

Page Down

SB_PAGEDOWN

Стрелка влево или вверх

SB_LINEUP

Стрелка вправо или вниз

SB_LINEDOWN

Фактически, сообщения полос прокрутки SB_TOP и SB_BOTTOM могут вырабатываться только с помощью клавиатуры. Если вы хотите, чтобы полоса прокрутки управления получила фокус ввода, когда на полосе прокрутки происходит щелчок мыши, то вы должны включить идентификатор WS_TABSTOP в параметр стиля окна при вызове функции CreateWindow. Если полоса прокрутки имеет фокус ввода, то бегунок полосы прокрутки становится похож на мигающий серый блочок.

Чтобы полностью обеспечить интерфейс клавиатуры для полос прокрутки, требуется затратить несколько больше усилий. Во-первых, оконная процедура WndProc должна специально передать полосе прокрутки фокус ввода. Она это делает, обрабатывая сообщение WM_SETFOCUS, которое получает родительское окно при получении фокуса ввода. WndProc просто устанавливает фокус ввода на одну из полос прокрутки:

SetFocus(hwndScrol[iFocus])

Но кроме этого нужно иметь возможность как-то переходить от одной полосы прокрутки к другой, предпочтительнее с помощью клавиши <Tab>. Это более трудно, поскольку, раз полоса прокрутки имеет фокус ввода, она обрабатывает все нажатия клавиш. Но полоса прокрутки отслеживает только клавиши управления курсором; клавиша <Tab> ею игнорируется. Для решения этой задачи существует прием, который называется "введение новой оконной процедуры" (window subclassing). Мы будем пользоваться этим приемом, чтобы в программе COLORS1 получить возможность с помощью клавиши <Tab> переходить с одной полосы прокрутки на другую.

Введение новой оконной процедуры

Оконная процедура для полос прокрутки — элементов управления находится где-то внутри Windows. Однако, вы можете получить адрес этой оконной процедуры с помощью вызова функции GetWindowLong, в которой в качестве параметра используется идентификатор GWL_WNDPROC. Более того, вызывая функцию SetWindowLong, вы можете задать для полос прокрутки новую оконную процедуру. Это очень мощный прием, который называется "введение новой оконной процедуры". Он позволяет вам "влезть" в существующие внутри Windows оконные процедуры, обработать некоторые сообщения внутри вашей собственной программы, а все остальные сообщения оставить прежней оконной процедуре.

277

Оконная процедура, которая в программе COLORS1 предварительно обрабатывает сообщения полос прокрутки, называется ScrollProc; она находится в конце программы COLORS1.С. Поскольку ScrollProc является функцией программы COLORS1, которая вызывается операционной системой Windows, то она должна определяться как функция обратного вызова (CALLBACK).

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

fnOldScr[i] =(WNDPROC) SetWindowLong(hwndScrol[i], GWL_WNDPROC,(LONG) ScrollProc));

Теперь функция ScrollProc получает все сообщения, которые Windows посылает оконной процедуре полосы прокрутки для трех полос прокрутки программы COLORS1 (но, конечно, не для полос прокрутки других программ). Оконная процедура ScrollProc, при получении сообщения о нажатии клавиши <Tab> или <Shift>+<Tab>, просто передает фокус ввода следующей (или предыдущей) полосе прокрутки. С помощью функции CallWindowProc она вызывает прежнюю оконную процедуру полосы прокрутки.

Закрашивание фона

Когда программа COLORS1 определяет свой класс окна, она задает для своей рабочей области сплошную черную кисть:

wndclass.hbrBackground = CreateSolidBrush(0L);

Если вы изменяете установки полос прокрутки программы COLORS1, то программа должна создать новую кисть и поместить в структуру класса окна новый описатель кисти. Точно также, как мы получали адрес прежней и вводили новую оконную процедуру полос прокрутки с помощью функций GetWindowLong и SetWindowLong, мы можем получить и ввести новый описатель этой кисти с помощью функций GetClassWord и SetClassWord.

Вы можете создать новую кисть, ввести ее описатель в структуру класса окна, а затем удалить старую кисть:

DeleteObject(

(HBRUSH)SetClassLong(

hwnd, GCL_HBRBACKGROUND,

(LONG)CreateSolidBrush(RGB(color[0], color[1], color[2]))

)

);

Следующий раз Windows при перерисовке фона окна будет пользоваться новой кистью. Чтобы заставить Windows обновить фон, мы делаем недействительной правую половину рабочей области:

InvalidateRect(hwnd, &rcColor, TRUE);

Использования в качестве третьего параметра значения TRUE (не равно 0) показывает, что перед рисованием мы хотим обновить фон.

Функция InvalidateRect заставляет Windows поместить сообщение WM_PAINT в очередь сообщений оконной процедуры. Поскольку сообщения WM_PAINT имеют низкий приоритет, то такое сообщение, если вы еще перемещаете полосу прокрутки с помощью мыши или клавиш управления курсором, не будет обработано немедленно. В противном случае, если вы хотите, чтобы окно обновилось сразу после того, как его цвет был изменен, в программу, после вызова функции InvalidateRect необходимо добавить следующую инструкцию:

UpdateWindow(hwnd);

Но это может затормозить обработку сообщений клавиатуры и мыши.

Функция WndProc программы COLORS1 не обрабатывает сообщения WM_PAINT, а передает его в DefWindowProc. Заданный в Windows по умолчанию процесс обработки сообщений WM_PAINT заключается просто в вызовах функций BeginPaint и EndPaint, которые делают окно действительным. Поскольку мы задали при вызове функции InvalidateRect, что фон должен быть обновлен, то вызов функции BeginPaint заставляет Windows выработать сообщение WM_ERASEBKGND (обновление фона). WndProc игнорирует и это сообщение тоже. Windows обрабатывает его, обновляя фон рабочей области с помощью кисти, заданной в классе окна.

Считается хорошим стилем программирования удалять созданные ресурсы. Поэтому при обработке сообщения WM_DESTROY функция DeleteObject вызывается снова:

DeleteObject((HBRUSH)SetClassLong(hwnd, GCL_HBRBACKGROUND,(LONG) GetStockObject(WHITE_BRUSH)));

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