Delphi FindVCLWindow返回nil

时间:2017-09-11 06:05:45

标签: windows delphi mousewheel

我的应用程序在许多地方使用鼠标滚轮滚动。

因此我编写了一个鼠标滚轮处理程序,在调用适当的对象方法之前,这个处理程序可以解决鼠标所在的位置。

在大多数电脑上,这种方法很好,但我有一台笔记本电脑,但没有。尽管处理程序从Windows接收到正确的鼠标坐标,但对FindVCLWindow的调用返回nil。然而,这仅在我使用笔记本电脑的内部触摸板时才会发生。外置USB鼠标工作正常。

我已经将笔记本电脑的触摸板驱动程序更新到制造商网站上的最新版本,但无济于事。

我还能解决这个问题吗?

以下是代码:

unit Mouse_Wheel_Testing;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Grids;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    StringGrid1: TStringGrid;
    Mouse_Coordinates: TEdit;
    Control_Name: TEdit;
    Button1: TButton;
    procedure MouseWheelHandler(var Message: TMessage); override;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.MouseWheelHandler(var Message: TMessage);
var
  Target_Control: TWinControl;
begin
  with TWMMouseWheel(Message) do
  begin
    Mouse_Coordinates.Text := IntToStr(XPos) + ', ' + IntToStr(YPos);
    Target_Control := FindVCLWindow(Point(XPos, YPos));
    if Target_Control <> nil then
      Control_Name.Text := Target_Control.Name
    else
      Control_Name.Text := 'nil';
  end;
end;

end.

1 个答案:

答案 0 :(得分:1)

FindVCLWindow返回nil的原因是WindowFromPoint返回了一个不正确的句柄。这又是笔记本电脑中设置与滚动模式下触摸板行为有关的结果。需要正确设置此选项才能返回正确的句柄。

由于我的应用程序无法依赖用户正确设置笔记本电脑,因此我现在编写了一个基于ChildWindowFromPointEx的新FindComponent函数。以下函数现在位于鼠标滚轮处理程序中:

function Find_Control: TWinControl;
var
  Parent: HWND;
  Child: HWND;
  Position: TPoint;
begin { Find_Control }
  Result := nil;
  Parent := Self.Handle;
  with TWMMouseWheel(Message) do
    Position := ScreenToClient(Point(XPos, YPos));
  Child := ChildWindowFromPointEx(Parent, Position, CWP_SKIPINVISIBLE);
  while (Child <> 0) and (Child <> Parent) do
  begin
    Result := FindControl(Child);
    Position := Point(Position.X - Result.Left, Position.Y - Result.Top);
    Parent := Child;
    Child := ChildWindowFromPointEx(Parent, Position, CWP_SKIPINVISIBLE);
  end; { while (Child <> 0) and (Child <> Parent) }
end; { Find_Control }