博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
为ComboBox添加ToolTip
阅读量:7281 次
发布时间:2019-06-30

本文共 4794 字,大约阅读时间需要 15 分钟。

如果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, 
0x1a9
0, (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 + 
10
1000);
                        m_Index = index;
                    }
                }
            }
            
base.WndProc(
ref m);
        }
    }
}

 url:

转载于:https://www.cnblogs.com/greatverve/archive/2012/06/27/combobox-tooltip.html

你可能感兴趣的文章
mac osx voice over的使用
查看>>
【Tools】maven安装
查看>>
每日一句(2014-9-11)
查看>>
【BZOJ】1665: [Usaco2006 Open]The Climbing Wall 攀岩(spfa)
查看>>
最长上升(不下降)子序列(详细,转)
查看>>
EF 6 调用存储过程时返回多结果集和OUTPUT参数问题
查看>>
oracle调优 浅析关联设计
查看>>
@功能的逻辑判断(原创)
查看>>
java异常处理
查看>>
SQL Server 的三种用户自定义函数
查看>>
nodejs文件操作笔记
查看>>
零零散散学算法之具体解释几种最短路径
查看>>
BDB (Berkeley DB)数据库简单介绍(转载)
查看>>
一款基于css3非常实用的鼠标悬停特效
查看>>
分布式存储系统sheepdog
查看>>
Ecshop与Jquery冲突的完美解决方案
查看>>
SQL Server 数据库设计规范
查看>>
sql server 2005 32位+64位、企业版+标准版、CD+DVD 下载地址大全
查看>>
Android中Application类用法
查看>>
(转)C#_WinForm接收命令行参数
查看>>