当控件的顶级父窗口是活动窗口时设置焦点?

时间:2018-05-03 22:07:34

标签: c# winforms

我正在开发一个C#项目。问题是鼠标输入等后台事件会使背景窗口在不是活动窗口时突出显示。解决方案策略是在设置此焦点之前添加预防步骤。

我的尝试包括以下策略:

control.Focus()来电之前,我想实现一个涉及GetActiveWindow() function的条件,以匹配控件的顶级父级相关的窗口句柄。对于后者,我使用的是Control.TopLevelControl()。但是,每次我这样做,我得到null这个属性。根据{{​​3}}的原因是控件不是表单上的父级。

尝试摘录:

if (myControl.TopLevelControl.Handle == GetActiveWindow())
{
     this.myControl.Focus();
}

代码的背景:此代码不归我所有。所以,原谅我是抽象的。我会尽量精心制作。相关控件是一个私有成员自定义布局面板,它继承自System.Windows.Forms.Panel,其中DoubleBuffered属性设置为true。此控件已添加到继承自UserControl(Windows窗体)的内部分部类。后一个控件已通过私有成员SplitContainer(Windows窗体)添加到公共分部类上(也从User Control继承)。

在此布局面板的用户控件的构造函数中,even添加为:

myLayoutPanel.MouseEnter += this.myLayoutPanel_MouseEnter;

没有我改变的事件如下:

private void myLayoutPanel_MouseEnter(object sender, EventArgs e)
    {
        myLayoutPanel.SuspendLayout();
        myLayoutPanel.Focus();
        myLayoutPanel.ResumeLayout(false);
    }

此外,我手动监视控件的父级层次结构的句柄,并且永远无法与活动窗口句柄匹配。直觉上,我觉得GetActiveWindow()使用互操作性来深入研究非托管代码以获取句柄,而顶级属性保留在托管区域中,因此有其限制。我可能错了。

有没有人对此有任何想法?

1 个答案:

答案 0 :(得分:2)

有两个级别的“焦点”。一个是Control形式的“焦点”。一个是Form在桌面上整个窗口组成中的“焦点”。

Control使用这些成员:

Form使用这些成员:

如果您将焦点设置为控制表单内部(通过Focus()),则焦点仅限于表单,并且不会更改表单状态。如果您还想将焦点设置为表单,则需要激活(通过Activate())表单。

重现此行为的最小代码是:

public class MyControl : FlowLayoutPanel {
    private TextBox textBox1;
    private TextBox textBox2;

    public MyControl() {
        this.textBox1 = new TextBox();
        this.Controls.Add(this.textBox1);

        this.textBox2 = new TextBox();
        this.Controls.Add(this.textBox2);

        this.BackColor = Color.Blue; // not required

        this.MouseEnter += this.MyControl_MouseEnter;
    }

    private void MyControl_MouseEnter(object sender, EventArgs e) {
        this.textBox1?.Focus(); // sets focus to the control

        var parentForm = this.FindForm();
        parentForm?.Activate(); // activates the form
    }
}