如何为 TScrollbox 散焦 child TButton 以使用鼠标滚轮滚动

How to defocus a child TButton for TScrollbox to scroll with mousewheel

要求

  1. 动态创建的按钮(很多)。
  2. Wordwrap 必不可少,因为事先不知道标题长度(TSpeedButton 不好)。

下面给出了通过鼠标滚轮滚动 TScrollBox 的代码,它位于窗体的 OnMouseWheel 事件中。当光标在按钮上保持静止时,它会变成橙色 (XP) 矩形并且不会滚动 TScrollBox。似乎所有其他鼠标移动事件都存在,除了这个特殊情况。

If WindowFromPoint( mouse.Cursorpos ) = scrlbx1.Handle Then Begin
  Handled := true;
  If ssShift In Shift Then
    msg := WM_HSCROLL
  Else
    msg := WM_VSCROLL;

  If WheelDelta > 0 Then
    code := SB_LINEUP
  Else
    code := SB_LINEDOWN;

  n:= Mouse.WheelScrollLines;
  For i:= 1 to n Do
    scrlbx1.Perform( msg, code, 0 );
  scrlbx1.Perform( msg, SB_ENDSCROLL, 0 );
End;

我们将不胜感激。

你的问题不是按钮有焦点,而是你的代码没有考虑鼠标指针在按钮上的情况。

If WindowFromPoint( mouse.Cursorpos ) = scrlbx1.Handle Then Begin

当鼠标在按钮上时,上述语句中的条件将不成立。 WindowFromPoint 将 return 按钮句柄,因此其余代码将不会执行。

您必须更正您的代码以说明鼠标可以在另一个控件上。顺便说一句,事件处理程序已经传递了鼠标位置,使用它而不是再次检索位置——甚至可能是不同的位置。一个例子可以是:

GetWindowRect(scrlbx1.Handle, Rect);
if PtInRect(Rect, MousePos) then begin
  ..


焦点不是问题,VCL在父链中传播wheel消息,直到被处理。