我使用Windows XE2,TVirtualStringTree
和TComboBox
作为内置编辑器。
当我在表单上直接放置TComboBox
时,在运行时我可以下拉列表,鼠标滚轮可以上下滚动列表中的项目(根据需要)。但是,当TComboBox
作为就地编辑器在运行时创建TVirtualStringTree
时,即使新创建的组合框具有焦点,鼠标滚轮的WM_MOUSEWHEEL
消息也会发送到树控件而不是组合框。
这很明显,因为组合框下拉列表中的项目不会滚动。相反,组合框后面的树控件滚动。组合框的固定部分随树一起移动,但下拉列表与组合框的固定部分断开连接并且不移动(如图所示)。
在这两种情况下,TComboBox.Style
都设置为csDropDownList
。当组合框被创建为树的就地编辑器时,它将以这种方式完成:
FCBox := TComboBox.Create(TreeControl);
FCBox.Visible := False;
FCBox.Parent := TreeControl;
// ... add items to combo box ...
FCBox.Visible := True;
FCBox.SetFocus;
FCBox.DroppedDown := True;
鼠标在哪里悬停并不重要。它可以直接在组合框下拉列表中的项目上,并且后台中的树控件仍然是滚动的树控件。滚动组合框中项目的唯一方法是使用其滚动条。
什么会导致焦点控件的父级接收鼠标轮消息而不是控件本身(在本例中为TComboBox
)?
答案 0 :(得分:1)
VirtualTrees.pas
在TBaseVirtualTree
类中包含以下声明:
private
procedure CMMouseWheel(var Message: TCMMouseWheel); message CM_MOUSEWHEEL;
组件作者捕获了鼠标滚轮消息,因此他可以先垂直滚动,然后水平滚动。自定义代码是将鼠标滚轮消息发送到TVirtualStringTree
而不是TComboBox
的原因。我注释掉了他的代码,并按预期滚动了TComboBox
下拉列表。
由于我真的不想删除TBaseVirtualTree
代码,因此我使用以下代码创建了自己的TMyComboBox
以用作就地编辑器。现在,滚动在下拉列表和树控件中都能正常工作。
interface
type
TMyCombBox = class(TComboBox)
private
procedure CMMouseWheel(var Message: TCMMouseWheel); message CM_MOUSEWHEEL;
end;
implementation
procedure TMyComboBox.CMMouseWheel(var Message: TCMMouseWheel);
begin
if DoMouseWheel([], Message.WheelDelta, SmallPointToPoint(Message.Pos)) then
Message.Result := 1;
end;
这会在CM_MOUSEWHEEL
消息传递给树控件之前捕获它,然后将其传递给TControl.DoMouseWheel()
方法进行处理。