How to create a non active dropdown with keybord focus

1

I want to create a dropdown control which should be inactive and have keyboard input focus. So I created a control as below.

public class DropDownEdit : UserControl
{
    [DllImport("user32.dll")]
    public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    private const int WS_EX_TOOLWINDOW = 0x00000080;
    private const int WS_EX_TOPMOST = 0x00000008;
    private const int WS_EX_NOACTIVATE = 0x08000000;
    private const int WS_CHILD = 0x40000000;
    private const int WS_POPUP = unchecked((int)0x80000000);

    private TextBox text = new TextBox();

    public DropDownEdit()
    {
        this.BackColor = Color.FromArgb(44, 68, 107);
        this.Controls.Add(text);
        this.Margin = Padding.Empty;
        this.Padding = new Padding(0);
        text.Multiline = true;
        text.ScrollBars = ScrollBars.Both;
        text.Size = new Size(this.Width, this.Height);
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams createParams = base.CreateParams;
            createParams.Style &= ~WS_CHILD;
            createParams.Style |= WS_POPUP;

            createParams.ExStyle |= WS_EX_TOOLWINDOW;
            createParams.ExStyle |= WS_EX_TOPMOST;
            createParams.ExStyle |= WS_EX_NOACTIVATE;
            return createParams;
        }
    }

    public void ShowWindow(Point point)
    {
        text.Focus();
        this.Capture = true;
        SetParent(this.Handle, IntPtr.Zero); 
        this.Location = point;
        Show();
    }

    protected override void OnMouseCaptureChanged(EventArgs e)
    {
        base.OnMouseCaptureChanged(e);
        this.Hide();
    }
}

And when I am displaying the above dropdown window as below,

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Point point = this.PointToScreen(button1.Location);
        DropDownEdit window = new DropDownEdit();
        window.ShowWindow(new Point(point.X, point.Y + 20));
    }
}

The Form1 has a flickering while displaying DropDownEdit. I think DropDownEdit get activated and Form1 loses its activation. How can I avoid this flickering in Form1?

NB:- I need input focus on TextBox in the dropdown control.

c#
windows
asked on Stack Overflow Jul 13, 2015 by Kaizen

1 Answer

1

I found a solution.

While displaying my dropdown window it will receive activation and Windows will deactivate the main window. The fix for this is to send a WM_NCACTIVATE message to the parent to update its visual appearance without changing its activation status. The below code is updated in DropDownEdit class to solve my issue.

    private const int WM_NCACTIVATE = 0x86;

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

    protected override void WndProc(ref Message m)
    {
        // The popup needs to be activated for the user to interact with it,
        // but we want to keep the owner window's appearance the same.
        if ((m.Msg == WM_NCACTIVATE) && !_activating && (m.WParam != IntPtr.Zero))
        {
            // The popup is being activated, ensure parent keeps activated appearance
            _activating = true;
            SendMessage(this.Owner.Handle, WM_NCACTIVATE, (IntPtr) 1, IntPtr.Zero);
            _activating = false;
            // Call base.WndProc here if you want the appearance of the popup to change
        }
        else
        {
            base.WndProc(ref m);
        }
    }
answered on Stack Overflow Jul 15, 2015 by Kaizen

User contributions licensed under CC BY-SA 3.0