2009-07-26 127 views
0

我的問題與答案如下在 How to create a button with drop-down menu?如何檢測鼠標點擊一個按鈕,下拉菜單

我試圖複製在左上角發現了「Office按鈕」的行爲的Mircosoft Office 2007用戶界面;特別是在用戶點擊按鈕的地方,彈出菜單出現並且按鈕在「下」狀態中被重新繪製。按鈕圖像保持在向下狀態,直到用戶單擊菜單上的鼠標或表單上的其他位置或者甚至在應用程序外部。

我需要檢測到這個鼠標點擊,所以我可以重新繪製正常圖像中的按鈕,如果我使用我自己的對話框作爲彈出菜單,隱藏菜單。

我正在使用D6。
感謝您的任何建議,
關心,
PhilW。

澄清:

我現在認識到,答案是瑣碎當使用TPopUpMenu,已經以曾經在彈出菜單中顯示的錯誤認識,它留給主事件的命運循環。我過去曾愉快地編碼。 Wiser,有點尷尬(但朋友之間沒關係)我的問題應該是更具體的,並且說:

「當我使用對話框表單來行爲像TPopUpMenu時,如何檢測到此鼠標單擊?

對不起,我感到困惑。

回答

1

也許我失去了一些東西,但至少一個彈出菜單,這是很容易:

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    SpeedButton1.AllowAllUp := TRUE; 
    SpeedButton1.GroupIndex := 1; 
end; 

procedure TForm1.SpeedButton1Click(Sender: TObject); 
var 
    CurPos: TPoint; 
begin 
    CurPos := Mouse.CursorPos; 
    PopupMenu1.Popup(CurPos.x, CurPos.y); 
    SpeedButton1.Down := FALSE; 
end; 

這工作,如使用輔助消息循環中所示的彈出式菜單,它的點擊外面做解僱它就像點擊一個菜單項一樣。

如果你想顯示一個窗體而不是彈出菜單,你只需要提供一個封裝函數,只有當窗體已經關閉時纔會返回,類似於上面代碼中的Popup()。例如,您可以顯示非模態表單,並使用SetCaptureControl()方法處理所有鼠標事件,即使鼠標光標位於表單區域之外。

編輯:

一些代碼來讓你開始 - 它表明了原則,但肯定是不完整的或最優的。取而代之的是彈出式菜單的形式顯示:

procedure TForm1.SpeedButton1Click(Sender: TObject); 
var 
    PtLeftTop: TPoint; 
begin 
    PtLeftTop := ClientToScreen(Point(SpeedButton1.Left + SpeedButton1.Width, 
    SpeedButton1.Top + SpeedButton1.Height)); 
    TForm2.ShowFormAsPopup(PtLeftTop); 
    SpeedButton1.Down := FALSE; 
end; 

形式具有下面的代碼:

type 
    TForm2 = class(TForm) 
    procedure FormCreate(Sender: TObject); 
    procedure FormKeyDown(Sender: TObject; var Key: Word; 
     Shift: TShiftState); 
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton; 
     Shift: TShiftState; X, Y: Integer); 
    procedure FormDeactivate(Sender: TObject); 
    public 
    class procedure ShowFormAsPopup(ATopLeft: TPoint); 
    end; 

// boilerplate snipped 

class procedure TForm2.ShowFormAsPopup(ATopLeft: TPoint); 
var 
    Form2: TForm2; 
    OldDeactivate: TNotifyEvent; 
begin 
    Form2 := TForm2.Create(nil); 
    try 
    OldDeactivate := Application.OnDeactivate; 
    try 
     Application.OnDeactivate := Form2.FormDeactivate; 

     Form2.Left := ATopLeft.x; 
     Form2.Top := ATopLeft.y; 
     Form2.Show; 
     SetCaptureControl(Form2); 
     while Form2.Visible do 
     Application.ProcessMessages; 
    finally 
     Application.OnDeactivate := OldDeactivate; 
    end; 
    finally 
    Form2.Release; 
    end; 
end; 

procedure TForm2.FormCreate(Sender: TObject); 
begin 
    KeyPreview := TRUE; 
end; 

procedure TForm2.FormKeyDown(Sender: TObject; var Key: Word; 
    Shift: TShiftState); 
begin 
    if Key = VK_ESCAPE then 
    Visible := FALSE; 
end; 

procedure TForm2.FormMouseDown(Sender: TObject; Button: TMouseButton; 
    Shift: TShiftState; X, Y: Integer); 
var 
    ScreenPos: TPoint; 
begin 
    ScreenPos := ClientToScreen(Point(X, Y)); 
    if (ScreenPos.X < Left) or (ScreenPos.Y < Top) 
    or (ScreenPos.X > Left + Width) or (ScreenPos.Y > Top + Height) 
    then begin 
    Visible := FALSE; 
    end; 
end; 

procedure TForm2.FormDeactivate(Sender: TObject); 
begin 
    Visible := FALSE; 
end; 
+0

金恰恰相反,那是我。花了很長時間才能理解你的答案,直到我意識到Popup語句在(!)之後立即返回控制權。我澄清了我的問題。 – PhilW 2009-07-27 07:06:48