namespace comboBoxApp
...{
/**
/// 可带ToolTip的组合框控件
///
public class ComboBoxEx : ComboBox
...{
/**
/// 这个子类窗口用来存放下拉列表窗口,通过它来操作下拉列表
///
private SubWindow m_SubWindow;
/**
/// 通常的构造函数
///
public ComboBoxEx()
...{
}
/**
/// 处理Windows的消息
///
///
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);
}
/**
/// 重写以释放子类
///
///
protected override void Dispose(bool disposing)
...{
if (disposing && this.m_SubWindow != null)
...{
this.m_SubWindow.DestroyHandle();
}
base.Dispose(disposing);
}
}
/**
/// 子类化窗口的类
///
internal class SubWindow : NativeWindow
...{
/**
/// 为了得到列表上的鼠标坐标而使用Api函数及其所用到的数据结构
///
[StructLayout(LayoutKind.Sequential)]
public class POINT
...{
public int x;
public int y;
public POINT(int x, int y)
...{
this.x = x;
this.y = y;
}
}
/**
/// 映射窗体的坐标
///
/// 源窗口句柄
/// 要影射到的窗口句柄
/// 转换前后的坐标数据
///
///
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int MapWindowPoints(IntPtr hWndFrom, IntPtr hWndTo, [In, Out] POINT pt, int cPoints);
/**
/// 为了得到指定坐标下的项而需要向列表发送消息
///
///
///
///
///
///
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
/**
/// 为了得到指定索引的列表的内容而需要向列表发送消息,因为列表文本可能被格式化,所以这是合理的。
///
///
///
///
///
///
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, StringBuilder lParam);