2012-12-17 44 views
4

在傳遞給WindowFromPoint的點處,在TWinControl的MouseMove事件中調用WindowFromPoint會導致MouseOver事件。這是一個VCL錯誤?有人知道是否有解決方法?爲什麼在MouseMove事件中調用WindowFromPoint時突出顯示窗體的系統按鈕?

enter image description here

這裏的演示代碼:

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 

我用Delphi XE2在Windows 7專業版64位。我也可以使用Delphi 7複製。

+3

WindowFromPoint是Windows API。所以似乎不是一個VCL問題。 –

+1

@TLama - 實際上,表單可以是任意大小,但光標必須在系統按鈕正下方40像素或更少。 – norgepaul

+0

也許這篇文章來自雷蒙德陳是相關的:http://blogs.msdn.com/b/oldnewthing/archive/2011/02/18/10131176.aspx –

回答

4

我用最簡單的C++應用程序測試了這個,並觀察到相同的行爲,這不是VCL錯誤(正如David在評論中提到的那樣)。這與鼠標移動無關順便說一句,任何時候當您通過字幕按鈕的座標傳遞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的條件(OS,主題..),使有條件的代碼可以避免不必要的開銷。

+0

嗨塞爾特克。這很有用,非常感謝。你有什麼想法如何徹底關閉突出顯示?我問的原因是在TChromeTabs中,我處理自己的選項卡拖放。拖動選項卡時,系統按鈕在光標位於它們上方時仍高亮顯示。 Chrome確實會出現這種行爲,所以我猜想必須有一種方法來臨時禁用突出顯示效果。也許這應該是一個新問題? – norgepaul

+0

@norge - 不客氣。我現在想不出任何東西,我要測試的第一件事就是嘗試處理WM_NCHITTEST,但是DWM可能會有一些差異來處理它。 –

相關問題