為ComboBox添加ToolTip



如果ComboBox寬度不夠,需要鼠標經過時顯示完整提示,就添加鼠標經過事件。
如果希望點擊下拉時也顯示提示,重寫ComboBox添加鼠標經過提示。
private  void comboBoxEx1_MouseHover( object sender, EventArgs e)
{
    toolTip1.SetToolTip(comboBoxEx1, comboBoxEx1.Text);
}

        在Windows應用程序中使用ToolTip控件給ComboBox控件顯示提示的信息,往往要求的不是直接給控件一個固定的ToolTip提示,可能更多的時候要給ComboBox的下拉列表的項添加提示。可是默認的Combobox控件並不提供這個功能。見到網上有了這方面的做法,但是總覺得“不太可靠”。。。

      我們知道對於ComboBox來說,其實他不像TextBox或Button一樣有一個句柄,它有多於一個句柄,一個是ComboBox本身,一個是處理編輯狀態的編輯框的文本的句柄,一個是下拉出來的“列表”的句柄。其實確實是這樣的。一個ComboBox是一個“復合”控件,由文本框和下拉列表組成。就是這個下拉列表有着非常吸引人的地方,可在程序里通過一般的方法又很難訪問到它,所以ComboBox控件變得好像是Windows控件中“最神秘”的控件之一。

     因為我們確實需要給ComboBox的下拉列表項添加ToolTip。既然我們知道了這個下拉列表是一個“ListBox”那么我們就有了訪問它的方法:使用Listbox的相關方法(API)來操作就可以了。比如我們可以通過在ListBox上的坐標得到坐標下的項所在的Items的索引,由這個索引就可以得到Items中的第幾個元素的內容。因為ToolTip都是通過鼠標在其上的時候顯示出來的,所以我們可通過這個方法得到當前鼠標下的ListBox的元素的索引,有了這個“難得”的索引就可以動態的顯示出項的ToolTip了。代碼參考如下:

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Threading;

namespace WinLib
{
     ///   <summary>
    
///  可帶ToolTip的組合框控件
    
///   </summary>
     public  class ComboBoxEx : ComboBox
    {
         ///   <summary>
        
///  這個子類窗口用來存放下拉列表窗口,通過它來操作下拉列表
        
///   </summary>
         private SubWindow m_SubWindow;
         ///   <summary>
        
///  通常的構造函數
        
///   </summary>
         public ComboBoxEx()
        {
        }
         ///   <summary>
        
///  處理Windows的消息
        
///   </summary>
        
///   <param name="m"></param>
         protected  override  void WndProc( ref Message m)
        {
             // 通過這個消息可以得到下拉列表的窗口名柄
             if (m.Msg ==  0x210 && ( int)m.WParam ==  0x3e80001)
            {
                 // 構建子類化窗口
                SubWindow sw =  new SubWindow();
                 // 把當前ComboBox實例做為屬性傳入方便處理
                sw.Owner =  this;
                 // 把得到的列表句柄關聯到子類窗口類上。
                sw.AssignHandle(m.LParam);
                 // 這里的做用是保證子類窗口和ComboBoxEx生存期同步
                 this.m_SubWindow = sw;
            }
             base.WndProc( ref m);
        }
         ///   <summary>
        
///  重寫以釋放子類
        
///   </summary>
        
///   <param name="disposing"></param>
         protected  override  void Dispose( bool disposing)
        {
             if (disposing &&  this.m_SubWindow !=  null)
            {
                 this.m_SubWindow.DestroyHandle();
            }
             base.Dispose(disposing);
        }
    }
     ///   <summary>
    
///  子類化窗口的類
    
///   </summary>
     internal  class SubWindow : NativeWindow
    {
         ///   <summary>
        
///  為了得到列表上的鼠標坐標而使用Api函數及其所用到的數據結構
        
///   </summary>
        [StructLayout(LayoutKind.Sequential)]
         public  class POINT
        {
             public  int x;
             public  int y;
             public POINT( int x,  int y)
            {
                 this.x = x;
                 this.y = y;
            }
        }
         ///   <summary>
        
///  映射窗體的坐標
        
///   </summary>
        
///   <param name="hWndFrom"> 源窗口句柄 </param>
        
///   <param name="hWndTo"> 要影射到的窗口句柄 </param>
        
///   <param name="pt"> 轉換前后的坐標數據 </param>
        
///   <param name="cPoints"></param>
        
///   <returns></returns>
        [DllImport( " user32.dll ", CharSet = CharSet.Auto, ExactSpelling =  true)]
         public  static  extern  int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] POINT pt,  int cPoints);
         ///   <summary>
        
///  為了得到指定坐標下的項而需要向列表發送消息
        
///   </summary>
        
///   <param name="hWnd"></param>
        
///   <param name="msg"></param>
        
///   <param name="wParam"></param>
        
///   <param name="lParam"></param>
        
///   <returns></returns>
        [DllImport( " user32.dll ", CharSet = CharSet.Auto)]
         public  static  extern  int SendMessage(IntPtr hWnd,  int msg,  int wParam,  int lParam);
         ///   <summary>
        
///  為了得到指定索引的列表的內容而需要向列表發送消息,因為列表文本可能被格式化,所以這是合理的。
        
///   </summary>
        
///   <param name="hWnd"></param>
        
///   <param name="msg"></param>
        
///   <param name="wParam"></param>
        
///   <param name="lParam"></param>
        
///   <returns></returns>
        [DllImport( " user32.dll ", CharSet = CharSet.Auto)]
         public  static  extern IntPtr SendMessage(IntPtr hWnd,  int msg,  int wParam, StringBuilder lParam);

         ///   <summary>
        
///  上一索引值
        
///   </summary>
         private  int m_Index;
         ///   <summary>
        
///  用來顯示信息ToolTip
        
///   </summary>
         private ToolTip toolTip;
         ///   <summary>
        
///  所屬性的ComboBox
        
///   </summary>
         private Control m_Owner;
         ///   <summary>
        
///  構造函數
        
///   </summary>
         public SubWindow()
        {
             this.m_Index = - 1;
             this.toolTip =  new ToolTip();
        }
         ///   <summary>
        
///  所屬的控件
        
///   </summary>
         public Control Owner
        {
             get {  return m_Owner; }
             set { m_Owner = value; }
        }
         ///   <summary>
        
///  處理鼠標的消息以顯示ToolTip信息
        
///   </summary>
        
///   <param name="m"></param>
         protected  override  void WndProc( ref Message m)
        {
             if (m.Msg ==  0x200)
            {
                 // 獲取鼠標坐標
                Point msPoint = Cursor.Position;
                POINT pt =  new POINT(msPoint.X, msPoint.Y);
                 // 影射到列表上的坐標
                MapWindowPoints(IntPtr.Zero,  this.Handle, pt,  1);
                 // 獲取鼠標下的項的索引
                 int index = SendMessage(m.HWnd,  0x1a90, (pt.y <<  0x10) | (pt.x &  0xffff));
                 if (((index >>  0x10) &  0xffff) ==  0)
                {
                    index = (index &  0xffff);
                     if (m_Index != index)
                    {
                         // 獲取項的字符串的長度
                         int num = SendMessage( this.Handle,  0x18a, index,  0);
                        StringBuilder lParam =  new StringBuilder(num +  1);
                         // 獲取項的字符串內容
                        SendMessage( this.Handle,  0x189, index, lParam);
                         // 獲取鼠標在所屬的控件的坐標信息
                        Point owPoint =  this.Owner.PointToClient(msPoint);
                         // 設置ToolTip信息並顯示
                         this.toolTip.RemoveAll();
                         this.toolTip.Show(lParam.ToString(),  this.Owner, owPoint.X +  10, owPoint.Y +  101000);
                        m_Index = index;
                    }
                }
            }
             base.WndProc( ref m);
        }
    }
}

 url: http://greatverve.cnblogs.com/archive/2012/06/27/combobox-tooltip.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM