4. Структура программы в DOS модели или
консольное приложение
program
uses <список модулей>
{описания
процедур}
……………
var
{описания
переменных}
……………
begin
{код программы}
end.
5. Структура программы для Windows
Любое приложение идентифицируется с точки зрения
Windows посредством своего окна, вернее – класса
окна. Соответственно, первыми шагами приложения
должны быть создание и регистрация класса окна.
Кнопка – то же окно,
только дочернее
6. Структура программы для Windows
Программа для Windows в целом идентична обычной
паскаль-программе с тем отличием, что она обязательно
должна содержать:
описание и создание объекта «главное окно
программы»;
функцию WinMain, работающую с этим окном.
При использовании среды Lazarus и/или Delphi эти
вопросы решаются средой и скрыты для программиста.
7. Структура программы для Windows
program
{модули с описаниями интерфейсов к системным DLL}
uses <список модулей>, windows;
{описания процедур}
procedure WinMain; //Основной цикл обработки сообщений
var
{описания локальных переменных WinMain}
{описание класса окна; имя класса произвольное,
тип – стандартный из библиотеки windows}
wndClass: TWndClassEx;
<описания остальных переменных WinMain>
8. Структура программы для Windows
begin
{установление ссылки на процедуру обработки событий
внутри окна – нажатие мышкой, набор на клавиатуре и т.п.
}
wndClass.lpfnWndProc := @WndProc;
<задание остальных свойств wndClass>
{вызов стандартной функции регистрации класса окна}
RegisterClassEx(wndClass);
………
end;
9. Структура программы для Windows
var
{описания переменных программы}
………………
{Раздел операторов}
begin
WinMain;
end.
10. Определение внешнего вида окна
Задавая различные параметры класса (или экземпляра) окна,
мы можем изменять внешний вид окна. Зададим параметры
класса WndClass, например, следующие:
wndClass.hIcon:=loadIcon(0, idi_Application);
//иконка приложения
wndClass.hCursor:=loadCursor(0, idc_Arrow); //курсор
приложения
wndClass.hbrBackground:=GetStockObject(white_Brush);
//цвет заднего фона
wndClass.lpszMenuName:=nil; //меню, вернее – ссылка на
меню; nil означает отсутствие меню
wndClass.lpszClassName:=’Timer’; //название класса окна
wndClass.hIconSm:=loadIcon(0, idi_Application); //иконка
приложения в свернутом виде
11. Определение внешнего вида окна
Как правило, все эти параметры задаются в процедуре
WinMain до регистрации класса.
Как видно из текста программы, после установления
всех параметров класса окна этот класс должен быть
зарегистрирован с использованием стандартной
функции RegisterClassEx.
12. Создание экземпляра окна
Обладая зарегистрированным классом, можно создать
экземпляр окна, использовав функцию CreateWindowEx,
которая возвращает ссылку на получившийся экземпляр.
Для этого в разделе var процедуры Winmain надо объявить
соответствующую переменную типа THandle, например:
hWnd: THandle,
и вызвать функцию создания экземпляра окна:
13. Создание экземпляра окна
hwnd:=CreateWindowEx(
0,
// параметр, относящийся к стилю окна
Timer,
//имя класса окна, то, что было определено в lpszClassName
'Программа-таймер', //заголовок окна
ws_overlappedWindow, //стиль окна
10, //левая граница
10, //верхняя граница
500, //ширина
14. Создание экземпляра окна
200, //высота
0, //хэндл родительского окна
0, //хэндл оконного меню
hInstance, //хэндл экземпляра приложения
nil);
Здесь hwnd – ссылка на экземпляр окна, так называемый хэндл
(handle) окна. Это специальное число, присваиваемое каждому
компоненту в windows и позволяющее впоследствии
идентифицировать этот компонент и обращаться к нему.
15. Отображение окна на экране
Созданное окно отображается на экране после вызова функции
ShowWindow:
ShowWindow (hwnd, SW_SHOW);
Здесь sw_show – параметр, указывающий, что окно надо
показать. Напротив, sw_hide уберет окно с экрана.
16. Оконный дескриптор, сообщение и событие
Объект в Windows является некоторой сложной структурой,
которая представляет системный ресурс, такой как файл,
поток, графическое изображение.
Приложение не может обращаться напрямую к внутренней
структуре объекта или системным ресурсам, которые он
представляет.
Вместо этого, приложение должно получить специальный
дескриптор (handle) объекта и использовать этот дескриптор
для работы с системным ресурсом. В Microsoft Win32
программном интерфейсе приложений (WinAPI)
дескрипторы применяются как непрямые указатели.
17. Оконный дескриптор, сообщение и событие
Оконный дескриптор (hWnd) является уникальным
идентификатором (который является целым
четырехбайтовым беззнаковым числом), который
присваивает Windows каждому созданному окну.
В этом случае, под окном подразумевается любые элементы:
от кнопок управления и надписей до диалоговых окон и окон
в целом.
18. Оконный дескриптор, сообщение и событие
Windows посылает специальные, определенные системой,
сообщения при взаимодействии с приложением.
Она использует эти сообщения для управления действиями
приложения и для предоставления ввода и прочей
информации, нужной для работы приложения.
Приложения также могут отправлять такие сообщения для
различных целей, например, для управления окнами,
созданными на основе заранее зарегистрированных оконных
классов.
19. Оконный дескриптор, сообщение и событие
Практически каждому сообщению в Windows сопоставлено
событие в Lazarus в LCL и/или в Delphi в VCL (или другой
IDE), при поступлении которого можно выполнить
специальные действия.
Например, для события создание формы приложения есть
обработчик события FormCreate:
procedure TMainForm.FormCreate(Sender: TObject);
begin
end;
20. Lazarus, Delphi, Pascal и все-все-все
PASCAL =
Язык
программи-
рования
Object Pascal Free Pascal
+ +
Visual Component
Library
Lazarus Component
Library
= Delphi = Lazarus
Среды разработки
21. Оконный дескриптор, сообщение и событие
Каждое системное сообщение имеет уникальный
идентификатор сообщения (номер) и соответствующее ему
название (определенное в заголовочном файле), которое
показывает назначение сообщения.
Например, сообщение с названием WM_PAINT просит окно
перерисовать свое содержимое.
Название сообщения описывает также и категорию, к которой
это сообщение принадлежит. Приставка в названии
определяет тип окна, которое может прочитать и обработать
это сообщение. Например, приставка WM_ обозначает, что
сообщение предназначается обычному окну.
22. Оконный дескриптор, сообщение и событие
Сообщения для обычных окон включают в себя множество
информационных сообщений и запросов, таких, как
сообщения от мышки и клавиатуры, выбор элементов меню и
диалоговых окон, создание и управление окнами,
динамический обмен данными (dynamic data exchange -
DDE).
Приложение может создавать сообщения, которые могут
использовать для своих внутренних нужд или для
взаимодействия с окнами других процессов. В случае, если
приложение создает свои собственные сообщения, оконная
функция, которая принимает их, должна интерпретировать
эти сообщения и соответствующим образом их обработать.
23. Обработка стандартных сообщений
Процедура WinMain должна содержать фрагмент,
отвечающий за взаимодействие программы с ОС, то есть за
обработку всех сообщений, посылаемых от ОС к программе.
Для облегчения создания такого обработчика практически все
классы (в частности, окна) содержат свои «минимальные»
обработчики (например, окно «знает», что его можно
перетаскивать за заголовок), так что можно обойтись
использованием этих стандартных средств.
24. Обработка стандартных сообщений
{ получить очередное сообщение }
while GetMessage (msg,0,0,0) do
begin
TranslateMessage(msg); {Windows транслирует сообщения от
клавиатуры}
DispatchMessage(msg); {Windows вызовет оконную процедуру}
end; {выход по wm_quit, на которое GetMessage вернет FALSE}
Функция GetMessage типа BOOL извлекает сообщение из
очереди. Сообщение WM_QUIT означает запрос на закрытие
приложения и генерируется, когда приложение вызывает
функцию PostQuitMessage. Оно заставляет функцию GetMessage
возвращать нуль.
25. Оконная процедура
Для «собственных» действий придется писать отдельный
обработчик. Он представляет собой процедуру,
«закрепленную» за экземпляром окна и называемую оконной
процедурой. Оконная процедура должна анализировать
нужные ей сообщения и соответствующим образом их
обрабатывать.
26. Оконная процедура
Для «собственных» действий придется писать отдельный
обработчик. Он представляет собой процедуру,
«закрепленную» за экземпляром окна и называемую оконной
процедурой. Оконная процедура должна анализировать
нужные ей сообщения и соответствующим образом их
обрабатывать.
27. Оконная процедура
Эта процедура будет вызываться всякий раз, как ОС адресует
программе (ее окну) какое-либо сообщение.
Например, мы хотим, чтобы при нажатии клавиши «вверх»
некая переменная увеличивалась на 10.
В этом случае нам придется обрабатывать сообщение
wm_keydown, анализировать код клавиши и, в случае его
соответствия значению vk_up («вверх»), выполнять действие
увеличения переменной.
28. Оконная процедура
В нашем случае оконная процедура называется WndProc и
ссылка на нее присутствует в теле процедуры WinMain при
задании значений параметров класса:
wndClass.lpfnWndProc := @WndProc.
Заголовок оконной процедуры (функции), описываемый
строго по требованиям windows, таков:
function WndProc(hWnd: THandle; Msg: integer; wParam:
longint; lParam: longint): longint; stdcall;
В качестве параметров оконная процедура получает хэндл
окна, которому она принадлежит, сообщение ОС, для
обработки которого она была вызвана, и два параметра,
несущие дополнительную информацию об этом сообщении.
Следует заметить также, что эта функция должна
использовать опережающее описание и быть описана в
самом начале программы.
29. Оконная процедура
В конце функции обязательно должен стоять вызов
стандартного обработчика – функции DefWindowProc
(обеспечивает обработку значения по умолчанию для любого
сообщения окна которое прикладная программа не
обрабатывает) с тем, чтобы ни одно сообщение не оставалось
необработанным.
Таким образом, простейшая оконная процедура выглядит так:
function WndProc (hWnd: THandle; Msg: integer; wParam:
longint; lParam: longint): longint; stdcall;
begin
result := DefWindowProc(hwnd,msg,wparam,lparam);
end;
30. Структура сообщений
Все сообщения представляют собой предобъявленные
(«забитые» в Windows) именованные числовые константы,
начинающиеся с префикса wm_.
Для различных сообщений смысл и значения параметров
wParam и lParam различаются. Н
Например, для сообщения WM_KEYDOWN wParam –
виртуальный код нажатой клавиши, а lParam –
соответствующие специальным образом закодированные
данные; для сообщения WM_QUIT wParam – код выхода,
передаваемый в функцию PostQuitMessage; для
WM_LBUTTONDOWN (передается при нажатии левой кнопки
мыши) wParam – флаг, передающий код кнопки, младшие
разряды lParam – координаты курсора по горизонтали,
старшие – по вертикали и т.п.
31. Приложение Пустое окно
См. код в файле Empty.lpr
Примечание: чтобы создать программу на чистом WinAPI в
lazarus можно:
1) Выбрать тип проекта приложение, удалить из проекта unit
для формы, а в код проекта заменить на код из Empty.lpr
2) Создать консольное приложение и добавить код из
Empty.lpr. Тогда при запуске будет еще и консольное окно.
33. Создание оконного приложения в Lazarus
См. код:
EnumWindows.pas – функция выводит на экран и в
файл список всех запущенных окон (дескриптор, класс,
имя)
ControlWindow.pas – программа управления оконным
приложением SimpleGUI.
34. Домашнее задание
Источники [1] и [2] лабы №1:
Повторить базовые понятия программирования в
Pascal: процедуры, функции, передача параметров,
указатели, динамическое выделение памяти,
глобальные и локальные переменные.
Проработать самостоятельно материал Главы 6 из [1].
Используя helprus, help, интернет (при поиске
вбивать WinAPI Delphi) проработать функции WinApi,
используемые в примерах. В word создать справку с
подробным описанием назначения, входных
параметров, возвращаемого значения, таблицу по
типам, таблицу по сообщениям. На оценку.
35. Функция Описание Параметры Возвращаемое
значение
GetClassName Считывает имя
класса окна.
Wnd:
Идентификатор
окна.
ClassName: Буфеp
для приема
имени класса.
MaxCount: Размер
буфера
Фактическое число
скопированных
символов;
0 - если ошибка