任务栏最小化c# Windows窗体问题
本文关键字:窗体 体问题 Windows 最小化 任务栏 | 更新日期: 2023-09-27 17:53:14
我有一个Windows窗体应用程序,当窗体被激活,去激活或sizechange时,窗体做一些事情。这是相当具体的。例如:
表单激活:将变量isActive
设置为true,并将输入集中到一个输入框中,以便其他人也可以输入一些内容。
Form Deactivated:将变量isActive
设置为false,这样应用程序中的任何焦点更改(由远程机器消息,聊天消息等引起)都不会从其他应用程序窃取焦点。
现在,我有我的webBrowser1.Focus()
命令在Form Activated
事件,这是不理想的,因为当你点击任务栏图标,它试图最小化,但由于它的焦点回到web浏览器,窗体然后恢复/激活再次。
我在这里做了一些搜索Stack Overflow,并找到了以下信息:
编辑以下信息:
我确实在另一篇关于Stack Overflow的文章中找到了这个信息:
protected void OnActivateApp(bool activate)
{
Console.WriteLine("Activate {0}", activate);
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
// Trap WM_ACTIVATEAPP
if (m.Msg == 0x1c) OnActivateApp(m.WParam != IntPtr.Zero);
base.WndProc(ref m);
}
但是行为类似于我在上面2个事件中看到的问题。当任务栏图标被点击时,表单会捕捉到Deactivated:
激活假
然后,它立即这样做:
激活真正的
看起来,当你最小化带有任务栏按钮的窗口时,它仍然是"聚焦"的应用程序,直到你点击另一个应用程序。
其中一个帖子确实建议我捕获表单的GotFocus
,但是没有事件,我可以找到GotFocus
的表单级别,因为GotFocus
是从控件派生的,而不是应用程序表单。
问题:我如何允许表单与任务栏按钮最小化,然后重新显示表单时,让它做webBrowser1.Focus()
命令将焦点放在应该在的地方?
我是这样解决这个问题的。以前,我在OnActivated中的ActiveElement上调用Focus()。然而,除了你注意到的任务栏最小化调用,按alt选项卡给你的表单焦点也不会导致调用OnActivated。
因此,我选择查看WM_ACTIVATE消息以确定何时给予焦点。来自MSDN文档:
按钮
低序字指定窗口是被激活还是被激活停用。该参数可以是以下值之一。的高阶字指定窗口的最小状态已激活或未激活。非零值表示窗口为最小化。
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message message)
{
base.WndProc(ref message);
if (message.Msg == 0x6)
{
int highOrderWord = (int)((message.WParam.ToInt32() & 0xFFFF0000) >> 16);
bool minimized = highOrderWord != 0;
bool activating = message.WParam != IntPtr.Zero;
if (activating && !minimized)
{
this.FocusBrowserElement();
}
}
}
private void FocusBrowserElement()
{
if (!this.webBrowser.IsDisposed &&
this.webBrowser.Document != null &&
this.webBrowser.Document.ActiveElement != null)
{
this.webBrowser.Document.ActiveElement.Focus();
}
}
对不起,我曾认为GotFocus事件会对窗体起作用,但当窗口本身的焦点发生变化时,它似乎不会触发。
所以我冒昧地写了一些可以工作的代码。而是使用Form Resize事件。我留下事件处理程序为您的激活和停用事件,以防他们仍然需要,但我不认为他们应该。只要确保调用'Refresh',这样表单就会重新绘制,焦点也会移动。
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private bool isActive = false;
private FormWindowState previousstate;
private void Form1_Load(object sender, EventArgs e)
{
previousstate = this.WindowState;
//Got Focus Anonymous Delegate handles focus on the textbox
//if the Form currently is Activated
this.Resize += delegate(object resizesender, EventArgs resizee)
{
//if (previousstate == FormWindowState.Minimized)
// {
txtGetFocus.Focus();
this.Refresh();
// }
previousstate = this.WindowState;
};
this.Activated += delegate(object activatedsender, EventArgs activatede)
{
isActive = true;
};
this.Deactivate += delegate(object deactivatesender, EventArgs deactivatee)
{
isActive = false;
};
}
}
我注释掉了一个测试用例,如果你想基于某个Windowstate来抑制移动。
我不喜欢你对焦点的方法,这是一个残酷的hack,但你可以推迟焦点的改变一秒钟,像这样:
Thread t = new Thread((ThreadStart)delegate(){
Thread.Sleep(1000);
this.Invoke(methodChangingFocus, new object[] {});
}).Start();
这样用户就有机会按下最小化按钮