Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
методическое пособие для самостоятельных работ.doc
Скачиваний:
21
Добавлен:
16.11.2019
Размер:
2.89 Mб
Скачать

2.3. Окно редактора с готовым изображением указателя

2.6. Реакция на события от мыши и клавиатуры

2.6.1. События от мыши

Для большинства видимых компонентов определен набор обработчиков событий, связанных с мышью:

type

TMouseButton = (mbLeft, mbRight, mbMiddle) ;

TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft,

ssRight, ssMiddle, ssDouble);

TMouseEvent = procedure (Sender: TObject;

Button: TMouseButton;

Shift: TShiftState; X, Y: Integer) of object;

TMouseMoveEvent = procedure(Sender: TObject;

Shift: TShiftState; X, Y: Integer) of object;

TNotifyEvent = procedure (Sender: TObject) of object;

property OnMouseDown: TMouseEvent;

property OnMouseUp: TMouseEvent;

property OnMouseMove: TMouseMoveEvent;

property OnClick: TNotifyEvent;

property OnDblClick: TNotifyEvent;

Тип TMouseButton определяет одну из трех кнопок мыши: левую (mbLeft), правую (mbRigth) и среднюю (mbMiddle). Тип TShiftState содержит признаки, уточняющие обстоятельства возникновения события: ssShift - нажата клавиша Shift; ssAlt -нажата клавиша Alt; ssCtrl - нажата клавиша Ctrl; ssLeft - нажата левая кнопка мыши; ssRight - нажата правая кнопка; ssMiddle -нажата средняя кнопка; ssDouble - нажаты одновременно левая и правая кнопки.

Обработчики OnMouseDown и OnMouseUp определяют реакцию программы на соответственно нажатие и отпускание кнопки мыши, OnMouseMove - на перемещение указателя мыши над компонентом, OnClick и OnDblClick - соответственно на щелчок и двойной щелчок левой кнопки. Во всех обработчиках параметр Sender содержит ссылку на компонент, над которым произошло событие, а X и Y определяют координаты точки чувствительности указателя мыши в момент возникновения события в системе координат клиентской области родительского компонента. Cобытие OnClick возникает после OnMouseDown, но перед OnMouseUp, а событие OnDblClick возникает после OnMouseUp.

2.6.2. События от клавиатуры

События от мыши получают любые потомки TControl. В отличие от этого события от клавиатуры получают только некоторые оконные компоненты (потомки TWinControl). Обработка событий связана со следующими свойствами этих компонентов:

type

TShiftState = set of (ssShift, ssAlt, ssCtrl, ssLeft,

ssRight, ssMiddle, ssDouble) ;

TKeyEvent = procedure (Sender: TObject; var Key: Word;

Shift: TShiftState) of object;

TKeyPressEvent = procedure (Sender: TObject;

var Key: Char) of object;

property OnKeyDown: TKeyEvent;

property OnKeyUp: TKeyEvent;

property OnKeyPress: TKeyPressEvent;

Параметр Shift, как и в обработчиках событий от мыши, содержит уточняющие признаки. Параметр Key в обработчиках TKeyEvent содержит виртуальный код клавиши, а в обработчике TKeyPressEvent - ASCII-символ. Обработчики OnKeyDown и OnKeyUp перехватывают нажатие большинства клавиш клавиатуры, в то время как обработчик QnKeyPress - только нажатие алфавитно-цифровых клавиш. Получаемый им символ Key учитывает выбранный язык и нажатую клавишу Shift.

2.6.3. Клавиатура в ms-dos и Windows

Windows значительно “строже” относится к использованию клавиатуры, чем MS-DOS. Это может вызывать проблемы при переносе игровых приложений, а также приложений, созданных с помощью FoxPro или Clipper, в среду Delphi.

Если вы захотите сохранить устоявшиеся приемы использования клавиатуры в новой разработке, вам придется перехватывать сообщения Windows, так как только таким способом программа сможет опознать факт нажатия на системные клавиши Alt, Tab, Shift и т. п. Нажатие на остальные клавиши можно анализировать с помощью перехвата сообщений от клавиатуры в обработчиках ОnKеуXXX формы при установленном значении True в ее свойство KeyPreview. Например, пусть акселератор Alt+X используется в существующей программе для закрытия модального диалогового окна. Чтобы сконструированное вами окно закрывалось по этой команде, напишите для него такой Обработчик события OnKeyDown:

procedure TForm2.FormKeyDown(Sender: TObject;

var Key: Word; Shift: TShiftState) ;

begin

if (Key = ord('X')) and (ssAlt in Shift) then Close

end;

Во многих случаях можно использовать собственные клавиши-акселераторы Windows. К сожалению, такими клавишами снабжаются лишь опции меню, но связанные с ними (опциями) обработчики OnClick выполняются даже в том случае, когда опция меню не видна (ее свойство Visible имеет значение False). Этим можно воспользоваться, чтобы вставить в главное меню окна фиктивные невидимые опции, связав их с нужными акселераторами. Пусть, например, клавиша Button1 должна “нажиматься” при нажатии Ctrl+S. Поместите на форму главное меню (если его еще нет) и создайте в нем опцию-заголовок с произвольным именем, например, MyButton. В списке свойства ShortCut опции выберите Ctrl+S и установите False в ее свойство Visible. Теперь можно связать ее обработчик события OnClick непосредственно с Button1Click или написать такой обработчик:

procedure TForm2.MyButtonClick(Sender: TObject);

begin

ButtonlClick(Self)

end;

И хотя опция MyButton главного меню не видна, нажатие связанных с ней клавиш Ctrl+S вызовет срабатывание нужного обработчика. В этом случае форма может не перехватывать клавиатурный ввод.

Oбработчики ОnKеуXXX не реагируют на нажатие системных клавиш Windows, в том числе - клавиш смещения курсора. Происходит это из-за того, что умалчиваемая оконная функция программы осуществляет стандартную обработку соответствующих сообщений Windows. Оконная функция связывается с каждым программным окном. Ее назначение - осуществлять связь программы с Windows. В оконную функцию главного окна программы Windows помещает сообщения о наступлении того или иного события, в том числе - о нажатии на клавишу. Оконная функция главного окна передает это сообщение оконной функции окна с фокусом ввода, а та, в свою очередь - функции сфокусированного оконного компонента. Чтобы получать все адресованные программе сообщения Windows, необходимо использовать метод HookMainWindow глобального объекта-программы Application или его обработчик события OnMessage. Единственным параметром обращения к методу Application. HookMainWindow является имя функции типа

TWindowHook = function(var Message: TMessage): Boolean of object;

которая будет получать сообщение Message. Возвращаемый ею результат и возможные изменения сообщения Message игнорируются. Фактически функция получает сообщение параллельно с иконной функцией и не может воздействовать на обработку сообщения. В отличие от этого обработчик Application OnMessage

type

TMsg = packed record

hwnd: HWND; message: UINT; wParam: WPARAM; IParam: LPARAM;

time: DWORD; pt: TPoint;

end;

TMessageEvent = procedure (var Ms.g: TMsg;

var Handled: Boolean) of object;

property OnMessage: TMessageEvent;

может запретить стандартную обработку сообщения. Для этого ему передается параметр Handled, в который следует установить True, если дальнейшая обработка сообщения не нужна.

В переменных типа TMsg ядро Windows передает программе так называемые сообщения - небольшие пакеты данных, оповещающие программу о наступлении того или иного события, будь то нажатие на клавишу, перемещение мыши или наступление нужного момента времени. Три параметра этого пакета используются следующим образом: Message - код события, wParam и lParam - уточняющие параметры. Для сообщения о нажатии клавиши код Message определен константой WmKeyDown (256) или (при отпускании клавиши) WmKeyUp (257), параметр wParam содержит виртуальный код нажатой клавиши, а IParam - дополнительные параметры, такие как количество нажатий клавиши с момента последнего обращения к функции перехвата, признак нажатой и удерживаемой Shift-клавиши и т. п.

Вот как, например, можно использовать клавиши курсора для смещения изображения (квадрата) в компоненте PaintBox:

type

TFormI = class(TForm)

PaintBoxl: TPaintBox;

procedure FormCreate(Sender: TObject);

procedure FormDestroy(Sender: TObject);

procedure PaintBoxIPaint(Sender: TObject);

private

{ Private declarations }

public .

{ Public declarations }

X, Y: Integer;

procedure Hook(var Msg: TMsg; var Handled: Boolean);end;

procedure TForm1.FormCreate(Sender: TObject);

{Регистрируем обработчик OnMessage в момент создания главного окна программы и устанавливаем начальное положение квадрата}

begin

Application.OnMessage := Hook;

X := 100; Y := 100; end;

procedure TFormI.Hook(var Msg: TMsg; var Handled: Boolean);

begin

if Msg.Message<>wm_keyDown then //Сообщение от клавиатуры?

Exit; //Нет case Msg.wParam of

vk_Left: dec(X,10); //Смещение влево

vk_Right: inc(X,10);//Смещение вправо

vk Up: dec(Y,10); //Смещение вверх

vk_Down: inc(Y,10); //Смещение вниз

end;

Paintbox1.Repaint;

Handled := True; //Блокируем дальнейшую обработку

end;

procedure TForm1.PaintBox1Paint(Sender: TObject);

(Вычерчиваем квадрат со стороной 20 пикселей и центром в точке X, Y}

begin

with PaintBox1.Canvas do

Rectangle(X-10,Y-10,X+10,Y+10)

end;