From 38947113f5336658eb703a5d3ffa1ede8c8bf080 Mon Sep 17 00:00:00 2001 From: Uladzimir Karpenka Date: Thu, 4 Jun 2026 20:59:17 +0300 Subject: [PATCH] Fix wheel over a VFO display tuning both that VFO and the active one TFreqDisplay.DoMouseWheel already tunes its own VFO per-digit when the wheel is used over it. But the form-level FormMouseWheel also fired for the same event (Cocoa routes the wheel to the form too) and tuned the active VFO, so scrolling over the VFO B display changed both B (via the widget) and A (via the form handler). Skip FormMouseWheel when the cursor is over either FreqDisplay; let the widget handle per-digit tuning there. Uses Mouse.CursorPos for the hit-test (the event's MousePos is not in screen coordinates on Cocoa). The form handler still tunes the active VFO over the spectrum/waterfall/empty areas. Pre-existing bug. Co-Authored-By: Claude Opus 4.8 --- MainForm.pas | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/MainForm.pas b/MainForm.pas index 76690e0..40f49f9 100644 --- a/MainForm.pas +++ b/MainForm.pas @@ -6859,16 +6859,30 @@ end; procedure TMainForm.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean); -// Колёсико на форме/спектре/водопаде — меняет VFO с квантованием +// Колёсико на форме/спектре/водопаде — меняет активный VFO с квантованием // Шаг зависит от модификаторов: Ctrl+Shift=1МГц, Ctrl=1кГц, Shift=10Гц, иначе 100Гц // Квантование: результат выровнен до кратного шагу (как в FreqDisplay) // CTUN логика: через ApplyVfoA + function OverFreqDisp(C: TControl): Boolean; + var P: TPoint; + begin + Result := False; + if (C = nil) or (not C.Visible) then Exit; + // Mouse.CursorPos — надёжные экранные координаты (переданный MousePos на + // Cocoa может быть не в экранной системе). + P := C.ScreenToClient(Mouse.CursorPos); + Result := (P.X >= 0) and (P.Y >= 0) and (P.X < C.Width) and (P.Y < C.Height); + end; var Step: Int64; Delta: Int64; Base: Int64; NewFreq: Int64; begin + // Над дисплеем VFO (A или B) колесо обрабатывает сам TFreqDisplay поразрядно + // (включая неактивный VFO). Не дублируем здесь, иначе менялись бы обе частоты: + // виджет крутил бы B, а этот хендлер — активный A. + if OverFreqDisp(FreqDispA) or OverFreqDisp(FreqDispB) then Exit; if (FController.FMode = MODE_FM) and FController.FFMStepOn and not ((ssCtrl in Shift) or (ssShift in Shift)) then Step := FM_STEP_HZ[FController.FFMStepIdx]