Alex
Alex

Reputation: 632

Event that triggers BEFORE my form loses focus

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

Answers (2)

Alex
Alex

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

Jeremy Thompson
Jeremy Thompson

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

Related Questions