@@ -47,6 +47,7 @@ TfrmMenu = class(TForm)
47
47
ActionList1: TActionList;
48
48
actSwitchAIChats: TAction;
49
49
JvApplicationHotKey3: TJvApplicationHotKey;
50
+ tmrDelayAction: TTimer;
50
51
51
52
procedure FormCreate (Sender: TObject);
52
53
procedure FormDestroy (Sender: TObject);
@@ -82,6 +83,7 @@ TfrmMenu = class(TForm)
82
83
procedure JvApplicationHotKey3HotKeyRegisterFailed (Sender: TObject;
83
84
var HotKey: TShortCut);
84
85
procedure JvApplicationHotKey3HotKey (Sender: TObject);
86
+ procedure tmrDelayActionTimer (Sender: TObject);
85
87
// procedure FormPaint(Sender: TObject);
86
88
private
87
89
{ Private declarations }
@@ -94,6 +96,15 @@ TfrmMenu = class(TForm)
94
96
FHookWndHandle: THandle;
95
97
FHookMsg: Integer;
96
98
99
+ { Mouse gestures }
100
+ FHotSpotEntered: Boolean;
101
+ FFirstKnockTime: TDateTime;
102
+ FKnockEnabled: Boolean;
103
+ FDelayEnabled: Boolean;
104
+ FActionPending: Boolean; // Prevent overlapping actions
105
+ FMousePosition: TPoint;
106
+ const KnockInteval = 0.5 / (24 * 60 * 60 ); // 500 milliseconds as TDateTime
107
+
97
108
procedure CreateParams (var Params: TCreateParams); override;
98
109
procedure HideMenu (Sender: TObject);
99
110
procedure RestoreRequest (var message: TMessage); message WM_USER + $1000 ;
@@ -139,8 +150,13 @@ TfrmMenu = class(TForm)
139
150
140
151
procedure OnAppLostFocus (Sender: TObject);
141
152
153
+ { Tightly coupled procedures for mouse actions }
142
154
procedure HotSpotAction (MousePos: TPoint);
155
+ function IsInHotSpot (const MPos: TPoint): Boolean;
156
+ procedure StartDelayedAction ;
143
157
property OnMenuArea: Boolean read FOnMenuArea write FOnMenuArea;
158
+ property MouseDelay: Boolean read FDelayEnabled write FDelayEnabled;
159
+ property MouseGesture: Boolean read FKnockEnabled write FKnockEnabled;
144
160
end ;
145
161
146
162
var
@@ -391,6 +407,19 @@ procedure TfrmMenu.SiteContextPopup(Sender: TObject; MousePos: TPoint;
391
407
end ;
392
408
end ;
393
409
410
+ procedure TfrmMenu.StartDelayedAction ;
411
+ begin
412
+ if not FDelayEnabled then
413
+ HotSpotAction(FMousePosition)
414
+ else
415
+ if not FActionPending then
416
+ begin
417
+ FActionPending := True;
418
+ tmrDelayAction.Interval := Settings.MouseDelayValue;
419
+ tmrDelayAction.Enabled := True;
420
+ end ;
421
+ end ;
422
+
394
423
procedure TfrmMenu.WMDisplayChange (var message: TMessage);
395
424
begin
396
425
// Resolution changed
@@ -497,8 +526,8 @@ procedure TfrmMenu.HideMenu(Sender: TObject);
497
526
end ;
498
527
499
528
procedure TfrmMenu.HotSpotAction (MousePos: TPoint);
500
- var
501
- TypesAniPlugin: TAQPSystemTypesAnimations;
529
+ // var
530
+ // TypesAniPlugin: TAQPSystemTypesAnimations;
502
531
begin
503
532
if Settings.DisableOnFullScreenDirectX and DetectFullScreen3D then Exit;
504
533
if Settings.DisableOnFullScreen and DetectFullScreenApp(GetForegroundWindow) then Exit;
@@ -520,18 +549,7 @@ procedure TfrmMenu.HotSpotAction(MousePos: TPoint);
520
549
NewAlphaBlend := MAXBYTE;
521
550
ShowMenuAnimation(ABE_LEFT);
522
551
end ;
523
- end
524
- else if (MousePos.X > frmMenu.Left + frmMenu.Width) and (tmrHideMenu.Enabled = False) then
525
- begin
526
- if OnMenuArea then
527
- begin
528
- OnMenuArea := False;
529
- NewWidth := 1 ;
530
- NewLeft := GetLeftMost;
531
- NewAlphaBlend := 0 ;
532
- ShowMenuAnimation(ABE_LEFT, False);
533
- end ;
534
- end ;
552
+ end ; // moved hide to rawinput
535
553
536
554
end ;
537
555
ABE_TOP:
@@ -551,18 +569,7 @@ procedure TfrmMenu.HotSpotAction(MousePos: TPoint);
551
569
NewAlphaBlend := MAXBYTE;
552
570
ShowMenuAnimation(ABE_RIGHT);
553
571
end ;
554
- end
555
- else if (MousePos.X < Left) and (tmrHideMenu.Enabled = False) then
556
- begin
557
- if OnMenuArea then
558
- begin
559
- OnMenuArea := False;
560
- NewWidth := 1 ;
561
- NewLeft := Screen.WorkAreaWidth - NewWidth;
562
- NewAlphaBlend := 0 ;
563
- ShowMenuAnimation(ABE_RIGHT, False);
564
- end ;
565
- end ;
572
+ end ; // moved hide to rawinput
566
573
567
574
end ;
568
575
ABE_BOTTOM:
@@ -866,6 +873,10 @@ procedure TfrmMenu.FormCreate(Sender: TObject);
866
873
AllowSetForegroundWindow(GetCurrentProcessId);
867
874
868
875
Application.OnDeactivate := OnAppLostFocus;
876
+
877
+ { Mouse behavior }
878
+ FDelayEnabled := Settings.MouseDelay;
879
+ FKnockEnabled := Settings.MouseGesture;
869
880
end ;
870
881
871
882
procedure TfrmMenu.FormDestroy (Sender: TObject);
@@ -1017,6 +1028,13 @@ procedure TfrmMenu.About1Click(Sender: TObject);
1017
1028
1018
1029
end ;
1019
1030
1031
+ procedure TfrmMenu.tmrDelayActionTimer (Sender: TObject);
1032
+ begin
1033
+ tmrDelayAction.Enabled := False;
1034
+ FActionPending := False;
1035
+ HotSpotAction(FMousePosition);
1036
+ end ;
1037
+
1020
1038
procedure TfrmMenu.tmrHideMenuTimer (Sender: TObject);
1021
1039
begin
1022
1040
if not tmrShowMenu.Enabled then
@@ -1078,6 +1096,19 @@ procedure TfrmMenu.FormShow(Sender: TObject);
1078
1096
ShowWindow(Application.Handle, SW_HIDE);
1079
1097
end ;
1080
1098
1099
+ function TfrmMenu.IsInHotSpot (const MPos: TPoint): Boolean;
1100
+ begin
1101
+ if (GetAsyncKeyState(VK_LBUTTON) = 0 ) and (GetAsyncKeyState(VK_RBUTTON) = 0 ) then
1102
+ begin
1103
+ case Settings.BarPosition of
1104
+ ABE_LEFT: Result := (MPos.X <= GetLeftMost + 1 );
1105
+ ABE_TOP:;
1106
+ ABE_RIGHT: Result := (MPos.X >= GetRightMost - 1 );
1107
+ ABE_BOTTOM:;
1108
+ end ;
1109
+ end ;
1110
+ end ;
1111
+
1081
1112
function TfrmMenu.IsStarteMenuVisible : Boolean;
1082
1113
var
1083
1114
startMenuOn: BOOL;
@@ -1353,8 +1384,8 @@ procedure TfrmMenu.ProcessRawInput(var Message: TMessage);
1353
1384
Mouse: RAWMOUSE;
1354
1385
1355
1386
Cur: THandle;
1356
- MPos: TPoint;
1357
1387
1388
+ NowTime: TDateTime;
1358
1389
begin
1359
1390
if GetRawInputData(HRAWINPUT(Message.lParam), RID_INPUT, nil , DataSize, SizeOf(Header)) = 0 then
1360
1391
begin
@@ -1369,20 +1400,100 @@ procedure TfrmMenu.ProcessRawInput(var Message: TMessage);
1369
1400
1370
1401
Cur := 0 ;
1371
1402
try
1372
- if not Windows.GetCursorPos(MPos ) then
1373
- MPos := Point(120 , 120 );
1403
+ if not Windows.GetCursorPos(FMousePosition ) then
1404
+ FMousePosition := Point(120 , 120 );
1374
1405
Cur := GetForegroundWindow; // it will likely fail on windows locked (Win+L)
1375
1406
except
1376
1407
Cur := 0 ;
1377
1408
end ;
1378
1409
1379
1410
if Cur <> 0 then
1380
1411
begin
1381
- HotSpotAction(MPos);
1412
+ NowTime := Now();
1413
+
1414
+ if IsInHotSpot(FMousePosition) then
1415
+ begin
1416
+ if not FHotSpotEntered and not FActionPending then
1417
+ begin
1418
+ // First entry into hot spot
1419
+ FHotSpotEntered := True;
1420
+
1421
+ if FKnockEnabled then
1422
+ begin
1423
+ if FFirstKnockTime = 0 then
1424
+ begin
1425
+ FFirstKnockTime := NowTime; // First knock time
1426
+ end
1427
+ else if NowTime - FFirstKnockTime <= KnockInteval then
1428
+ begin
1429
+ // Second knock within the interval
1430
+ FFirstKnockTime := 0 ; // Reset knock time
1431
+ StartDelayedAction;
1432
+ end
1433
+ else
1434
+ begin
1435
+ // Too late, reset knock
1436
+ FFirstKnockTime := NowTime;
1437
+ end ;
1438
+ end
1439
+ else
1440
+ begin
1441
+ // No knock-knock, just start delay
1442
+ StartDelayedAction;
1443
+ end ;
1444
+ end ;
1445
+ end
1446
+ else
1447
+ begin
1448
+ // Mouse left the hot spot
1449
+ FHotSpotEntered := False;
1450
+ // Hide if visible menu
1451
+ case Settings.BarPosition of
1452
+ ABE_LEFT:
1453
+ begin
1454
+ if (FMousePosition.X > frmMenu.Left + frmMenu.Width) and (tmrHideMenu.Enabled = False) then
1455
+ begin
1456
+ if OnMenuArea then
1457
+ begin
1458
+ OnMenuArea := False;
1459
+ NewWidth := 1 ;
1460
+ NewLeft := GetLeftMost;
1461
+ NewAlphaBlend := 0 ;
1462
+ ShowMenuAnimation(ABE_LEFT, False);
1463
+ end ;
1464
+ end ;
1465
+ end ;
1466
+ ABE_TOP:
1467
+ begin
1468
+
1469
+ end ;
1470
+ ABE_RIGHT:
1471
+ begin
1472
+ if (FMousePosition.X < Left) and (tmrHideMenu.Enabled = False) then
1473
+ begin
1474
+ if OnMenuArea then
1475
+ begin
1476
+ OnMenuArea := False;
1477
+ NewWidth := 1 ;
1478
+ NewLeft := Screen.WorkAreaWidth - NewWidth;
1479
+ NewAlphaBlend := 0 ;
1480
+ ShowMenuAnimation(ABE_RIGHT, False);
1481
+ end ;
1482
+ end ;
1483
+
1484
+ end ;
1485
+ ABE_BOTTOM:
1486
+ begin
1487
+
1488
+ end ;
1489
+ end ;
1490
+
1491
+ end ;
1492
+
1493
+
1494
+ // HotSpotAction(MPos);
1382
1495
end ;
1383
-
1384
1496
end ;
1385
-
1386
1497
end ;
1387
1498
finally
1388
1499
FreeMem(lRawInput);
0 commit comments