ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 02.12.2020
Просмотров: 112
Скачиваний: 1
Лекция № 7 DELPHI (конспекты лекций)
События в Delphi
-
События в Delphi
Одна из ключевых целей среды визуального программирования - скрыть от пользователя сложность программирования в Windows. Delphi предоставляет полный доступ к подструктуре событий, предоставляемой Windows. С другой стороны, Delphi упрощает программирование обработчиков таких событий.
Объекты из библиотеки визуальных компонент (VCL) Delphi, равно как и объекты реального мира, имеют свой набор свойств и свое поведение - набор откликов на события, происходящие с ними. Список событий для данного объекта, на которые он реагирует, можно посмотреть, например, в Инспекторе Объектов на странице событий. (На самом деле, на этой странице представлен список свойств, которые имеют тип вроде TMouseMoveEvent и представляют из себя процедуры-обработчики событий.
Существует соглашение по названиям данных свойств. Например, OnDblClick соответствует двойному щелчку мыши, а OnKeyUp - событию, когда нажатая клавиша была отпущена.) Среди набора событий для различных объектов из VCL есть как события, портируемые из Windows (МouseMove, KeyDown), так и события, порождаемые непосредственно в программе (DataChange для TDataSource).
Поведение объекта определяется тем, какие обработчики и для каких событий он имеет. Создание приложения в Delphi состоит из настройки свойств используемых объектов и создания обработчиков событий.
Простейшие события, на которые иногда нужно реагировать - это, например, события, связанные с мышкой (они есть практически у всех видимых объектов) или событие Click для кнопки TButton.
Предположим, что вы хотите перехватить щелчок левой кнопки мыши на форме.
Чтобы сделать это - создайте новый проект, в Инспекторе Объектов выберите страницу событий и сделайте двойной щелчок на правой части для свойства OnClick. Вы получите заготовку для обработчика данного события:
procedure TForm1.FormClick(Sender: TObject);
begin
MessageDlg('Hello', mtInformation, [mbOk], 0);
end;
Каждый раз, когда делается щелчок левой кнопки мыши над формой, будет появляться окно диалога.
Синтаксис функции MessageDlg.
function MessageDlg(const Msg: WideString; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons; HelpCtx: Longint; DefaultBtn: TMsgDlgBtn = mbNone; Bitmap: TBitmap = nil): Integer; overload;
Значения аргумента Buttons: TMsgDlgBtn перечисляются через запятую в квадратных скобках.
Значения аргумента Buttons: TMsgDlgBtn |
Возвращаемые значения |
mbOk |
mrOk |
mbCancel |
mrCancel |
mbYes |
mrYes |
mbNo |
mrNo |
mbAbort |
mrAbort |
mbRetry |
mrRetry |
mbIgnore |
mrIgnore |
При возникновении события, операционная система передает не только уведомление о нем, но и некоторую связанную с ним информацию. Например, при возникновении события “нажата левая кнопка мыши” программа информируется о том, в каком месте это произошло. Если вы хотите получить доступ к такой информации, то должны вернуться в Инспектор Объектов и создать обработчик события OnMouseDown:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
Canvas.TextOut(X, Y, 'X='+IntToStr(X)+' Y='+IntToStr(Y));
end;
Используются аргументы следующих типов:
type TMouseButton = (mbLeft, mbRight, mbMiddle); // Нажатая клавиша мыши.
type TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble); // Нажатая клавиша клавиатуры или кнопка мыши.
ssLeft Нажата левая кнопка мыши.
ssRight Нажата правая кнопка мыши.
ssMiddle Нажата средняя кнопка мыши.
ssDouble Двойной щелчок кнопкой мыши.
X,Y : координаты текущего положения мыши.
Мышкой не обязательно и щелкать.
Пример. Отображение в Label1 и Label2 текущих координат указателя мыши.
procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
label1.Caption:=IntToStr(x);
label2.Caption:=IntToStr(y);
end;
Можно проанализировать и события связанные с нажатием клавиш на клавиатуре. Например, можно создать обработчик для OnKeyDown (нажата клавиша):
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
label3.Caption:=Chr(Key);
end;
Правда, будут отображаться только заглавные буквы латинского алфавита, арабские цифры и некоторые символы.
Для отображения не только латинских, но и русских букв достаточно следующей процедуры.
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
Label1.Caption:=Key
end;
Перемещение рисунка с помощью клавиш управления курсором можно организовать следующим образом.
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
label1.caption:=inttostr(key);
Case key of
39: Form1.Image1.left:= Form1.Image1.left+2;
37: Form1.Image1.left:= Form1.Image1.left-2;
38: Form1.Image1.Top:= Form1.Image1.Top-2;
40: Form1.Image1.Top:= Form1.Image1.Top+2;
34: Begin
Form1.Image1.left:= Form1.Image1.left+2;
Form1.Image1.Top:= Form1.Image1.Top+2;
end
end
end;
Созданное сообщение, в этом случае, пересылается в некую процедуру DefWindowProc окна (default window procedure). DefWindowProc - аналог процедуры HandleEvent из примера, приведенного выше.
Каждое окно в Windows имеет свою DefWindowProc. Чтобы полностью понять данное утверждение, представьте, что каждая кнопка, каждый ListBox, каждое поле ввода и т.д. на самом деле являются окнами и имеют свою процедуру DefWindowProc. Это очень гибкая и мощная система, но она может заставить программиста писать очень сложный код. Delphi дает возможность быть защищенным от такой структуры программы.
Почти все, что происходит в Windows принимает форму сообщений и, если вы хотите их использовать в Delphi (в большей мере это необходимо при написании своих собственных компонент), то нужно понять, как эти сообщения работают.
Если посмотреть на DefWindowProc в справочнике по Windows API, то можно увидеть следующее определение:
function DefWindowProc(Wnd: HWnd; Msg, wParam: Word; lParam: LongInt);
Каждое сообщение, посылаемое в окно, состоит из четырех частей: первая часть - handle окна, получающего сообщение, Msg сообщает, что произошло а третья и четвертая части (wParam и lParam) содержат дополнительную информацию о событии. Вместе эти четыре части являются аналогом показанной выше структуры TEvent.
Вторая часть сообщения имеет длину 16 бит и сообщает, что за событие произошло. Например, если нажата левая кнопка на мыши, то переменная Msg содержит значение WM_LBUTTONDOWN.
Существуют десятки различного типа сообщений, и они называются вроде WM_GETTEXT, WM_HSCROLL, WM_GETTEXTLENGTH и т.п. Список всех сообщений можно видеть в справочнике по Windows API (on-line help).
Последние две переменные, длиной 16 и 32 бита, называются wParam и lParam. Они сообщают программисту важную дополнительную информацию о каждом событии. Например при нажатии кнопки мыши, lParam содержит координаты указателя мыши.
Одна из хитростей заключается в том, как выделить нужную информацию из этих переменных. В большинстве случаев Delphi освобождает вас от необходимости выполнять данную задачу. Например, в обработчике события OnMouseDown для формы вы просто используете координаты X и Y. Как программисту, вам не нужно прилагать усилия для получения сообщения и связанных с ним параметров.
Все, что связано с событиями, представлено в простом и непосредственном виде:
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
Т.о. Windows является системой ориентированной на события. События в Windows принимают форму сообщений;
В недрах VCL Delphi сообщения Windows обрабатываются и преобразуются в более простую для программиста форму; обработка событий в Delphi сводится к написанию для каждого объекта своих обработчиков; события в программе на Delphi вызываются не только сообщениями Windows, но и внутренними процессами.
Нельзя придумать такую библиотеку объектов, которые бы полностью соответствовали потребностям программистов. Всегда возникнет необходимость дополнения или изменения свойств и поведения объектов. В этом случае, так же, как и при создании своих собственных компонент в Delphi, часто требуется обрабатывать сообщения Windows. Поскольку Object Pascal является развитием и продолжением Borland Pascal 7.0, то это выполняется сходным с BP способом.
Общий синтаксис для декларации обработчика сообщений Windows:
procedure Handler_Name(var Msg : MessageType);
message WM_XXXXX;
Handler_Name обозначает имя метода; Msg - имя передаваемого параметра; MessageType - какой либо тип записи, подходящий для данного сообщения; директива message указывает, что данный метод является обработчиком сообщения; WM_XXXXX - константа или выражение, которое определяет номер обрабатываемого сообщения Windows.
Рассмотрим обработку сообщений на примере. Например, при нажатии правой кнопки мыши на форме в программе появляется всплывающее меню (pop-up menu, если оно было привязано к этой форме). Программист может захотеть привязать к правой кнопке какое-нибудь другое событие. Это можно сделать так:
type
TForm1 = class(TForm)
PopupMenu1: TPopupMenu;
MenuItem1: TMenuItem;
MenuItem2: TMenuItem;
MenuItem3: TMenuItem;
private
{ Private declarations }
procedure WMRButtonDown(var Msg : TWMMouse);
message WM_RBUTTONDOWN;
public { Public declarations }
end;
Далее, в секции implementation нужно написать обработчик:
procedure TForm1.WMRButtonDown(var Msg : TWMMouse);
begin
MessageDlg('Right mouse button click.', mtInformation, [mbOK], 0);
end;
В данном случае при нажатии правой кнопки мыши будет появляться диалог.
У класса TForm уже есть унаследованный от дальнего предка обработчик данного события, который называется также и вызывает Popup меню. Если в новом обработчике сообщения нужно выполнить действия, которые производились в старом, то для этого применяется ключевое слово inherited. Если модифицировать обработчик, то после диалога будет появляться Popup меню:
procedure TForm1.WMRButtonDown(var Msg : TWMMouse);
begin
MessageDlg('Right mouse button click.', mtInformation, [mbOK], 0);
inherited;
end;
Есть способ обработки всех сообщений, которые получает приложение. Для этого используется свойство OnMessage объекта Application, который автоматически создается при запуске программы. Если определен обработчик события OnMessage, то он получает управление при любом событии, сообщение о котором направлено в программу. Следующий код будет приводить к появлению диалога при двойном щелчке мыши на любом объекте в приложении.
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage:=AOM;
end;
procedure TForm1.AOM(var Msg: TMsg; var Handled: Boolean);
begin
Handled:=False;
if Msg.Message = WM_LBUTTONDBLCLK
then begin
MessageDlg('Double click.', mtInformation, [mbOK], 0);
Handled:=True;
end;
end;
Конечно, в обработчике нельзя выполнять операции, требующие длительного времени, поскольку это приведет к замедлению выполнения всего приложения.