WinForms ComboBox background color also applies to dropdown list

51 Views Asked by At

In order to set a background color for the active control I am using

private void ProcessEnter(object sender, EventArgs e)
{
  ((Control)sender).BackColor = Color.LightYellow;
}

but that also changes the background color of the dropdown list which looks weird. How can I prevent this?

1

There are 1 best solutions below

1
Loathing On

This code seems to work. A ComboBox is composed of 3 separate handles (the container, the text edit, the list). Get a handle to the hwndList window. When the list window receives a message and the combo is in the dropped down state, set the BackColor to white. If the ComboBox window receives the WM_ERASEBACKGROUND message, then set the BackColor back to yellow.

enter image description here

public class ComboBox2 : ComboBox {
    [System.Runtime.InteropServices.DllImport("user32.dll")]
    public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);

    private const UInt32 WM_ERASEBKGND         = 0x0014;

    NW nw = null;
    COMBOBOXINFO cbi;

    public ComboBox2() : base() {
        this.BackColor = Color.Yellow;
        this.Items.AddRange(new Object[] { "", "A", "B", "C" });
    }

    protected override void OnHandleCreated(EventArgs e) {
        base.OnHandleCreated(e);
        cbi = new COMBOBOXINFO();
        cbi.cbSize = System.Runtime.InteropServices.Marshal.SizeOf(cbi);
        GetComboBoxInfo(this.Handle, ref cbi);
        nw = new NW();
        nw.AssignHandle(cbi.hwndList);
        nw.combo = this;
    }

    protected override void Dispose(bool disposing) {
        base.Dispose(disposing);
        if (disposing) {
            if (nw != null) {
                nw.ReleaseHandle();
            }
        }
    }

    protected override void WndProc(ref Message m) {
        if (m.Msg == WM_ERASEBKGND) {
            this.BackColor = Color.Yellow;
        }
        base.WndProc(ref m);
    }

    private class NW : NativeWindow {
        public ComboBox2 combo = null;
        protected override void WndProc(ref Message m) {
            if (combo.DroppedDown)
                combo.BackColor = Color.White;
            base.WndProc(ref m);
        }
    }
}


[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct COMBOBOXINFO {
    public Int32 cbSize;
    public RECT rcItem;
    public RECT rcButton;
    public ComboBoxButtonState buttonState;
    public IntPtr hwndCombo;
    public IntPtr hwndEdit;
    public IntPtr hwndList;
}

[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
public struct RECT {
   public int Left, Top, Right, Bottom;
}

public enum ComboBoxButtonState {
    STATE_SYSTEM_NONE = 0,
    STATE_SYSTEM_INVISIBLE = 0x00008000,
    STATE_SYSTEM_PRESSED = 0x00000008
}