2011-12-06 75 views
5

我在表單上添加了提示。當組件獲得焦點時,我想設置標籤組件的標題以顯示提示。顯示提示

我添加了一個TApplicationEvents對象和OnShowHint事件設置爲

procedure TImportFrm.ApplicationEvents1ShowHint(var HintStr: string; 
    var CanShow: Boolean; var HintInfo: THintInfo); 
begin 
    HelpLbl.Caption := HintStr; 
end; 

但是似乎ShowHint事件僅與鼠標移動火災。有沒有辦法在組件獲得焦點時觸發提示代碼,而無需爲窗體上的每個組件實現OnEnter事件?

+0

你用什麼,VCL或FMX? – Kromster

+0

我使用VCL和XE2。 –

回答

4

在主窗體的創建在該事件中添加處理程序TScreen.OnActiveControlChange,並辦理提示:

type 
    TForm2=class(TForm) 
    ... 
    private 
    procedure ScreenFocusControlChange(Sender: TObject); 
    end; 

implementation 

procedure TForm2.FormCreate(Sender: TObject); 
begin 
    Screen.OnActiveControlChange := ScreenFocusControlChange; 
end; 

procedure TForm2.ScreenFocusControlChange(Sender: TObject); 
begin 
    Label1.Caption := ActiveControl.Hint; 
    Label1.Update; 
end; 

注意Sender不會做你多好;它總是Screen。您可以過濾(例如,僅改變Label.Caption爲編輯控件)通過測試ActiveControl

if (ActiveControl is TEdit) then 
    // Update caption of label with ActiveControl.Hint 

請注意,如果你需要的時候告訴你的孩子的形式(對某個事件重新分配事件子表單),或者您將始終使用提示更新原始表單的標籤。做再分配的最簡單的方法是給每一個形式OnActiveControlChange處理程序,並在窗體的OnActivate事件爲它分配和取消其在OnDeactivate事件:

procedure TForm1.FormActivate(Sender: TObject); 
begin 
    Screen.OnActiveControlChange := Self.ScreenActiveControlChange; 
end; 

procedure TForm1.FormDeactivate(Sender: TObject); 
begin 
    Screen.OnActiveControlChange := nil; 
end; 

這將允許您更新比Label1其它控件每個表單,並且只在你想要的表單上使用提示更改。

+0

謝謝Ken。那個事件正是我正在尋找的東西,我忘記了看TForm對象之外的東西。 –

4

一個簡單的解決方案是使用OnIdle事件:

procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean); 
begin 
    if Assigned(ActiveControl) then 
    Label1.Caption:= ActiveControl.Hint; 
end; 

更先進的解決方案是要覆蓋保護的方法ActiveChangedTForm

type 
    TForm1 = class(TForm) 
    ... 
    protected 
    procedure ActiveChanged; override; 
    end; 

... 

procedure TForm1.ActiveChanged; 
begin 
    inherited; 
    if Assigned(ActiveControl) then 
    Label1.Caption:= ActiveControl.Hint; 
end; 

接收焦點和OnShowHint是相當不同的事件;對於非集中控制,也可以觸發OnShowHint

+1

+1使用OnIdle。建議:使用Screen.ActiveControl而不是(Self).ActiveControl使其在應用程序範圍內工作;不僅適用於TForm1,還適用於可能的彈出窗體等。 – NGLN

+0

這是我在我的TKinect「虛擬鼠標光標」演示中使用的相同方法...效果很好! +1 – LaKraven

1

爲什麼您需要爲每個組件執行OnEnter事件?您可以創建一個通用方法/事件處理程序,如:

procedure TForm1.AnyControlEnter(Sender: TObject); 
begin 
    lbl1.Caption := TControl(Sender).Hint; 
end; 

並將其分配給您放置在窗體上的每個組件。

1

你說:

似乎ShowHint事件僅與鼠標移動

這是一種正常的行爲觸發。你有問題(這是一個猜測)是暗示不是直接觸發的。不要嘗試做出解決方法,你對MouseEnter所做的嘗試正是已經發生的事情......唯一的區別是你忘記了一些東西......

保持事件ApplicationEvents1ShowHint()如你最初做,但在窗體的構造事件補充一點:

Application.HintPause := 1; 

然後提示會顯示(幾乎)無延遲。