I have a Windows Form application that, when the form is Activated, Deactivated, or SizeChanged, the form does something. It's rather specific. For example:
Form Activated: Will set t开发者_StackOverflow社区he variable isActive
to true, and focus the input to an input box for someone to enter something too.
Form Deactivated: Will set the variable isActive
to false, so that any focus changes in the application (caused by remote machine messages, chat messages, etc), does not steal focus from other applications.
Right now, I have my webBrowser1.Focus()
command inside of the Form Activated
event which isn't ideal, as when you click on the taskbar icon, it tries to minimize, but since it focuses back to the web browser, the form is then restored/activated again.
I did some searching here on Stack Overflow, and found the following information:
Edited for the below information:
I did find this information in another post here on 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);
}
But the behavior is similar to the problem I'm seeing with the above 2 events. When the taskbar icon is CLICKED, the form does catch the Deactivated:
Activate False
But then immediately, it does this:
Activate True
It would appear, that when you minimize a window with the taskbar button, it still remains as the 'focused' application until you click on another application.
One of the posts did suggest I capture the GotFocus
of the form, but there is no event that I can find for a form level for GotFocus
, as GotFocus
is derived from a control, not an application form.
Question: How do I allow the form to be minimized with the taskbar button, and when the form is then reshown, get it to do the webBrowser1.Focus()
command to put the focus where it should be?
Here's how I ended up solving the problem. Previously, I was calling Focus() on the ActiveElement in OnActivated. However, in addition to the taskbar minimization call you noticed, pressing Alt-tab to give your form focus also doesn't cause a call to OnActivated.
As a result, I chose to look at the WM_ACTIVATE message to determine when to give focus. From the MSDN docs:
wParam
The low-order word specifies whether the window is being activated or deactivated. This parameter can be one of the following values. The high-order word specifies the minimized state of the window being activated or deactivated. A nonzero value indicates the window is minimized.
[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();
}
}
Sorry I had thought the GotFocus Event would work against the Form but it seems not to fire when the focus on the window itself changes.
So I took the liberty of writing code that does work. It taps into the Form Resize Event instead. I left event handlers for your Activated and Deactivate events in case they were still required but I dont think they should be. Just be sure to call 'Refresh' so the form repaints and the focus moves.
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;
};
}
}
I commented out a test case in the event you want to suppress movement based on a certain Windowstate. Hope this helps.
I don't like your approach with the focuses and this is a brutal hack but you could postpone the change of focus for one second liek this:
Thread t = new Thread((ThreadStart)delegate(){
Thread.Sleep(1000);
this.Invoke(methodChangingFocus, new object[] {});
}).Start();
That could give the opportunity to the user to press the minimize button.
精彩评论