有没有办法跟踪来自 TComboBox 的滚动条消息?
Is there a way to track scroll bar messages from TComboBox?
在我的扩展 TComboBox
class 中,我覆盖了 ComboWndProc()
过程处理程序,但我无法检测到来自 CN_VSCROLL 和 WM_VSCROLL 的消息列表的滚动条(FListHandle
).
我基本上想用winapi实现无限滚动。
我想,为了做我想做的事,我基本上需要知道滚动条的轨迹条位置,所以当轨迹条触摸下行按钮时,我会向字符串添加更多数据。
这个想法很简单,也许很天真,但我可以从那里开始,看看我会遇到什么问题。
这样的事情可以做吗?
有没有办法跟踪来自 TComboBox 的滚动条消息?
更重要的是:
- 如果是,如何?
- 如果不是,为什么?
您可以使用 WM_VSCROLL
,为此您必须继承组合框的列表框控件。 CN_VSCROLL
将不起作用,因为组合框的列表框部分不是 VCL 控件。
下面的示例基本上来自 Kobik 的 this answer,为了完整起见将其包含在此处。
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FComboListWnd: HWND;
FComboListWndProc, FSaveComboListWndProc: Pointer;
procedure ComboListWndProc(var Message: TMessage);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
Info: TComboBoxInfo;
begin
ZeroMemory(@Info, SizeOf(Info));
Info.cbSize := SizeOf(Info);
GetComboBoxInfo(ComboBox1.Handle, Info);
FComboListWnd := Info.hwndList;
FComboListWndProc := classes.MakeObjectInstance(ComboListWndProc);
FSaveComboListWndProc := Pointer(GetWindowLong(FComboListWnd, GWL_WNDPROC));
SetWindowLong(FComboListWnd, GWL_WNDPROC, Longint(FComboListWndProc));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SetWindowLong(FComboListWnd, GWL_WNDPROC, Longint(FSaveComboListWndProc));
classes.FreeObjectInstance(FComboListWndProc);
end;
procedure TForm1.ComboListWndProc(var Message: TMessage);
begin
case Message.Msg of
WM_VSCROLL: OutputDebugString('scrolling');
end;
Message.Result := CallWindowProc(FSaveComboListWndProc,
FComboListWnd, Message.Msg, Message.WParam, Message.LParam);
end;
在我的扩展 TComboBox
class 中,我覆盖了 ComboWndProc()
过程处理程序,但我无法检测到来自 CN_VSCROLL 和 WM_VSCROLL 的消息列表的滚动条(FListHandle
).
我基本上想用winapi实现无限滚动。
我想,为了做我想做的事,我基本上需要知道滚动条的轨迹条位置,所以当轨迹条触摸下行按钮时,我会向字符串添加更多数据。
这个想法很简单,也许很天真,但我可以从那里开始,看看我会遇到什么问题。
这样的事情可以做吗?
有没有办法跟踪来自 TComboBox 的滚动条消息?
更重要的是:
- 如果是,如何?
- 如果不是,为什么?
您可以使用 WM_VSCROLL
,为此您必须继承组合框的列表框控件。 CN_VSCROLL
将不起作用,因为组合框的列表框部分不是 VCL 控件。
下面的示例基本上来自 Kobik 的 this answer,为了完整起见将其包含在此处。
type
TForm1 = class(TForm)
ComboBox1: TComboBox;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FComboListWnd: HWND;
FComboListWndProc, FSaveComboListWndProc: Pointer;
procedure ComboListWndProc(var Message: TMessage);
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
Info: TComboBoxInfo;
begin
ZeroMemory(@Info, SizeOf(Info));
Info.cbSize := SizeOf(Info);
GetComboBoxInfo(ComboBox1.Handle, Info);
FComboListWnd := Info.hwndList;
FComboListWndProc := classes.MakeObjectInstance(ComboListWndProc);
FSaveComboListWndProc := Pointer(GetWindowLong(FComboListWnd, GWL_WNDPROC));
SetWindowLong(FComboListWnd, GWL_WNDPROC, Longint(FComboListWndProc));
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
SetWindowLong(FComboListWnd, GWL_WNDPROC, Longint(FSaveComboListWndProc));
classes.FreeObjectInstance(FComboListWndProc);
end;
procedure TForm1.ComboListWndProc(var Message: TMessage);
begin
case Message.Msg of
WM_VSCROLL: OutputDebugString('scrolling');
end;
Message.Result := CallWindowProc(FSaveComboListWndProc,
FComboListWnd, Message.Msg, Message.WParam, Message.LParam);
end;