如何在C#中为组合框的文本设置图像

how to set image for text of combobox in c#

我正在尝试在自定义控件中的 Combobox 内绘制图像,我使用以下代码:

    public partial class Jo_ComboBox : ComboBox
{


    #region Constructor

    public Jo_ComboBox()
    {
        InitializeComponent();
        
    }

    #endregion

    #region Fields

    bool _IsRequired = false;
    bool _IsEmpty = true;
    Bitmap _xImg;

    #endregion


    #region Properties

    [Category("Joul_Properties")]
    public Bitmap xImg { get { return _xImg; } }

    [Category("Joul_Properties")]
    public bool IsEmpty { get { return _IsEmpty; } }

    [Category("Joul_Properties")]
    public bool IsRequired { get { return _IsRequired; } set { _IsRequired = value; } }

    #endregion


    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        base.OnPaint(e);

        if (IsRequired == true && this.Text == string.Empty)
        {
            _xImg = Resources._16Exc;
            e.Graphics.DrawImage(xImg, new Point(this.Width - 18, 30));
            _IsEmpty = true;
        }
        else
        {
            _IsEmpty = false;
        }




    }


    #region Events 

   
    //OnLeave
    protected override void OnLeave(EventArgs e)
    {
        base.OnLeave(e);
        this.Invalidate();
    }

    #endregion

实际上,我得到了一个不错的结果,但我注意到图像不在组合框的文本框上方,我注意到当我尝试更改组合框的高度时。

请查看视频以了解问题所在:

enter link description here

编辑: 如果我改变高度,请看有编辑区域覆盖图像

谢谢@dr.null

我应用了以下代码,它正在运行:

    using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public class MyComboBox : ComboBox
{
    public MyComboBox()
    {
        SetStyle(ControlStyles.ResizeRedraw, true);
        DrawMode = DrawMode.OwnerDrawFixed;
        ItemHeight = 40;
}

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
    public int Width { get { return Right - Left; } }
    public int Height { get { return Bottom - Top; } }
}

private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOZORDER = 0x0004;
private const int SWP_SHOWWINDOW = 0x0040;
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, 
    int X, int Y, int cx, int cy, int uFlags);

[DllImport("user32.dll")]
public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);

[StructLayout(LayoutKind.Sequential)]
public struct COMBOBOXINFO
{
    public int cbSize;
    public RECT rcItem;
    public RECT rcButton;
    public int stateButton;
    public IntPtr hwndCombo;
    public IntPtr hwndEdit;
    public IntPtr hwndList;
}
protected override void OnResize(EventArgs e)
{
    base.OnResize(e);
    SetupEdit();
    Invalidate();
}
private int buttonWidth = SystemInformation.HorizontalScrollBarArrowWidth;
protected override void WndProc(ref Message m)
{
    if (m.Msg == 0xF)
    {
        using (var g = this.CreateGraphics())
        {
            var r = new Rectangle(2, 2,
                ClientRectangle.Width - buttonWidth - 2,
                ClientRectangle.Height - 4);
            g.FillRectangle(Brushes.White, r);
        }
    }
    base.WndProc(ref m);
}
protected override void OnVisibleChanged(EventArgs e)
{
    base.OnVisibleChanged(e);
    SetupEdit();
}
private void SetupEdit()
{
    var info = new COMBOBOXINFO();
    info.cbSize = Marshal.SizeOf(info);
    GetComboBoxInfo(this.Handle, ref info);
    SetWindowPos(info.hwndEdit, IntPtr.Zero, 3,
        (this.Height - Font.Height) / 2,
        ClientRectangle.Width - buttonWidth - 3,
        ClientRectangle.Height - Font.Height - 4,
        SWP_NOZORDER);
}
protected override void OnDrawItem(DrawItemEventArgs e)
{
    base.OnDrawItem(e);
    e.DrawBackground();
    var txt = "";
    if (e.Index >= 0)
        txt = GetItemText(Items[e.Index]);
    TextRenderer.DrawText(e.Graphics, txt, Font, e.Bounds, 
        ForeColor, TextFormatFlags.Left | TextFormatFlags.VerticalCenter);
}

}