1

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.

Alex
  • 552
  • 3
  • 15

2 Answers2

1

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);
            }
        }
    }
}
Community
  • 1
  • 1
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
  • OK! this is close. It works sometimes. But sometimes it causes my form to be reactivated. Is there any way to make it more reliable? – Alex Dec 19 '16 at 20:16
  • I was able to improve it by using Send instead of SendWait, sometimes it still reactivates my form(tabs out of the window i just activated). I think the problem is the code isn't being run fast enough and the other tab opens before the Deactivate method executes. – Alex Dec 19 '16 at 20:28
  • Yeah, I noticed if it you click on Desktop for example the app still is active. I'll have a think about a less hacky way than *SendKeys* – Jeremy Thompson Dec 19 '16 at 23:02
  • From my tests the new updated one is happening after the deactivate event. So after the form already lost focus. :( – Alex Dec 20 '16 at 17:28
  • Ok, I finally got a solution that works, not to brag but Its pretty clever i think. Check out my answer. – Alex Dec 20 '16 at 19:40
0

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.

Alex
  • 552
  • 3
  • 15