1 Метод WndProc
Задание 1.1. С помощью переопределения метода WndProc обработаем сообщение щелчка мыши в неклиентской области Формы (область–полоска за которую тянем окно мышкой, когда перемещаем окно–форму).
Создайте новый проект. Теперь просто переопределим метод WndProc. Напишите в
разделе public класса TForm1 следующее:
procedure WndProc(var Message:TMessage); override; //объявили прототип
Указали прототип. Здесь ключевое слово override указывает, на то, что мы создаём новый метод WndProc, который будет относиться именно к классу TForm1 изменяя старый метод WndProc унаследованный классом TForm1 от ближайшего потомка класса TCustomForm.
По значению поля Message.Msg будем идентифицировать полученное сообщение, и затем по собственному желанию можем обрабатывать его нужным способом. Как только обработали данное сообщение желательно вызвать родительский метод WndProc (с помощью директивы inherited) для обработки остальных сообщений в стандартном режиме.
Нажмите Ctrl+Shift+Cи у вас сформируется следующая заготовка процедуры:
Рис. 1Окно редактора кода содержащее заготовку обработчикаWndProc
Измените её следующим образом:
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg=WM_NCLButtonDBlClk then
MessageDlg('Получено сообщение о щелчке левой кнопкой мыши в неклиентской области '+#10#13+’Это полученное сообщение не предусмотрено данным приложением'
+#10#13+’Но обработано благодаря стандартному методу '+#10#13
+#10#13+'procedure WndProc(var Message:TMessage); override;'
+#10#13+#10#13+'умеющему работать с полученными сообщениями Windows'
+#10#13+#10#13
+' ключевое слово overrideозначает перегруженный (измененный) метод',
mtInformation,[mbOk],0);
inherited; {вызываем стандартный родительский обработчик сообщений, для обработки сообщений в стандартном режиме}
end;
Здесь с помощью директивы inherited вызываем стандартный родительский метод WndProcс тем же именем объявленный в ближайшем предке классаTForm1 классе TCustomForm. Который в свою очередь унаследовал этот метод от класса–предкаTWinControl, при этом класс TWinControl тоже наследует данный методWndProcот класса–предкаTControl. Именно в классе TControl данный метод является виртуальным и объявлен впервые следующим образом
procedure WndProc(var Message: TMessage); virtual;
Запустите программу. Щелкните двойным щелчком в верхней неклиентской области формы. Программа должна работать правильно. Вернитесь в режим программирования (РП)
Задание 1.2. С помощью переопределения метода WndProc обработаем сообщение движения Формы.
Здесь же внутри данного обработчика поместите ключевое слово inheritedв самый конец обработчика перед словомend, т.к. во многих случаях требуется обрабатывать сообщения в стандартном режиме после вмешательства в методWndProc.
Кроме того, скиньте на форму Shape1 и немного его растяните
Рис. 2Приложение, демонстрирующее получение им сообщений о движении окна
В разделе publicукажите переменнуюx:integerи в обработчикеonCreateпроинициализируете её нулемx:=0, а на форму сбросьтеlabel1, будем просто выводить туда увеличенное на 1 значение переменнойx, при каждом получении формой сообщения двигаться. Также при этом пусть форма мигает случайными цветами и сжимается по вертикали, а фигураShape1 будет менять свой вид случайно от круга до квадрата.
В обработчике WndProcдопишите к уже написанному ( inheritedне трогать, он должен всегда быть в конце передend ), следующее:
ifMessage.Msg=WM_MOVEthen// Ежели получено сообщение ДВИГАТЬСЯ
begin// То…
inc(x); // увеличиваемxна 1
label1.Caption:=IntToStr(x); // выводим его в label1
color:=random(100000); // Придаём форме случайный цвет
form1.Height:=form1.Height-x;//заставляем форму сжиматься по вертикали
//меняем вид фигуры через каждые 10 сообщений WM_MOVE
if x mod 10 =0 then Shape1.Shape:=TShapeType(Random(6)+1);
end;
Запустите программу. Двигайте форму. Программа должна работать правильно.
Вернитесь в РП.
Задание 1.3. С помощью переопределения метода WndProc обработаем сообщение получения Формой нажатия клавиши и получим значения виртуального и ASCII кода нажатой клавиши.
В обработчике WndProcдопишите к уже написанному следующее:
if Message.Msg=WM_CHAR
then
MessageDlg('WM_CHAR'+' ASCII = '+IntToStr(Message.WParam),
mtInformation,[mbOk],0);
if Message.Msg=WM_KEYDOWN then
MessageDlg('WM_KEYDOWN'+' Виртуальный код клавиши '+IntToStr(Message.WParam),
mtInformation,[mbOk],0);
Дело в том, что если принято сообщение WM_CHAR, то в полеWParamпеременнойMessageкак раз находитсяASCIIкод. Очевидно, что для другого сообщения в полеWParamбудет содержаться уже другая информация специфичная для этого другого сообщения.
Поэтому когда принимается сообщение WM_KEYDOWNто в полеWParamбудет помещён виртуальный код клавиши.
Запустите программу. Нажимаёте клавиши клавиатуры. Программа должна работать правильно. Вернитесь в РП.
Каждое сообщение является целым числом, удерживайте Ctrlи щёлкните наWM_KEYDOWN. Вы попадёте в модуль Messagesв котором каждому сообщению соответствует целое число записанное в шестнадцатеричном формате. Так, например WM_KEYDOWN = $0100;
Поэтому в обработчике вместо if Message.Msg=WM_KEYDOWN then… можно было бы написать
if Message.Msg=$0100 then …
Проверьте это. Программа должна работать правильно. Вернитесь вРП.
Задание 1.4. С помощью переопределения метода WndProc обработаем сообщение получения Формой щелчка мыши.Покажем, что если у объекта есть стандартные предусмотренные обработчики событий, то обработка этих же событий в стандартных предусмотренных обработчиках иногда вызывается позже, чем этих же событий, но в методе WndProc.
Нужно сказать, что любое событие это всегда, по сути, сообщение. Поэтому в некоторых случаях сообщение и событие можно считать синонимами.
Перейдите в обработчик события onMouseDown щелчка на форме. Напишите там следующее:
InputBox('onMouseDown','Я Предусмотренное событие обрабатываемое’ +‘стандартным’+’ обработчиком FormMouseDown’,' Обрабатываюсь позже, чем аналогичное из WndProc ');
Затем вернитесь в метод WndProcи допишите там к уже написанному следующее:
if Message.Msg=WM_LBUTTONDOWN then
InputBox('WM_LBUTTONDOWN','Я Сообщение щелчка кнопкой мыши на форме', ‘Обрабатываюсь раньше, чем предусмотренное т.к. обрабатываюсь в WndProc ');
Запустите программу. Щелкайте мышью. Программа должна работать правильно. Вернитесь в РП.