У меня есть PopupMenu в моем приложении, которое появляется, когда пользователь щелкает правой кнопкой мыши значок моего приложения.Автоматическое скрытие или закрытие меню PopUp, когда указатель мыши находится за его пределами - Delphi
Когда я щелкаю правой кнопкой мыши по этому значку, всплывающее меню и ничего не делаю, мое приложение ведет себя как возобновление своей работы, потому что похоже, что оно ждет, пока я нажму на элемент меню.
Я хочу удалить это поведение. Я попытался установить PopupMenu, добавив процедуру Auto-Close, когда от пользователя не приходит ответ, и когда указатель мыши покидает PopupMenu.
Я также попытался добавить TTimer
, который закрывает мой TPopUpMenu
через определенное время, но закрывается после указанного мной времени, не глядя, указатель мыши находится внутри или вне PopupMenu.
два сценария я хочу достичь являются:
Я хочу
TPopUpMenu
закрыть, когда пользователь перемещает указатель мыши из него более двух-трех секунд.Когда пользователь перемещает указатель мыши внутри него, то
TPopupMenu
должен быть закрыт после того, как пять минут, потому что какой-либо пользователь должен ответить на PopupMenu в течение пяти минут.
Я попытался добавить следующий код с TTimer
обработчик события моего приложения, что открывает PopupMenu, когда правая кнопка мыши пользователя на Tray Icon, но PopupMenu всегда закрывается через две секунды:
procedure TMainForm_1.SysTrayIconMessageHandler(var Msg: TMessage);
var
SysTrayTimer: TTimer;
PT: TPoint;
begin
case Msg.LParam of
WM_.....:;
WM_RBUTTONDOWN:
begin
GetCursorPos(PT);
SysTrayTimer.Enabled := True;
SysTrayTimer.Interval := 2500;
SystemTrayPopUpMenu.PopUp(PT.X, PT.Y);
SystemTrayPopUpMenu.AutoLineReduction := maAutomatic;
end;
end;
end;
procedure TMainForm_1.OnSysTrayTimer(Sender: TObject);
begin
SysTrayTimer.Enabled := False;
SendMessage(PopupList.Window, WM_CANCELMODE, 0, 0);
end;
Я также читал this, но после того, как я добавил код, ничего не изменилось.
По крайней мере, я должен быть в состоянии сделать это: закройте PopupMenu после того, как пользователь откроет его, щелкнув правой кнопкой мыши и перемещая указатель мыши за его пределы.
Это, как я добавил новый код для достижения этой цели:
unit MainForm_1;
interface
uses
Windows, SysUtils, Messages, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ExtCtrls, Menus, ImgList;
type
TMainForm_1 = class(TForm);
SystemTrayPopUpMenu: TPopUpMenu;
ExitTheProgram: TMenuItem;
RestoreFromSystemTray: TMenuItem;
ReadTheInstructions: TMenuItem;
Separator1: TMenuItem;
TrackSysTrayMenuTimer: TTimer;
CloseSysTrayMenuTimer: TTimer;
procedure OnTrackSysTrayMenuTimer(Sender: TObject);
procedure OnCloseSysTrayMenuTimer(Sender: TObject);
procedure SysTrayPopUpMenuPopUp(Sender: TObject);
private
MouseInSysTrayPopUpMenu: Boolean;
IconData: TNotifyIconData;
procedure SysTrayIconMsgHandler(var Msg: TMessage); message TRAY_CALLBACK;
procedure AddSysTrayIcon;
procedure DisplayBalloonTips;
procedure ApplySystemTrayIcon;
procedure DeleteSysTrayIcon;
public
IsSystemTrayIconShown: Boolean;
end;
var
MainForm_1: TMainForm_1;
implementation
uses
ShlObj, MMSystem, ShellAPI, SHFolder,.....;
procedure TMainForm_1.SysTrayIconMsgHandler(var Msg: TMessage);
var
PT: TPoint;
begin
case Msg.LParam of
WM_MOUSEMOVE:;
WM_LBUTTONUP:;
WM_LBUTTONDBLCLK:;
WM_RBUTTONUP:;
WM_RBUTTONDBLCLK:;
WM_LBUTTONDOWN:;
NIN_BALLOONSHOW:;
NIN_BALLOONHIDE:;
NIN_BALLOONTIMEOUT:;
NIN_BALLOONUSERCLICK:;
WM_RBUTTONDOWN:
begin
GetCursorPos(PT);
SetForegroundWindow(Handle);
SystemTrayPopUpMenu.OnPopup := SysTrayPopUpMenuPopUp;
SystemTrayPopUpMenu.PopUp(Pt.X, Pt.Y);
PostMessage(Handle, WM_NULL, 0, 0);
TrackSysTrayMenuTimer.Enabled := False;
CloseSysTrayMenuTimer.Enabled := False;
end;
end;
end;
procedure TMainForm_1.SysTrayPopUpMenuPopup(Sender: TObject);
begin
MouseInSysTrayMenu := True;
TrackSysTrayMenuTimer.Interval := 100;
TrackSysTrayMenuTimer.OnTimer := OnTrackSysTrayMenuTimer;
TrackSysTrayMenuTimer.Enabled := True;
CloseSysTrayMenuTimer.Interval := 300000;
CloseSysTrayMenuTimer.OnTimer := OnCloseSysTrayMenuTimer;
CloseSysTrayMenuTimer.Enabled := True;
end;
procedure TMainForm_1.OnTrackSysTrayMenuTimer(Sender: TObject);
var
hPopupWnd: HWND;
R: TRect;
PT: TPoint;
begin
hPopupWnd := FindWindow('#32768', nil);
if hPopupWnd = 0 then Exit;
GetWindowRect(hPopupWnd, R);
GetCursorPos(Pt);
if PtInRect(R, Pt) then begin
if not MouseInSysTrayMenu then begin
MouseInSysTrayMenu := True;
CloseSysTrayMenuTimer.Interval := 300000;
end;
end else begin
if MouseInSysTrayMenu then begin
MouseInSysTrayMenu := False;
CloseSysTrayMenuTimer.Interval := 2500;
end;
end;
end;
procedure TMainForm_1.OnCloseSysTrayMenuTimer(Sender: TObject);
begin
CloseSysTrayMenuTimer.Enabled := False;
SendMessage(PopupList.Window, WM_CANCELMODE, 0, 0);
end;
Как два TTimers
используются в MainForm экране приложения:
Как присвоенного TrackSysTrayMenuTimer
значения свойств .....
Как я присвоил CloseSysTrayMenuTimer
«s значения свойств .....
Я также получил Exception сообщение, как это .....
Это сообщение, которое я написал, как это, чтобы проверить, что происходит сбой в Кодексе ..... Так что с этим я могу определить, если FindWindow
не удается или нет .....
...
hPopupWnd := FindWindow('#32768', nil);
if hPopupWnd = 0 then
begin
TrackSysTrayMenuTimer.Enabled := False;
if ShowErrors = True and TestingMode = True then
Application.MessageBox('The PopUp Menu "SystemTrayPopUpMenu" could not be found.' +
' FindWindow will abort.', ' Exception Message', MB_ICONSTOP or MB_OK);
exit;
Последняя ошибка я получил:
Спасибо заранее.
Не будет ли запутать пользователей, что программа ведет себя по-разному от каждая другая программа? –
Да ........... Это мое плохое ........ Я исправлю это очень скоро, потому что это меня тоже смущает. – GTAVLover