c# - 如何获取光标下ComboBox Item的索引?
问题描述
在我最近的一个项目中,我有一个 ComboBox,其中包含超过 ComboBox 下拉列表长度的项目。
我想在工具提示中显示项目全文。
不幸的是,.NET 框架没有为此提供内置解决方案。
解决方案
这是我自己的解决方案
你可以在我的 github 上找到完整的代码、更详细的解释和示例项目。 https://github.com/MaxBGitHub/MouseOverItemComboBox
先决条件
提供的代码适用于 C# .NET 4.5.2 框架的 Windows 窗体库,并使用 Visual Studio 2017 编写。
为了让它工作,您需要利用一些本机 WinAPI 函数和结构。将使用以下本机函数和本机结构:
只需从 pinvoke 复制粘贴结构即可。没有必要把你的头绕在这些上面。LBItemFromPt 函数和 GetComboBoxInfo 函数非常简单。如果您不知道如何实现这些,只需转到上面的 github 页面或阅读下面的代码即可。
自定义 ComboBox 类实现
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Drawing;
using System;
class MouseOverItemComboBox : ComboBox
{
// Event delegate
public delegate void OnMouseOverItem(object sender, MouseOverEventArgs e);
// Event which the parent can subscribe to.
public event OnMouseOverItem MouseOverItem;
// The possible combo box button states.
enum ButtonState {
STATE_SYSTEM_NONE = 0, // Button exists and is not pressed.
STATE_SYSTEM_INVISIBLE = 0x00008000, // There is no button.
STATE_SYSTEM_PRESSED = 0x00000008, // Button is pressed.
}
/* Native COMBOBOXINFO struct implementation.
** Contains combo box status information. */
[StructLayout(LayoutKind.Sequential)]
struct COMBOBOXINFO
{
public int cbSize; // Size in bytes of struct.
public RECT rcItem; // RECT that specifies the coordinates of the edit box.
public RECT rcButton; // RECT that specifies the coordinates of the drop-down button.
public ButtonState stateButton; // Drop-down button state.
public IntPtr hwndCombo; // Handle to the combo box.
public IntPtr hwndEdit; // Handle to the edit box.
public IntPtr hwndList; // Handle to the drop-down list.
}
/* Sent to parent window of a list box before the system draws the list box.
** Can set text and background color of the list box by using the specified
** device context handle. */
const int WM_CTLCOLORLISTBOX = 0x0134;
// Native function that retreives information about the specified combo box.
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getcomboboxinfo
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetComboBoxInfo(IntPtr hWnd, [In][Out] ref COMBOBOXINFO pcbi);
// Native function that retreives the index of the item at the specified point in a list box.
// https://docs.microsoft.com/en-us/windows/win32/api/commctrl/nf-commctrl-lbitemfrompt
[DllImport("Comctl32.dll", SetLastError = true)]
static extern int LBItemFromPt(IntPtr hLB, POINT pt, bool bAutoScroll);
// Helper method which will invoke the MouseOverItem event.
private void HandleMouseOverItem()
{
// cbSize must be set before calling GetComboBoxInfo.
COMBOBOXINFO pcbi = new COMBOBOXINFO();
pcbi.cbSize = Marshal.SizeOf(pcbi);
// Get combo box information.
GetComboBoxInfo(Handle, ref pcbi);
// Check for invalid pointer... just in case.
if (pcbi.hwndList == IntPtr.Zero)
return;
// Current position of cursor.
POINT pt = Cursor.Position;
// LBItemFromPt will return the Index of the Item on success.
int retVal = LBItemFromPt(pcbi.hwndList, pt, false);
if (retVal == -1)
return;
// Invoke the event.
MouseOverItem?.Invoke(this, new MouseOverEventArgs(retVal));
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
/* This message is sent by the list box of the combo box.
** It is sent before the system draws the list box.
** Whenever the cursor enters a list item this message will be
** sent to the parent i.e. the combox box.
** NOTE that this message is always sent twice.
** First time for drawing the default item background.
** Second time for drawing the highlighted item background. */
case WM_CTLCOLORLISTBOX:
{
// Let the helper method do the rest.
HandleMouseOverItem();
base.WndProc(ref m);
break;
}
default:
{
base.WndProc(ref m);
break;
}
}
}
}
推荐阅读
- python - 如何实现获取参数列表或元组列表的代码?
- elasticsearch - 我们如何进行关键不敏感基数聚合?
- java - 在 recyclerview 中调用 textview 和 imageview
- python - numpy 数组:在作为输入的一组行和列的固定窗口内计算 argmax 的有效方法
- aws-lambda - 使用 AWS lambda 步骤调用 java -jar 命令
- asp.net - ASP.NET Core:没有看到详细的错误,即使环境变量设置为开发
- arrays - 在字典中添加新键?
- c - 关于 C 中函数参数中的静态值
- typescript - 哪些方法遍历 Typescript AST 会产生什么结果?
- c# - API 给出错误 {{System.Runtime.CompilerServices.AsyncTaskMethodBuilder1+AsyncStateMachineBox1}}