Windows 为什么是表格';在MouseMove事件中从点调用WindowFromPoint时,系统按钮是否高亮显示?

Windows 为什么是表格';在MouseMove事件中从点调用WindowFromPoint时,系统按钮是否高亮显示?,windows,delphi,delphi-xe2,Windows,Delphi,Delphi Xe2,在TWinControl的MouseMove事件中调用WindowFromPoint会在传递给WindowFromPoint的点处引发MouseOver事件。这是VCL错误吗?有人知道是否有解决办法吗 以下是演示代码: unit Unit7; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Contr

在TWinControl的MouseMove事件中调用WindowFromPoint会在传递给WindowFromPoint的点处引发MouseOver事件。这是VCL错误吗?有人知道是否有解决办法吗

以下是演示代码:

unit Unit7;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm7 = class(TForm)
    Button1: TButton;
    procedure Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form7: TForm7;

implementation

{$R *.dfm}

procedure TForm7.Button1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  WindowFromPoint(Point(Mouse.CursorPos.X, Mouse.CursorPos.Y - 40));
end;

end.
DFM:


我正在Windows 7 Pro 64位上使用Delphi XE2。我也可以用Delphi 7来复制。

< P>我用最简单的C++应用程序测试了这一点,观察到了同样的行为,这不是VCL错误(正如戴维在评论中提到的)。顺便说一句,它与鼠标移动无关,只要你调用
WindowFromPoint
传递标题按钮的坐标,这种特性就会出现。它只发生在属于调用函数的线程的窗口上

因此,对于解决方法,可以从线程调用
WindowFromPoint
。下面是一个简单的示例,在代码等待它完成时,它实际上不是一个后台线程:

type
  TGetWndThread = class(TThread)
  private
    FPoint: TPoint;
  protected
    procedure Execute; override;
    constructor Create(AOwner: TComponent; Point: TPoint);
  end;

constructor TGetWndThread.Create(AOwner: TComponent; Point: TPoint);
begin
  FPoint := Point;
  inherited Create;
end;

procedure TGetWndThread.Execute;
begin
  ReturnValue := WindowFromPoint(FPoint);
end;

..

var
  Wnd: HWND;
  Thr: TGetWndThread;
begin
  Thr := TGetWndThread.Create(nil, Point(Mouse.CursorPos.X, Mouse.CursorPos.Y - 40));
  Wnd := Thr.WaitFor;
  Thr.Free;
  .. // use Wnd


测试bug显示的条件(操作系统、主题…)并使代码有条件以避免不必要的开销是有意义的。

WindowFromPoint是Windows API。所以这似乎不是VCL的问题。@TLama-实际上,表单可以是任何大小,但光标必须在系统按钮正下方小于等于40像素。这篇来自Raymond Chen的文章可能与此相关:Hi Sertac。那很有效,非常感谢。你知道如何完全关闭高亮显示吗?我问这个问题的原因是,在TchromeTab中,我处理自己的选项卡拖放。拖动选项卡时,当光标位于系统按钮上方时,系统按钮仍高亮显示。Chrome确实表现出这种行为,所以我想一定有办法暂时禁用高光效果。也许这应该是一个新问题?@norge-不客气。我现在想不出什么,我要测试的第一件事是尝试处理WM_NCHITTEST,但是对于DWM来说,处理它可能会有一些不同。
type
  TGetWndThread = class(TThread)
  private
    FPoint: TPoint;
  protected
    procedure Execute; override;
    constructor Create(AOwner: TComponent; Point: TPoint);
  end;

constructor TGetWndThread.Create(AOwner: TComponent; Point: TPoint);
begin
  FPoint := Point;
  inherited Create;
end;

procedure TGetWndThread.Execute;
begin
  ReturnValue := WindowFromPoint(FPoint);
end;

..

var
  Wnd: HWND;
  Thr: TGetWndThread;
begin
  Thr := TGetWndThread.Create(nil, Point(Mouse.CursorPos.X, Mouse.CursorPos.Y - 40));
  Wnd := Thr.WaitFor;
  Thr.Free;
  .. // use Wnd