Оконный дескриптор (hWnd) является уникальным идентификатором (который является целым четырехбайтовым беззнаковым числом), который присваивает Windows каждому созданному окну. В этом случае, под окном подразумевается любые элементы: от кнопок управления и надписей до диалоговых окон и окон в целом.
Windows посылает специальные, определенные системой, сообщения при взаимодействии с приложением. Она использует эти сообщения для управления действиями приложения и для предоставления ввода и прочей информации, нужной для работы приложения. Приложения также могут отправлять такие сообщения для различных целей, например, для управления окнами, созданными на основе заранее зарегистрированных оконных классов.
Практически каждому сообщению в Windows сопоставлено событие в Делфи, при поступлении которого можно выполнить специальные действия. Мы не будем использовать библиотеку VCL, а вместе с ней и события в Делфи (см. модуль 2).
Каждое системное сообщение имеет уникальный идентификатор сообщения (номер) и соответствующее ему название (определенное в заголовочном файле), которое показывает назначение сообщения. Например, сообщение с названием WM_PAINT просит окно перерисовать свое содержимое.
Название сообщения описывает также и категорию, к которой это сообщение принадлежит. Приставка в названии определяет тип окна, которое может прочитать и обработать это сообщение. Например, приставка WM_ обозначает, что сообщение предназначается обычному окну.
Сообщения для обычных окон включают в себя множество информационных сообщений и запросов, таких, как сообщения от мышки и клавиатуры, выбор элементов меню и диалоговых окон, создание и управление окнами, динамический обмен данными (dynamic data exchange - DDE).
Приложение может создавать сообщения, которые могут использовать для своих внутренних нужд или для взаимодействия с окнами других процессов. В случае, если приложение создает свои собственные сообщения, оконная функция, которая принимает их, должна интерпретировать эти сообщения и соответствующим образом их обработать.
В операционной системе Windows зарезервированы значения идентификаторов сообщений в интервалах от 0x0000 до 0x03FF (WM_USER – 1) и от 0x8000 до 0xBFFF для системных сообщений. Приложения не могут использовать эти значения для своих собственных сообщений.
1.3. Функция MessageBox
Начнем знакомиться с API функциями с наиболее простой и часто употребляемой функции MessageBox. Эта функция позволяет выводить стандартное окно сообщения Windows с заданны текстом и кнопками.
Функция объявлена в файле windows.pas следующим образом:
function MessageBox; external user32 name 'MessageBoxA';
Откуда видно, что функция реализована в библиотеке user32.dll. Синтаксис функции описан в справке (на языке C++):
int MessageBox(
HWND hWnd, // ссылка на окно владельца
LPCTSTR lpText, // текст сообщения
LPCTSTR lpCaption, // заголовок окна
UINT uType // стиль окна
);
hWnd – ссылка на окно-владельца, может быть равно 0, тогда владельцем будет рабочий стол windows.
lpText, lpCaption – строки символов текста сообщения и заголовка соответственно. В языке Object Pascal имеют тип PChar. Для преобразования строки типа String к PChar можно использовать функцию PChar(). Если текст сообщения задан в явном виде, то преобразование будет проведено автоматически, например, код
var s: string;
…
s := 'ZL';
MessageBox(0, 'Текст сообщения', PChar(s), 0);
приведет к появлению окна, похожего на приведенное на рисунке 1. Отличия в оформлении могут быть связаны с особенностями и настройкой операционной системы.
Рис. 1.
uType – указывает особенности окна сообщения, такие, как кнопки и иконка в левой его части. Например, указав MB_OK (который равен нулю, чем мы и воспользовались ранее), мы получим окно с одной кнопкой Ok. Если бы мы указали стиль MB_ICONSTOP OR MB_OKCANCEL, то получили бы окно с двумя кнопками Ok и Cancel и иконкой со знаком остановки. Полный список параметров приведен в справке Delphi и MSDN.
Возвращаемое значение функции равно одной из констант IDABORT, IDCANCEL, IDIGNORE, IDNO, IDOK, IDRETRY, IDYES в зависимости от выбранной пользователем кнопки (если их несколько).
Примером использования этой функции является окно, появляющееся при выходе из программы. Запишем обработчик события формы OnCloseQuery:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);begin CanClose := MessageBox( handle, {handle – свойство формы, содержащее дескриптор окна} PChar('Действительно выйти?'+#13+'Все несохраненные данные будут потеряны.'), '', MB_ICONQUESTION or MB_YESNO ) = IDYES;end;Окно, выводимое при попытке закрыть программу, приведено на рисунке 2.
Рис. 2.
Написать программу, выводящую дескриптор окна и всех оконных компонентов (свойство Handle всех объектов-наследников TControl библиотеки VCL) в окне, выводимом функцией MessageBox, содержащем три кнопки – Ok, Retry, Cancel. Проверить, какую из кнопок выбрал пользователь.
Тест содержит 5 заданий, на выполнение которых отводится 3 минуты. Выберите наиболее правильный, по Вашему мнению, вариант ответа и отметьте его любым значком в бланке ответов.
1. Windows API функции это: | |||
1) | Функции, предоставляемые оболочкой Delphi при работе в ОС Windows | 2) | Функции всех динамических библиотек (DLL) |
3) | Системные функции операционной системы Windows, используемые при разработке приложений | 4) | Функции, которые выполняет операционная система (поддержка устройств, интерфейс пользователя…) |
2. Сообщения в Windows позволяет | |||
1) | Взаимодействовать операционной системе и приложению | 2) | Управлять системой из приложения |
3) | Управлять приложением | 4) | Все вышеперечисленное |
3. Дескриптор это | |||
1) | Объект или ресурс операционной системы | 2) | Некоторое однобайтовое целое число |
3) | Непрямой указатель | 4) | Указатель на область памяти |
4. Выполнение кода MessageBox(0, ‘’, ‘’, MB_ICONASTERYX or MB_YESNO) приведет к | |||
1) | Возникновению ошибки при исполнении | 2) | Возникновению ошибки при компиляции |
3) | Появлению окна без заголовка и текста, но с иконкой с вопросом и кнопками да/нет | 4) | Появлению окна без заголовка и текста, но с иконкой остановки и кнопками да/нет |
5. Выполнение кода MessageBox(0, '', '', MB_OK or MB_YESNO or MB_ABORTRETRYIGNORE or MB_RETRYCANCEL) приведет к | |||
1) | Возникновению ошибки при исполнении | 2) | Возникновению ошибки при компиляции |
3) | Не приведет к возникновению ошибки, однако окно показано не будет | 4) | Приведет к появлению окна с большим количеством кнопок |
Бланк ответов
№ | 1 | 2 | 3 | 4 |
1) | ||||
2) | ||||
3) | ||||
4) | ||||
5) |
Критерии оценки
4 и более правильных ответов – отлично
3 правильных ответа – хорошо
2 правильных ответа – удовлетворительно
1 и менее правильных ответов - неудовлетворительно
Модуль 2. Создание элементов управления
Разработка программ зачастую напоминает священный ритуал, построенный на произнесении ряда обязательных магических заклинаний. Особенно это касается Windows приложений. Windows-заклинания позволяют вывести графическое окно, обработать поступающие сообщения. Порядок их следования предопределен священными руководствами.
Легалов А. И., д.т.н., проф. Сибирского федерального университета
Комплексная цель: научиться создавать полноценные программы без использования дополнительных визуальных библиотек, таких как VCL в Delphi или MFC в C++.
Краткое изложение программного материала: в модуле показано как создавать на основе Win API функций:
· Окна
· Кнопки
· Редакторы ввода
· Меню
· Стандартные диалоговые окна
Материал ориентирован на студентов, умеющих читать и понимать программный код и снабжен большим количеством примеров. Приведены некоторые способы управления созданными элементами.
2.1. Создание окна средствами WinAPI
Для того, чтобы создать окно, необходимо:
1. Создать и зарегистрировать в Windows специальный класс окна с помощью функции RegisterClass();
2. Создать (CreateWindow) и показать (ShowWindow) экземпляр окна;
3. На этапе создания необходимо указать процедуру, которая будет обрабатывать сообщения, приходящие из операционной системы. В этой процедуре в дальнейшем и будет сосредоточен весь код.
Регистрация специального класса окна производиться с помощью функции ATOM RegisterClass(CONST WNDCLASS *lpWndClass), возвращаемое значение которой равно нулю в случае ошибки. Информация о классе содержится в структуре lpWndClass типа WNDCLASS* (язык C), которую необходимо предварительно заполнить, например, следующим образом (Delphi):