Click here to Skip to main content
15,921,212 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I want to create a dropdown control which should be inactive and have keyboard input focus. So I created a control as below.

C#
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,

C#
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.
Posted
Updated 13-Jul-15 0:55am
v2
Comments
Ralf Meier 13-Jul-15 6:40am    
What are you doing inside the Form-methods to generate the described effect ?
Which Events are handled there ?
bhaskerlee 13-Jul-15 7:23am    
@Ralf Meier, I didn't handled any event in Form1. I just created a DropDownEdit control as the code snippet and just called its ShowWindow() method from Form1.
Ralf Meier 13-Jul-15 8:13am    
It's because you wrote "flickering" ...
You call your Control with the Button-Click - the time before could not be any "flickering" to be seen.
Why do you instance your UserControl as window inside the Button.Click-method ?

Just listen how it sounds "non-active drop down with keyboard focus". How anything inactive could have keyboard focus? Why? what it could possibly do? It does not seem to make any sense.

Another problem you have is using P/Invoke. You don't need P/Invoke to set a parent. A parent is set by assignment
C#
myControl.Parent = someOtherControl;

or using
C#
someOtherControl.Controls.Add(myControl);

It P/Invoke is not absolutely require, it's bad it use it; it can compromise the platform compatibility of your code.

—SA
 
Share this answer
 
Comments
bhaskerlee 14-Jul-15 2:12am    
So how can I make desktop as parent of my window?
Sergey Alexandrovich Kryukov 14-Jul-15 2:15am    
You don't need it. Desktop is always a parent of all forms. You can change a parent from desktop to some control (if you set TopLevel = false), but it really makes no sense.

The issues we discussed and you code sample have nothing to do with flickering. If you have flicker, you need to provide relevant code sample showing flicker.

—SA
bhaskerlee 15-Jul-15 6:11am    
While displaying my dropdown window it will receive activation and Windows will deactivate the main window. This deactivation feels like a flickering in the title bar of main window.(Sorry for the word "flickering". Better I should use "Title bar blinking")
Sergey Alexandrovich Kryukov 15-Jul-15 7:11am    
Understood, thank you. Your problem is formulation of the problem, which sounds totally absurd. It is still like that. How could you expect anyone to understand it?
—SA
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.

C#
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);
    }
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900