我有一个Windows窗体应用程序,当窗体是Activated,Deactivated或SizeChanged时,窗体会执行某些操作。这是相当具体的。例如:
表单已激活:将变量isActive
设置为true,并将输入重点放在输入框中,以便某人输入内容。
表单已停用:将变量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个事件中看到的问题。当任务栏图标为CLICKED时,表单会捕获Deactivated:
激活假
然后立刻就这样做了:
激活True
看来,当您使用任务栏按钮最小化窗口时,它仍然作为“聚焦”应用程序保留,直到您单击另一个应用程序。
其中一个帖子确实建议我捕获表单的GotFocus
,但我找不到GotFocus
的表单级别的事件,因为GotFocus
来自一个控件,而不是一个申请表。
问题:如何使用任务栏按钮最小化表单,然后在重新表示表单时,让它执行webBrowser1.Focus()
命令将焦点放在何处它应该是?
答案 0 :(得分:2)
以下是我最终解决问题的方法。以前,我在OnActivated的ActiveElement上调用Focus()。但是,除了您注意到的任务栏最小化调用之外,按Alt-tab键使您的表单重点也不会导致对OnActivated的调用。
因此,我选择查看WM_ACTIVATE消息以确定何时给予焦点。来自MSDN docs:
的wParam
低位字指定窗口是否被激活或 停用。此参数可以是以下值之一。该 高位字指定窗口的最小化状态 激活或停用。非零值表示窗口是 最小化。
[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();
}
}
答案 1 :(得分:0)
我不喜欢你的焦点方法,这是一个残酷的黑客,但你可以推迟焦点的变化一秒钟这个:
Thread t = new Thread((ThreadStart)delegate(){
Thread.Sleep(1000);
this.Invoke(methodChangingFocus, new object[] {});
}).Start();
这可以让用户按下最小化按钮。
答案 2 :(得分:0)
很抱歉我原本以为GotFocus事件会对表单起作用,但是当窗口本身的焦点发生变化时似乎不会触发。
所以我冒昧地编写了有效的代码。它改为使用Form Resize Event。我为你的Activated和Deactivate事件留下了事件处理程序,以防它们仍然需要但我不认为它们应该是。只需确保调用'刷新',以便重新绘制表单并重点移动。
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抑制移动,我会注释掉一个测试用例。希望这会有所帮助。