2015-07-13 64 views
1

我想创建一个应该处于非活动状态且具有键盘输入焦点的下拉控件。所以我创建了如下的控件。如何使用keybord焦点创建非活动下拉列表

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

,当我下面显示上述下拉窗口,

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

Form1有闪烁的现象,同时显示DropDownEdit。我认为DropDownEdit被激活,Form1失去激活。如何避免Form1中的闪烁现象?

注意: - 我需要关注下拉控件中的TextBox

+0

您是否已将Form1的'DoubeBuffered'属性设置为'True'? – LInsoDeTeh

+0

@LInsoDeTeh其实这不是一个画相关的闪烁。这里闪烁意味着我的下拉窗口变成了活动窗口,即使它具有'WS_EX_NOACTIVATE'风格。所以'Form1'有一个眨眼的效果,并没有用'DoubeBuffered'做什么。 – Kaizen

回答

1

我找到了解决方案。

显示我的下拉窗口时,它将接收激活,Windows将停用主窗口。修复此问题的方法是发送WM_NCACTIVATE消息给父级,以更新其视觉外观而不更改其激活状态。 下面的代码在DropDownEdit类更新,以解决我的问题。

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