【问题标题】:Delphi FindVCLWindow returning nilDelphi FindVCLWindow 返回 nil
【发布时间】:2017-09-11 06:05:44
【问题描述】:

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

因此我编写了一个鼠标滚轮处理程序,该处理程序在调用适当的对象方法之前计算出鼠标所在的位置。

在大多数 PC 上这都能正常工作,但我这里有一台笔记本电脑不能。尽管处理程序从 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.

【问题讨论】:

  • 那么坐标是错误的,那么呢?如果是这样,返回什么? GetMessagePos函数?
  • 你做过调试吗?
  • 坐标似乎是正确的,但 FindVCLWindow 返回 nil。这是我无法理解的。
  • 进一步:坐标似乎是正确的,因为触摸板和 USB 鼠标都返回相同的坐标。但是,当我响应鼠标调用 FindVCLWindow 时,它返回正确的组件,但是当我响应触摸板调用它时,它返回 nil。
  • 所以做一些调试。为什么 FindVCLWindow 返回 nil?这里的绝大多数问题都可以通过调试来解决。在元级别上,您需要的不是解决此问题的方法。你需要学习如何调试这个问题。

标签: windows delphi mousewheel


【解决方案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 }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-07
    • 2013-02-18
    • 2019-06-20
    • 2017-12-16
    • 2014-09-27
    相关资源
    最近更新 更多