2010-03-17 76 views
3

場景:一個(小的)表單託管一個用戶控件。如何在Windows.Forms中創建浮動(工具提示)控件?

圖:每當UserControl引發懸停事件時,都會以工具提示方式顯示一些(圖形)信息。當用戶移動鼠標時,再次淡出它們。

備註:我想顯示多個「工具提示」,每個工具提示都是一個以圖形方式顯示信息的UserControl。不只是黃色框中的文字!另外,我正在使用Windows.Forms庫。

這是我到目前爲止有:

private void myControl_Hovered(object sender, MyEventArgs e) 
{    
    var tooltip = new MyToolTip(); 
    Controls.Add(tooltip); 
    tooltip.UpdateDisplay(e.Data); 
    tooltip.Show(); 
} 

但它在後臺顯示出來(我可以處理)和可悲的是,被限制在窗口...


編輯:這是我最終做的...

我無法得到ToolTip提供的控制與.NET工作。這主要是因爲我試圖在用戶繪製的控件中顯示用於「熱點」的工具提示(認爲功能點的圖形,顯示點的附加項目)。 ToolTip控件真的只想在用戶第一次進入控件時才顯示 - 手動顯示它似乎不起作用。我試過了。漫長而艱難。

所以,這個ToolTipWindow類可以用來在無框窗口中顯示控件。我添加了Offset屬性,因此它可以顯示在當前鼠標位置的偏移處。

/// <summary> 
/// A tooltip class to display some information from a control. 
/// </summary> 
internal class ToolTipWindow: Form 
{ 
    /// <summary> 
    /// The offset from the mouse pointer to show the window at. 
    /// </summary> 
    public Point Offset { get; set;} 

    internal ToolTipWindow(Control controlToDisplay) 
    { 
     FormBorderStyle = FormBorderStyle.None; 
     TopMost = true; 
     ShowInTaskbar = false; 
     Opacity = 0.9; 
     Width = controlToDisplay.Width; 
     Height = controlToDisplay.Height; 
     Controls.Add(controlToDisplay); 
     controlToDisplay.Show(); 
    } 

    /// <summary> 
    /// Move the window to an offset of mouse pointer. 
    /// </summary> 
    protected override void OnShown(EventArgs e) 
    { 
     base.OnShown(e); 
     Location = new Point(MousePosition.X + Offset.X, MousePosition.Y + Offset.Y); 
    } 

    /// <summary> 
    /// Move the window to an offset of mouse pointer. 
    /// </summary> 
    protected override void OnVisibleChanged(EventArgs e) 
    { 
     base.OnVisibleChanged(e); 
     if (Visible) 
     { 
      Location = new Point(MousePosition.X + Offset.X, MousePosition.Y +  Offset.Y);  
     } 
    } 
} 

要顯示工具提示,你可以趕上MouseHoverMouseMove事件。首先檢查,如果你在「熱點」上方並顯示工具提示。在MouseMove中,如果您不在「熱點」之上,請隱藏工具提示。另外,關閉窗口時,請確保您關閉所有工具提示窗口!

注意:MouseHover事件只會在第一次鼠標進入控件時顯示。如果你想讓它反覆(如在檢測的「熱點」的情況下)顯示出來,你應該增加類似的代碼包含「熱點」下面的控制:

#region AddReHoverExperience 
    // ReSharper disable InconsistentNaming 
    // found this code here: http://www.pinvoke.net/default.aspx/user32.TrackMouseEvent 

    [DllImport("user32.dll")] 
    static extern int TrackMouseEvent(ref TRACKMOUSEEVENT lpEventTrack); 
    [StructLayout(LayoutKind.Sequential)] 

    public struct TRACKMOUSEEVENT 

    { 
     public UInt32 cbSize; 
     public UInt32 dwFlags; 
     public IntPtr hwndTrack; 
     public UInt32 dwHoverTime; 
    } 

    TRACKMOUSEEVENT tme; 
    private const uint TME_HOVER = 0x1; 

    protected override void OnMouseHover(EventArgs e) 
    {    
     base.OnMouseHover(e); 
     OnMouseEnter(e); 
    } 

    protected override void OnMouseEnter(EventArgs e) 
    { 
     base.OnMouseEnter(e); 
     tme = new TRACKMOUSEEVENT 
        { 
         hwndTrack = Handle, 
         dwFlags = TME_HOVER, 
         dwHoverTime = 500 
        }; 
     tme.cbSize = (uint)Marshal.SizeOf(tme); 
     TrackMouseEvent(ref tme); 
    } 
    // ReSharper restore InconsistentNaming 
    #endregion AddReHoverExperience 
+0

會顯示一個無邊框,TopMost窗體的幫助? – fre0n 2010-03-17 11:06:11

+0

是的,fre0n,它會 - 我現在正在探索這條路線 - 將在完成後發佈此類代碼的源代碼) – 2010-03-17 11:26:16

回答

5

代碼有嚴重問題,它每次鼠標懸停時都會向用戶控件添加控件,但不會刪除它們。

首先,確保內置的ToolTip組件不能解決您的問題。它應該,它的行爲就像你描述的那樣。請注意,它具有OwnerDraw屬性,它允許您自定義其外觀。

創建你自己是棘手的。工具提示是一個相當不尋常的窗口,它不像其他所有WF控件一樣是一個子控件。它是一個頂級窗口,允許它與其他窗口重疊並延伸到容器窗口的客戶區域之外。 Windows窗體中唯一以這種方式運行的類是Form類。使用無邊界表單來實現您的自定義工具提示是可能的。

最棘手的部分是確保它在用戶控件的父窗體移動時移動。您必須遍歷UC的Parent屬性,直到找到Form,然後訂閱LocationChanged,VisibleChanged和FormClosing事件。你還應該連接UC的ParentChanged和HandleDestroyed事件。

+0

我現在要使用ToolTip組件路線。你有什麼想法瞭解如何在取消Popup事件後再次發生Popup事件?這是因爲我顯示的工具提示有一些熱點,我不想顯示冷點的提示(因此取消)。 – 2010-03-17 13:44:03

+0

您只會獲得一次MouseHover事件,您需要使用MouseMove重新顯示提示。另外請注意,ToolTip有一個內置的「功能」,如果第一個提示超時,它將阻止它顯示提示兩次。 – 2010-03-17 14:38:28

+0

可以關閉「功能」嗎? – 2010-03-17 15:44:50

相關問題