Reputation: 632
I need to be alerted before my entire form loses focus. The Deactivate event only triggers after it loses focus. LostFocus and Leave are only for controls.
I have also tried overriding WndProc but this only triggers after the message has been processed.
overriding PreProcessMessage only can be used for keyboard stuff, not form deactivation.
Upvotes: 1
Views: 392
Reputation: 632
Got it, this hack works perfectly.
private void MyForm_Deactivate(object sender, EventArgs e)
{
Thread.Sleep(200); //delay to allow external tab time to open
Form f1 = new Form(); //create a new form that will take focus, switch input, then terminate itself
f1.Shown += new EventHandler((s, e1) => { f1.Activate(); InputLanguage.CurrentInputLanguage = InputLanguage.DefaultInputLanguage; f1.Close(); });
f1.Show();
}
EDIT: upon further testing I have found this to be equally unreliable. It doesn't seem like there is a good way to do this at all.
For now I am tracking the mouse and keyboard to detect when the user is about to deactivate it. Obviously a mouse and keyboard hook is a horrible solution but its the only reliable solution so far.
Upvotes: 0
Reputation: 65554
Dodgy Method
Even though this is a quick and hacky way of doing it, changing Input Language is unnatural to start with..
private void Form1_Deactivate(object sender, EventArgs e)
{
((Form)sender).Activate();
System.Diagnostics.Debug.WriteLine(this.ActiveControl.Name);
//Change Input Language here..
//Alt TAB to set focus to the application selected 5 milliseconds ago
SendKeys.SendWait("%{TAB");
}
Correct and orthadox method
How to monitor focus changes? and C#: Detecting which application has focus
Its using the Automation framework, Add references to UIAutomationClient
and UIAutomationTypes
and use Automation.AddAutomationFocusChangedEventHandler
, e.g.:
public class FocusMonitor
{
public FocusMonitor()
{
AutomationFocusChangedEventHandler focusHandler = OnFocusChanged;
Automation.AddAutomationFocusChangedEventHandler(focusHandler);
}
private void OnFocusChanged(object sender, AutomationFocusChangedEventArgs e)
{
AutomationElement focusedElement = sender as AutomationElement;
if (focusedElement != null)
{
int processId = focusedElement.Current.ProcessId;
using (Process process = Process.GetProcessById(processId))
{
Debug.WriteLine(process.ProcessName);
}
}
}
}
Upvotes: 1