抑制特定控件上的鼠标滚动事件而不是它们的父控件?

Suppress mouse scroll events on specific controls but NOT their parent?

我有一个嵌入滚动框内的表单。我像这样在滚动框中实现滚动:

procedure TfrmPO.sbItemsMouseWheelDown(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
begin
  sbItems.Perform(WM_VSCROLL, SB_PAGEDOWN, 0);
end;

procedure TfrmPO.sbItemsMouseWheelUp(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
begin
  sbItems.Perform(WM_VSCROLL, SB_PAGEUP, 0);
end;

这很好用,但是此表单中还有许多组合框控件。如果焦点位于其中之一,它还会滚动该组合框中的项目。所以我需要禁用这样的效果。

我已经尝试了两种确实有效的解决方案,但是这两种解决方案都引入了一个新问题:父滚动框从不接收消息,因此不会按要求滚动。如果焦点在另一个控件中,父控件会滚动,但如果焦点在组合框中,则不会滚动。

尝试 1:

procedure TForm1.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
  if Screen.ActiveControl is TComboBox then Handled := True;
end;

尝试 2:

type
  TComboBox = class(Vcl.StdCtrls.TComboBox)
  protected
    function DoMouseWheel(Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint): Boolean; override;
  end;

.....

{ TComboBox }

function TComboBox.DoMouseWheel(Shift: TShiftState; WheelDelta: Integer;
  MousePos: TPoint): Boolean;
begin
  Result:= True;
end;

如何在特定控件中禁用鼠标滚轮滚动而不在其父项上禁用它?

鼠标滚轮消息被传播到接收它们的控件的父链,直到它被处理。因此,在滚动框中实际处理它们的地方将 Handled 设置为 true。不要在其他任何地方放置任何消息处理程序,以便将消息发送给父级。

procedure TfrmPO.sbItemsMouseWheelDown(Sender: TObject; Shift: TShiftState;
  MousePos: TPoint; var Handled: Boolean);
begin
  Handled := True;
  sbItems.Perform(WM_VSCROLL, SB_PAGEDOWN, 0);
end;