Search code examples
c#comboboxcustom-controls

how to set image for text of combobox in c#


I'm trying to paint an image inside Combobox in a custom control, I use the following code:

    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

actually, I got a good result but I noticed that the image is not above the textbox of the Combobox, I noticed that when I tried to change the hight of combobox.

enter image description here

see the video please to know what is the problem:

enter link description here

edit: please see that there is editor area that is covering the image if I change the height

enter image description here


Solution

  • thank you @dr.null

    I applied the following code and it's working:

        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);
    }
    

    }