Главная » Delphi » Обработка щелчков мышью

0

При  работе с индикаторами одной  из наиболее сложных задач является обеспече ние  правильной обработки щелчков мышью.  Как можно  заметить, многие  индикато ры панели  задач реагируют на щелчки  мышью тремя  различными способами:

•   открывают окно при одинарном щелчке;

•   открывают другое окно (обычно окно свойств) при двойном щелчке;

•   вызывают контекстное меню при щелчке  правой кнопкой.

Проблема заключается в создании события, представляющего двойной щелчок мыши без предварительного события одиночного щелчка.

В системе сообщений Windows,  при  выполнении пользователем двойного щелчка левой   кнопкой  мыши,   обладающее  фокусом   окно   получит   сразу  два  сообщения: WM_LBUTTONDOWN (нажата левая  кнопка) и WM_LBUTTONDBLCLK (двойной щелчок  на левой   кнопке). Для  того  чтобы   позволить программе обработать только   двойной щелчок  мышью,  необходимо предусмотреть механизм задержки обработки  сообще ния  WM_LBUTTONDOWN на период времени, достаточный, чтобы  убедиться  в отсутст на период времени, достаточный, чтобы убедиться в отсутствии сообщения о вы

полнении двойного щелчка.

Нетрудно определить период ожидания, необходимый для того,  чтобы  убедиться  в отсутствии сообщения WM_LBUTTONDBLCLK после  сообщения WM_LBUTTONDOWN. Для этого  используется функция API GetDoubleClickTime(), которая не имеет  никаких параметров и возвращает максимальный промежуток времени (в миллисекундах) ме жду двумя щелчками двойного щелчка  мышью,  допускаемый панелью управления (Control Panel). Для  построения  механизма ожидания, устанавливаемого на  основа нии периода ожидания в миллисекундах, возвращаемого функцией GetDouble- ClickTime(), применяется компонент TTimer. Он создается и инициируется в кон структоре компонента TTrayNotifyIcon следующим образом:FTimer := TTimer.Create(Self);

with FTimer do begin

Enabled := False;

Interval := GetDoubleClickTime;

OnTimer := OnButtonTimer;

end;

По  истечении  периода  ожидания  вызывается  метод   OnButtonTimer(),  Более подробная информация об этом методе приведена далее в настоящей главе.

Как уже говорилось, сообщения панели задач фильтруются методом TrayWndProc()

глобального объекта IconMgr. Рассмотрим код данного метода.

procedure TIconManager.TrayWndProc(var Message: TMessage);

{ Позволяет обрабатывать все "обратные" сообщения панели задач в

контексте компонента. }

var

Pt: TPoint;

TheIcon: TTrayNotifyIcon;

begin

with Message do begin

{ Если это обратное сообщение от панели задач. }

if (Msg = DDGM_TRAYICON) then begin

TheIcon := TTrayNotifyIcon(WParam);

case lParam of

{ Запустить таймер при первом щелчке мышью. Событие

OnClick будет передано методом OnTimer, гарантируя, что

двойного щелчка не было. }

WM_LBUTTONDOWN: TheIcon.FTimer.Enabled := True;

{ Сбросить флаг двойного щелчка. Это предотвратит

одиночный щелчок. }

WM_LBUTTONDBLCLK: begin

TheIcon.FNoShowClick := True;

if Assigned(TheIcon.FOnDblClick) then

TheIcon.FOnDblClick(Self);

end;

WM_RBUTTONDOWN: begin

if Assigned(TheIcon.FPopupMenu) then begin

{ Вызвать функцию SetForegroundWindow, необходимую API }

SetForegroundWindow(IconMgr.HWindow);

{ Открыть контекстное меню в позиции курсора. }

GetCursorPos(Pt);

TheIcon.FPopupMenu.Popup(Pt.X, Pt.Y);

{ Отправить сообщение, необходимое API для

переключения задач. }

PostMessage(IconMgr.HWindow, WM_USER, 0, 0);

end;

end;

end;            // case

end             // if

else

{ Если сообщение не относится к панели задач, то вызвать

процедуру DefWindowProc. }

Result := DefWindowProc(FHWindow, Msg, wParam, lParam);end; // with end;

В этом  фрагменте кода задана  реакция на сообщения, передаваемые различными событиями: при  одинарном щелчке  просто запускается таймер, при  двойном —  уста навливается флаг  двойного щелчка   перед   передачей события OnDblClick, а  при щелчке  правой кнопкой мыши  вызывается контекстное меню,  определяемое свойст вом PopupMenu. Теперь рассмотрим метод  OnButtonTimer(), код которого приве ден ниже.

procedure TTrayNotifyIcon.OnButtonTimer(Sender: TObject);

begin

{ Отключить таймер, ведь он нужен только при первом щелчке. }

FTimer.Enabled := False;

{ Если второго щелчка так и не последовало, то передать

одиночный щелчок. }

if (not FNoShowClick) and Assigned(FOnClick) then

FOnClick(Self);

FNoShowClick := False;       // Сбросить флаг

end;

В первую  очередь этот  метод  отключает таймер, гарантируя, что  щелчок  мыши создаст только  одно событие. Затем  проверяется состояние флага  FNoShowClick. Помните, что  такой  флаг  устанавливается в методе  OwnerWndProc() при  обработке сообщения, вызванного двойным щелчком мыши.  Таким  образом, событие OnClick будет создано  только  при условии отсутствия события OnDblClk.

Источник: Тейксейра, Стив, Пачеко, Ксавье.   Borland Delphi 6. Руководство разработчика. : Пер.  с англ. — М. : Издательский дом “Вильямс”, 2002. —  1120 с. : ил. — Парал. тит. англ.

По теме:

  • Комментарии