LEKCII (Лекции), страница 16
Описание файла
Файл "LEKCII" внутри архива находится в папке "Лекции". Документ из архива "Лекции", который расположен в категории "". Всё это находится в предмете "api windows" из 6 семестр, которые можно найти в файловом архиве МГТУ им. Н.Э.Баумана. Не смотря на прямую связь этого архива с МГТУ им. Н.Э.Баумана, его также можно найти и в других разделах. Архив можно найти в разделе "лекции и семинары", в предмете "api windows" в общих файлах.
Онлайн просмотр документа "LEKCII"
Текст 16 страницы из документа "LEKCII"
Список "combobox" посылает в родительское окно сообщение WM_COMMAND. Параметр wParam этого сообщения содержит идентификатор списка. Младшее слово параметра lParam содержит идентификатор окна списка, а старшее - код извещения.
Приведем список кодов извещения, поступающих от органа управления класса "combobox".
Код извещения | Описание |
CBN_CLOSEUP | Список исчез (стал невидим) |
CBN_DBLCLK | Двойной щелчок левой клавишей мыши по строке списка, имеющего стиль CBS_SIMPLE |
CBN_DROPDOWN | Список стал видимым |
CBN_EDITCHANGE | Пользователь изменил содержимое окна редактирования, причем изменения уже отображены |
CBN_EDITUPDATE | Пользователь изменил содержимое окна редактирования, изменения еще не отображены |
CBN_ERRSPACE | Ошибка при попытке заказать дополнительную память |
CBN_KILLFOCUS | Список теряет фокус ввода |
CBN_SELENDCANCEL | Пользователь отменил выбор в списке. |
CBN_SELENDOK | Пользователь выбрал строку в списке. |
CBN_SELCHANGE | Изменился номер выбранной строки (т. е. пользователь выбрал другую строку) |
CBN_SETFOCUS | Список получает фокус ввода |
Сообщения для списка
Для управления списком "combobox" используется набор сообщений, аналогичный набору сообщений для списка "listbox" и редактора текста "edit". Функция SendMessage, посылающая сообщения списку "combobox", возвращает значение, которое зависит от выполняемой функции или коды ошибок CB_ERRSPACE (ошибка при получении дополнительной памяти), CB_ERR (затребованная операция не может быть выполнена). Если операция выполнена без ошибок, возвращается значение CB_OKAY.
В файле windows.h определены сообщения, специально предназначенные для работы со списком "combobox". Символические имена этих сообщений имеют префикс CB_. Приведем список таких сообщений.
CB_ADDSTRING
Добавление строки в список.
Параметры:
wParam = 0;
lParam = (LPARAM)(LPCSTR)lpszStr;
lpszStr - указатель на добавляемую строку.
Возвращаемое значение:
Номер строки в списке (первая строка имеет номер 0), или код ошибки.
CB_DELETESTRING
Удаление строки из списка.
Параметры:
wParam = (WPARAM)nIndex;
lParam = 0L;
nIndex - номер удаляемой строки. Первая строка имеет номер 0.
Возвращаемое значение:
Количество строк, оставшихся в списке, или код ошибки.
CB_DIR
Заполнение списка именами файлов и каталогов, расположенных в текущем каталоге, а также именами дисков.
Параметры:
wParam = (WPARAM)(UINT)uAttr;
lParam = (LPARAM)(LPCSTR)lpszFileSpec;
uAttr - атрибуты файлов;
lpszFileSpec - указатель на строку, содержащую имя файла или шаблон имени файла.
Возвращаемое значение:
Номер последнего имени файла, добавленного в список, или код ошибки.
Контекст.
Как правило, приложения выполняют всю работу по рисованию во время обработки сообщения WM_PAINT , хотя часто требуется рисовать и во время обработки других сообщений. В любом случае приложение должно придерживаться следующей последовательности действий:
получение или создание контекста отображения;
установка необходимых атрибутов в контексте отображения;
выполнение операций рисования;
освобождение или удаление контекста отображения.
Последнее действие (освобождение или удаление контекста отображения) должно быть обязательно выполнено. Самый простой способ полностью нарушить работоспособность Windows - забыть освободить полученный контекст отображения или удалить созданный контекст отображения или устройства.
Так как контекст отображения - критический ресурс, его необходимо освобождать сразу, как только в нем отпадет необходимость. Операционная система Windows выполняет кеширование обычного контекста отображения (есть и необычные контексты отображения, но об этом позже), причем кешируются только пять контекстов. Если Windows не может удовлетворить запрос какого-либо приложения на выделение контекста отображения, вся операционная система окажется в критическом состоянии, единственным выходом из которого будет полный перезапуск Windows.
Среди всех атрибутов контекста отображения, описанных в первой главе, особое место занимает режим отображения, влияющий на систему координат и, соответственно, на работу практически всех функций рисования. Поэтому необходимо уделить особое внимание вопросам использования режимов отображения и систем координат.
Однако прежде всего необходимо научиться получать и освобождать контекст отображения.
Получение и освобождение контекста отображения
Способы получения (и, соответственно, освобождения) контекста отображения разные для контекстов разного типа. Можно выделить следующие типы контекста отображения:
общий контекст отображения (common display context);
контекст отображения для класса окна (class display context);
личный контекст отображения (private display context);
родительский контекст отображения (parent display context);
контекст отображения для окна (window display context);
контекст физического устройства (device context);
информационный контекст (information context);
контекст для памяти (memory device context);
контекст для метафайла (metafile context).
Каждый из перечисленных выше контекстов имеет свои особенности и свое назначение.
Общий контекст отображения
Этот контекст используется чаще всего и поэтому для ускорения доступа к нему Windows использует кеширование (как мы уже говорили, размер кеша достаточен для хранения только пяти контекстов отображения).
Для получения общего контекста отображения приложение должно вызвать функцию BeginPaint (при обработке сообщения WM_PAINT ) или GetDC (при обработке других сообщений). При этом перед регистрацией класса окна в поле стиля класса окна в структуре WNDCLASS не должны использоваться значения CS_OWNDC , CS_PARENTDC или CS_CLASSDC :
wc.style = 0;
Функция BeginPaint возвращает контекст отображения для окна hwnd:
HDC WINAPI BeginPaint(HWND hwnd, PAINTSTRUCT FAR* lpps);
Перед этим она подготавливает указанное окно для рисования, заполняя структуру типа PAINTSTRUCT (адрес которой передается через параметр lpps) информацией, которую можно использовать в процессе рисования.
Структура PAINTSTRUCT и указатели на нее (различных типов) описаны в файле windows.h:
typedef struct tagPAINTSTRUCT
{
HDC hdc;
BOOL fErase;
RECT rcPaint;
BOOL fRestore;
BOOL fIncUpdate;
BYTE rgbReserved[16];
} PAINTSTRUCT;
typedef PAINTSTRUCT* PPAINTSTRUCT;
typedef PAINTSTRUCT NEAR* NPPAINTSTRUCT;
typedef PAINTSTRUCT FAR* LPPAINTSTRUCT;
Рассмотрим назначение отдельных полей структуры PAINTSTRUCT.
Поле hdc после возврата из функции будет содержать идентификатор полученного контекста отображения, который должен передаваться в качестве параметра функциям интерфейса GDI, выполняющим рисование. Можно использовать также значение идентификатора контекста, возвращенное функцией BeginPaint, так как эти значения одинаковые.
Анализируя содержимое поля fErase, приложение может определить, нужно ли перерисовывать фон окна. Если в этом поле находится значение TRUE, фон окна должен быть перерисован. Такая необходимость может возникнуть в том случае, если в классе, на базе которого создано окно, при регистрации не была выбрана кисть для закрашивания фона (поле hbrBackground структуры WNDCLASS).
Поле rcPaint, которое представляет собой структуру типа RECT, содержит координаты верхнего левого и правого нижнего угла прямоугольника, внутри которого нужно рисовать. Напомним вам формат структуры RECT , описанной в файле windows.h:
typedef struct tagRECT
{
int left;
int top;
int right;
int bottom;
} RECT;
Мы уже говорили вам в 11 томе "Библиотеки системного программиста", что при обработке сообщения WM_PAINT приложение должно суметь перерисовать все окно или любую его часть. Сообщение WM_PAINT может попасть в функцию окна в том случае, если все окно или его часть требуют перерисовки. Поле rcPaint в структуре PAINTSTRUCT содержит координаты прямоугольной области, расположенной в окне и требующей перерисовки.
Остальные поля зарезервированы для Windows и не используются приложениями.
Контекст отображения, полученный при помощи функции BeginPaint, необходимо освободить перед завершением обработки сообщения WM_PAINT, вызвав функцию EndPaint :
void WINAPI EndPaint(HWND hwnd, const PAINTSTRUCT FAR* lpps);
Функции EndPaint передаются те же параметры, что и функции BeginPaint.
Обычно обработчик сообщения WM_PAINT выглядит следующим образом:
PAINTSTRUCT ps;
HDC hdc;
........
case WM_PAINT:
{
// Получаем контекст отображения
hdc = BeginPaint(hwnd, &ps);
// После получения контекста отображения
// можно вызывать функции GDI
TextOut(hdc, 0, 0, (LPSTR)"String", 6);
.
.
// Освобождаем контекст отображения
EndPaint(hwnd, &ps);
break;
}
Подобный фрагмент кода вы можете найти в приложениях, описанных в одном из предыдущих томов "Библиотеки системного программиста".
Функции BeginPaint и EndPaint можно использовать только внутри обработчика сообщения WM_PAINT. Если же приложению требуется рисовать во время обработки других сообщений, оно должно получить контекст отображения с помощью функции GetDC . После завершения процедуры рисования перед выходом из обработчика сообщения следует освободить полученный контекст отображения, вызвав функцию ReleaseDC .
Функция GetDC возвращает контекст отображения для окна с идентификатором hwnd:
HDC WINAPI GetDC(HWND hwnd);
Полученный таким образом контекст отображения можно использовать для рисования во внутренней области окна (window client region).
Функция ReleaseDC освобождает контекст отображения hdc, полученный для окна hwnd:
int WINAPI ReleaseDC(HWND hwnd, HDC hdc);
Мы еще раз обращаем ваше внимание на необходимость своевременного освобождения общего контекста отображения.
Каждый раз, когда приложение получает общий контекст отображения, его атрибуты принимают значения по умолчанию, перечисленные нами ранее. Если перед выполнением рисования приложение изменит атрибуты контекста отображения, вызвав соответствующие функции GDI, в следующий раз при получении общего контекста отображения эти атрибуты снова примут значения по умолчанию. Поэтому установка атрибутов должна выполняться каждый раз после получения общего контекста отображения. Такая процедура отнимает дополнительное время, но она необходима при использовании контекста отображения этого типа.
Контекст отображения для класса окна
Общий контекст отображения, описанный нами в предыдущем разделе, кешируется операционной системой Windows для ускорения доступа к нему. Однако вы можете создать такой контекст отображения, который хранится отдельно в единственном экземпляре и используется всеми окнами, созданными на базе класса окна. При регистрации такого класса окна вы должны указать стиль CS_CLASSDC :
wc.style = CS_CLASSDC;
Все окна, созданные на базе класса, имеющего стиль CS_CLASSDC, будут использовать один общий контекст отображения.
В отличие от общего контекста отображения, приложения, однажды получив контекст отображения для класса окна, могут не освобождать его. То есть для контекста этого типа после функций BeginPaint и GetDC можно не вызывать функции EndPaint и ReleaseDC. Если же приложение вызовет функцию EndPaint или ReleaseDC, они не будут ничего делать и сразу вернут управление. Для уменьшения вероятности ошибки мы рекомендуем вам всегда освобождать контекст отображения, даже если это и не требуется для данного типа контекста.
Несмотря на то, что для всех окон, созданных на базе класса стиля CS_CLASSDC, создается один контекст отображения, не следует думать, что приложение, однажды получив этот контекст, не должно получать его вновь при очередном вызове обработчика сообщения, выполняющего рисование.
Дело в том, что при получении контекста отображения для окна в нем устанавливаются атрибуты области ограничения и начало системы физических координат устройства отображения. Если на базе нашего класса создано несколько окон, при получении ими контекста отображения эти атрибуты "настраиваются" на окно, получившее контекст отображения. Но если на базе класса стиля CS_CLASSDC приложение создало только одно окно, оно может получить контекст отображения для класса окна один раз и не освобождать его.
Контекст отображения класса окна можно использовать в тех случаях, когда по соображениям повышения производительности нежелательно выполнять настройку многочисленных атрибутов контекста отображения после каждого вызова функции BeginPaint или EndPaint. Эту настройку можно выполнить только один раз. Каждый раз, когда функция окна получает контекст отображения класса окна, в нем выполняется настройка только двух атрибутов - области ограничения и начала системы физических координат устройства вывода. Остальные атрибуты остаются без изменений и, следовательно, не требуют повторной настройки.
Личный контекст отображения