在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:
object Form7: TForm7
Left = 0
Top = 0
Caption = 'Form7'
ClientHeight = 40
ClientWidth = 116
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object Button1: TButton
Left = 24
Top = 7
Width = 75
Height = 25
Caption = 'Button1'
TabOrder = 0
OnMouseMove = Button1MouseMove
end
end
我在Windows 7 Pro 64bit上使用Delphi XE2。我也可以使用Delphi 7重现。
答案 0 :(得分:4)
我用最简单的C ++应用程序对此进行了测试并观察到了相同的行为,这不是VCL错误(正如David在评论中提到的那样)。它与鼠标移动BTW无关,只要你通过标题按钮的坐标调用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
测试错误显示的条件(操作系统,主题..)并使代码有条件以避免不必要的开销是有意义的。