Delphi 网格在模式窗口后滚动
我已经建立了这个问题的MCV,我很高兴上传它。我先试着描述一下这个问题Delphi 网格在模式窗口后滚动,delphi,windows-10,delphi-xe3,Delphi,Windows 10,Delphi Xe3,我已经建立了这个问题的MCV,我很高兴上传它。我先试着描述一下这个问题 创建一个主窗口,并通过任何可用的数据库将TDBGrid连接到表。在显示窗口时,连接到数据库并打开表 在主窗口上创建启动非模式窗口的按钮 在非模式窗口上创建一个按钮,用于启动模式窗口 仔细按照这些步骤复制问题 运行应用程序 将焦点放在网格中,并使用鼠标滚轮上下滚动 按下按钮以启动非模式窗口 非模态窗口打开时,单击主窗口中的网格,然后再次使用鼠标滚轮上下滚动 当仍在网格中聚焦时,单击非模式窗口上的按钮以启动模式窗口 模式窗口打开
应该注意的是,在步骤4和步骤5之间,如果在启动模式窗口之前没有将焦点放在网格中,则不会发生此问题。在显示模式窗口之前,我曾尝试通过编程将焦点设置为非模式窗口上的控件,但没有成功 这是VCL代码中的错误。如注释中所述,要在普通应用程序中复制此问题,需要启用Windows 10的非活动窗口滚动功能,或在早期操作系统中提供类似功能的软件 但是,可以在没有特殊要求的情况下演示问题。这将是一个比问题中更简单的复制 在窗体上放置stringgrid和按钮,按钮的单击处理程序中包含以下代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
StringGrid1.Enabled := False;
SetFocusedControl(StringGrid1);
end;
单击按钮,将鼠标悬停在网格上并滚动。尽管网格被禁用,但它不应该滚动,但确实如此
下面是一个更适合问题中情况的问题。这是因为模式窗口禁用了包含网格的表单,该表单随后会发布鼠标滚轮消息。控制盘消息是针对不具备上述要求的环境合成的
procedure TForm1.Button1Click(Sender: TObject);
var
Pt: TPoint;
begin
Enabled := False;
Pt := Point(1, 1);
MapWindowPoints(StringGrid1.Handle, HWND_DESKTOP, Pt, 1);
SetFocusedControl(StringGrid1);
Perform(WM_MOUSEWHEEL, MakeWParam(0, WORD(-120)), MakeLParam(Pt.X, Pt.Y));
end;
观察到网格滚动后,按Ctrl+F2
问题的根本原因是,VCL在决定控件是否为焦点控件以及使其执行鼠标滚轮消息时,不关心控件是否已启用。将鼠标滚轮消息变为
CM\u鼠标滚轮
,并完全绕过默认窗口过程,VCL应该执行这些检查
对于解决方法,可以在启动模式窗体之前将焦点控件设置为其他控件:
MainForm.SetFocusedControl(MainForm);
OtherForm.ShowModal;
您不能在此处设置ActiveControl
,因为该控件具有必要的可见性/状态检查
如果不想与主窗体耦合,可以将鼠标滚轮消息处理程序放置到主窗体:
type
TMainForm = class(TForm)
...
protected
procedure WMMouseWheel(var Message: TWMMouseWheel); message WM_MOUSEWHEEL;
...
procedure TMainForm.WMMouseWheel(var Message: TWMMouseWheel);
begin
if IsWindowEnabled(Handle) then
inherited;
end;
这是VCL代码中的错误。如注释中所述,要在普通应用程序中复制此问题,需要启用Windows 10的非活动窗口滚动功能,或在早期操作系统中提供类似功能的软件 但是,可以在没有特殊要求的情况下演示问题。这将是一个比问题中更简单的复制 在窗体上放置stringgrid和按钮,按钮的单击处理程序中包含以下代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
StringGrid1.Enabled := False;
SetFocusedControl(StringGrid1);
end;
单击按钮,将鼠标悬停在网格上并滚动。尽管网格被禁用,但它不应该滚动,但确实如此
下面是一个更适合问题中情况的问题。这是因为模式窗口禁用了包含网格的表单,该表单随后会发布鼠标滚轮消息。控制盘消息是针对不具备上述要求的环境合成的
procedure TForm1.Button1Click(Sender: TObject);
var
Pt: TPoint;
begin
Enabled := False;
Pt := Point(1, 1);
MapWindowPoints(StringGrid1.Handle, HWND_DESKTOP, Pt, 1);
SetFocusedControl(StringGrid1);
Perform(WM_MOUSEWHEEL, MakeWParam(0, WORD(-120)), MakeLParam(Pt.X, Pt.Y));
end;
观察到网格滚动后,按Ctrl+F2
问题的根本原因是,VCL在决定控件是否为焦点控件以及使其执行鼠标滚轮消息时,不关心控件是否已启用。将鼠标滚轮消息变为
CM\u鼠标滚轮
,并完全绕过默认窗口过程,VCL应该执行这些检查
对于解决方法,可以在启动模式窗体之前将焦点控件设置为其他控件:
MainForm.SetFocusedControl(MainForm);
OtherForm.ShowModal;
您不能在此处设置ActiveControl
,因为该控件具有必要的可见性/状态检查
如果不想与主窗体耦合,可以将鼠标滚轮消息处理程序放置到主窗体:
type
TMainForm = class(TForm)
...
protected
procedure WMMouseWheel(var Message: TWMMouseWheel); message WM_MOUSEWHEEL;
...
procedure TMainForm.WMMouseWheel(var Message: TWMMouseWheel);
begin
if IsWindowEnabled(Handle) then
inherited;
end;
当显示模式窗口时,主窗口是否正确禁用?是否正确。AAMOF我可以在W7上用字符串网格复制它。它似乎取决于鼠标驱动程序/软件设置,而不是操作系统。如果我在我的盒子f.I.上禁用“wizmouse”,那就不会发生。不客气。然而,你仍然有一个问题。禁用的窗口不应滚动。@sertac这是vcl网格的问题。列表框是否滚动?显示模式窗口时主窗口是否正确禁用?是否。AAMOF我可以在W7上用字符串网格复制它。它似乎取决于鼠标驱动程序/软件设置,而不是操作系统。它是d