You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Delphi(FMX) HD应用中实现鼠标滚轮缩放功能?

FireMonkey Mouse Wheel Zoom Implementation & Usability Questions

Hi there! Let's break down your questions step by step—first solving the mouse wheel zooming issue, then addressing your FMX usability concerns.

Implementing Mouse Wheel Zoom for FMX Form

Your existing FormMouseWheel event is the right starting point. FMX does have scaling capabilities, but they work a bit differently than you might expect. Here's a practical implementation that scales your content around the mouse cursor for a natural zoom experience:

Option 1: Scale the Entire Form

If you want to zoom the entire main window, use this code in your event handler:

const
  ZoomStep = 0.1; // Adjust this value to control zoom sensitivity
  MinScale = 0.5; // Prevent zooming too far out
  MaxScale = 2.0; // Prevent zooming too far in

procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
var
  TargetScale: Single;
  MouseLocalPos: TPointF;
begin
  // Calculate desired scale based on wheel direction
  if WheelDelta > 0 then
    TargetScale := Scale.X + ZoomStep
  else
    TargetScale := Scale.X - ZoomStep;

  // Clamp scale to our defined limits
  TargetScale := Clamp(TargetScale, MinScale, MaxScale);

  // Convert mouse position to form-local coordinates for centered zoom
  MouseLocalPos := ScreenToClient(Mouse.Position);

  // Scale the form around the mouse cursor (avoids awkward offset)
  Scale.ScaleBy(TargetScale / Scale.X, MouseLocalPos);

  Handled := True; // Mark the event as processed
end;

Option 2: Scale a Content Container (Better for Games)

For a 2D game, it's often better to keep your form size fixed and zoom a container holding your game assets (like a TLayout or TPaintBox). This avoids window resizing issues:

  1. Add a TLayout to your form, set its Align property to Client, and place all your game content inside it.
  2. Use this modified event handler:
const
  ZoomStep = 0.1;
  MinScale = 0.5;
  MaxScale = 3.0;

procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState; WheelDelta: Integer; var Handled: Boolean);
var
  TargetScale: Single;
  MouseLocalPos: TPointF;
begin
  // Get mouse position relative to the layout
  MouseLocalPos := Layout1.ScreenToClient(Mouse.Position);

  if WheelDelta > 0 then
    TargetScale := Layout1.Scale.X + ZoomStep
  else
    TargetScale := Layout1.Scale.X - ZoomStep;

  TargetScale := Clamp(TargetScale, MinScale, MaxScale);
  Layout1.Scale.ScaleBy(TargetScale / Layout1.Scale.X, MouseLocalPos);

  Handled := True;
end;

Addressing Your FMX Usability Concerns

Where is the "easy" Scale property?

FMX does include scaling functionality—every control (including TForm) has a Scale property of type TScaleRec, which holds separate X and Y scaling values. The confusion likely comes from it being a structured property instead of a single numeric value (unlike some other frameworks). The ScaleBy method we used above simplifies scaling by handling both axes and allowing a center point, which is more flexible than just setting Scale.X/Scale.Y directly.

Why does FMX feel less polished than expected?

You’re not alone in this observation:

  • FMX is a cross-platform framework, which means it has to balance compatibility across Windows, macOS, iOS, Android, and Linux. This leads to some design tradeoffs compared to VCL (Delphi’s Windows-only framework), which has decades of refinement.
  • The FMX community and ecosystem are smaller than VCL’s. While official documentation and Idera’s resources exist, third-party tutorials, examples, and discussions are less abundant. That said, Delphi’s official forums and dedicated FMX-focused communities do have helpful content if you dig a bit deeper.

Hopefully this clears things up and gets your zoom functionality working smoothly!

内容的提问来源于stack exchange,提问作者ecofast

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 15:22:58