コンボ ボックスの各項目にツールチップを追加したいだけです。私はc#.net Windowsアプリケーションを使用しています。
みたいな選択肢はない
コンボボックス.アイテム[1].ツールチップ();
ツールチップを追加する方法はありますか?
この質問には、実際にはいくつかの合理的な解決策があります。MSDN フォーラムには、nobugz からのものと agrobler からのものの 2 つの可能性を含むComboBox アイテムのハイライト イベント投稿があります。それらのそれぞれは、ComboBox のドロップダウン内の個々の項目のツール ヒントを処理することになっている ComboBox をサブクラス化するコードを提供します。Agroblr のソリューションは、いくつかの素敵なイラストが含まれているという点で、より洗練されたように見えますが、残念ながら、(少なくとも私には) コントロールの重要な ToolTipMember プロパティを設定する方法が明確ではありません。
これらのソリューションはどちらも、個々のアイテムに割り当てられた任意のツールチップを許可しているようです。より具体的ではありますが、より一般的なケースは、ComboBox の幅に収まらない長すぎる項目があることがわかっている場合に、単にツールチップに項目のテキストを反映させたい場合です。私の場合、完全なファイル パスを保持する ComboBox のインスタンスがあるため、内容が ComboBox の幅を超える可能性がある場所を簡単に確認できます。
Zhi-Xin Ye は、MSDN フォーラムの投稿Windows ドロップダウンの質問で、このより具体的な問題に対処する、より簡単なソリューションを提供しています。ここにコード全体を再現します。(このコードは、Form1 という名前のフォームを作成し、表示されているロード ハンドラーを接続し、さらに、comboBox1 という名前の ComboBox とツール ヒント ハンドラー toolTip1 を追加したことを前提としていることに注意してください。)
private void Form1_Load(object sender, EventArgs e)
{
this.comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
this.comboBox1.DrawItem += new DrawItemEventHandler(comboBox1_DrawItem);
}
void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
string text = this.comboBox1.GetItemText(comboBox1.Items[e.Index]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{ e.Graphics.DrawString(text, e.Font, br, e.Bounds); }
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{ this.toolTip1.Show(text, comboBox1, e.Bounds.Right, e.Bounds.Bottom); }
else { this.toolTip1.Hide(comboBox1); }
e.DrawFocusRectangle();
}
シンプルで簡潔ですが、このコードには 1 つの欠陥があります (上記の MSDN スレッドの返信で指摘されているように): あるドロップダウン項目から次の項目に (クリックせずに) マウスを移動すると、他のすべてのドロップダウン項目のみが表示されます。永続的なツールチップ! 修正は、そのスレッドのさらに別のエントリによってのみ示唆されているため、ここで完全な修正済みコードを提供すると役立つと思いました。
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
comboBox1.DrawItem += comboBox1_DrawItem;
comboBox1.DropDownClosed += comboBox1_DropDownClosed;
}
private void comboBox1_DropDownClosed(object sender, EventArgs e)
{
toolTip1.Hide(comboBox1);
}
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) { return; } // added this line thanks to Andrew's comment
string text = comboBox1.GetItemText(comboBox1.Items[e.Index]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{ e.Graphics.DrawString(text, e.Font, br, e.Bounds); }
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{ toolTip1.Show(text, comboBox1, e.Bounds.Right, e.Bounds.Bottom); }
e.DrawFocusRectangle();
}
コードのいくつかの冗長な部分 ("this" 修飾子など) を削除することに加えて、主な違いは、toolTip1.Hide 呼び出しを DropDownClosed イベント ハンドラーに移動したことです。これを DrawItem ハンドラーから除外すると、上記の欠陥が解消されます。ただし、ドロップダウンが閉じたときに閉じる必要があります。そうしないと、最後に表示されたツールチップが画面に残ります。
2012.07.31 追記
それ以来、このツールチップ機能を組み込んだ複合 ComboBox を作成したので、私のライブラリを使用する場合、コードを書く必要はまったくありません。ComboBoxWithTooltip を Visual Studio デザイナーにドラッグするだけで完了です。API ページの ComboBoxWithTooltip にドリルダウンするか、オープンソースの C# ライブラリをダウンロードして開始してください。(Andrew が見つけたバグのパッチは、リリース 1.1.04 にあり、間もなくリリースされることに注意してください。)
private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
ToolTip toolTip1 = new ToolTip();
toolTip1.AutoPopDelay = 0;
toolTip1.InitialDelay = 0;
toolTip1.ReshowDelay = 0;
toolTip1.ShowAlways = true;
toolTip1.SetToolTip(this.comboBox1, comboBox1.Items[comboBox1.SelectedIndex].ToString()) ;
}
独自のUserControlを作成する必要があります。
コンボボックス内の各項目にツールチップを用意することは、通常とは異なります。おそらく、代わりに 2 列のコンボボックスを使用できますか?
データソースからロードしている場合は、データをデータテーブルに取得し、同じものをコンボボックスに設定します。私のデータテーブルには、ID、NAME、DEFINITION の 3 つの列があります。以下は私のコードです:
InputQuery = "select * from ds_static_frequency";
TempTable = UseFunc.GetData(InputQuery);
cmbxUpdateFrequency.DataSource = TempTable;
cmbxUpdateFrequency.DataTextField = "NAME";
cmbxUpdateFrequency.DataValueField = "ID";
cmbxUpdateFrequency.DataBind();
foreach (DataRow dr in TempTable.Rows)
{
int CurrentRow = Convert.ToInt32(dr["ID"].ToString());
cmbxUpdateFrequency.Items[CurrentRow - 1].ToolTip = dr["Definition"].ToString();
}
私の解決策:
public class ToolTipComboBox: ComboBox
{
#region Fields
private ToolTip toolTip;
private bool _tooltipVisible;
private bool _dropDownOpen;
#endregion
#region Types
[StructLayout(LayoutKind.Sequential)]
// ReSharper disable once InconsistentNaming
public struct COMBOBOXINFO
{
public Int32 cbSize;
public RECT rcItem;
public RECT rcButton;
public ComboBoxButtonState buttonState;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
public enum ComboBoxButtonState
{
// ReSharper disable once UnusedMember.Global
StateSystemNone = 0,
// ReSharper disable once UnusedMember.Global
StateSystemInvisible = 0x00008000,
// ReSharper disable once UnusedMember.Global
StateSystemPressed = 0x00000008
}
[DllImport("user32.dll")]
public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
#endregion
#region Properties
private IntPtr HwndCombo
{
get
{
COMBOBOXINFO pcbi = new COMBOBOXINFO();
pcbi.cbSize = Marshal.SizeOf(pcbi);
GetComboBoxInfo(Handle, ref pcbi);
return pcbi.hwndCombo;
}
}
private IntPtr HwndDropDown
{
get
{
COMBOBOXINFO pcbi = new COMBOBOXINFO();
pcbi.cbSize = Marshal.SizeOf(pcbi);
GetComboBoxInfo(Handle, ref pcbi);
return pcbi.hwndList;
}
}
[Browsable(false)]
public new DrawMode DrawMode
{
get { return base.DrawMode; }
set { base.DrawMode = value; }
}
#endregion
#region ctor
public ToolTipComboBox()
{
toolTip = new ToolTip
{
UseAnimation = false,
UseFading = false
};
base.DrawMode = DrawMode.OwnerDrawFixed;
DrawItem += OnDrawItem;
DropDownClosed += OnDropDownClosed;
DropDown += OnDropDown;
MouseLeave += OnMouseLeave;
}
#endregion
#region Methods
private void OnDropDown(object sender, EventArgs e)
{
_dropDownOpen = true;
}
private void OnMouseLeave(object sender, EventArgs e)
{
ResetToolTip();
}
private void ShowToolTip(string text, int x, int y)
{
toolTip.Show(text, this, x, y);
_tooltipVisible = true;
}
private void OnDrawItem(object sender, DrawItemEventArgs e)
{
ComboBox cbo = sender as ComboBox;
if (e.Index == -1) return;
// ReSharper disable once PossibleNullReferenceException
string text = cbo.GetItemText(cbo.Items[e.Index]);
e.DrawBackground();
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
TextRenderer.DrawText(e.Graphics, text, e.Font, e.Bounds.Location, SystemColors.Window);
if (_dropDownOpen)
{
Size szText = TextRenderer.MeasureText(text, cbo.Font);
if (szText.Width > cbo.Width - SystemInformation.VerticalScrollBarWidth && !_tooltipVisible)
{
RECT rcDropDown;
GetWindowRect(HwndDropDown, out rcDropDown);
RECT rcCombo;
GetWindowRect(HwndCombo, out rcCombo);
if (rcCombo.Top > rcDropDown.Top)
{
ShowToolTip(text, e.Bounds.X, e.Bounds.Y - rcDropDown.Rect.Height - cbo.ItemHeight - 5);
}
else
{
ShowToolTip(text, e.Bounds.X, e.Bounds.Y + cbo.ItemHeight - cbo.ItemHeight);
}
}
}
}
else
{
ResetToolTip();
TextRenderer.DrawText(e.Graphics, text, e.Font, e.Bounds.Location, cbo.ForeColor);
}
e.DrawFocusRectangle();
}
private void OnDropDownClosed(object sender, EventArgs e)
{
_dropDownOpen = false;
ResetToolTip();
}
private void ResetToolTip()
{
if (_tooltipVisible)
{
// ReSharper disable once AssignNullToNotNullAttribute
toolTip.SetToolTip(this, null);
_tooltipVisible = false;
}
}
#endregion
}
以下は、幅がコンボ ボックス コントロールの幅より大きいコンボ ボックスのアイテムにツール ヒントを表示する C# コードです。ユーザーがそのようなコンボ ボックスにカーソルを合わせると、ツール ヒントが表示されます。
this.combo_box1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.combo_box1.DrawMode = DrawMode.OwnerDrawFixed;
this.combo_box1.DrawItem += new DrawItemEventHandler(combo_box1_DrawItem);
this.combo_box1.DropDownClosed += new EventHandler(combo_box1_DropDownClosed);
this.combo_box1.MouseLeave += new EventHandler(combo_box1_Leave);
void combo_box1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) { return; }
string text = combo_box1.GetItemText(combo_box1.Items[e.Index]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{
e.Graphics.DrawString(text, e.Font, br, e.Bounds);
}
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected && combo_box1.DroppedDown)
{
if (TextRenderer.MeasureText(text, combo_box1.Font).Width > combo_box1.Width)
{
toolTip1.Show(text, combo_box1, e.Bounds.Right, e.Bounds.Bottom);
}
else
{
toolTip1.Hide(combo_box1);
}
}
e.DrawFocusRectangle();
}
private void combo_box1_DropDownClosed(object sender, EventArgs e)
{
toolTip1.Hide(combo_box1);
}
private void combo_box1_Leave(object sender, EventArgs e)
{
toolTip1.Hide(combo_box1);
}
private void combo_box1_MouseHover(object sender, EventArgs e)
{
if (!combo_box1.DroppedDown && TextRenderer.MeasureText(combo_box1.SelectedItem.ToString(), combo_box1.Font).Width > combo_box1.Width)
{
toolTip1.Show(combo_box1.SelectedItem.ToString(), combo_box1, combo_box1.Location.X, combo_box1.Location.Y);
}
}
詳細については、こちらのリンクをご覧ください - http://newapputil.blogspot.in/2016/12/display-tooltip-for-combo-box-item-cnet.html