简体   繁体   中英

C# - How to detect user's attempt to remove focus from a modal form

I need a modal form to notify user (eg by shaking itself) when user is attempting to access any other form of the application (by mouse clicking or anyhow else). The problem is that I can't detect this attempt. Events /Deactivate,LostFocus,Leave/ just don't work. ADD: the modal form is borderless , so when a user clicks on the parent form (which is disabled when the modal form is open) - NOTHING happens. Form has no border, so it's not flashing. That's why I need some way to notify the user, that he must close the modal form to access the parent one. I decided to shake the modal form to make user pay attention to it. But for this I must catch the event when user tries to access parent form. I don't know how to do this.

Use Form.ShowDialog() instead of Form.Show()

ShowDialog shows your window as modal, which means you cannot interact with the parent form until it closes.

And you can disable parent form

this.Enabled = false;
MyChildForm childForm = new MyChildForm();
childForm.ShowDialog(this);

You could do something a bit hacky:

Firstly, add a boolean property to your main form (the one that you want to flash, not the modal form) so you can track whether the modal form is shown:

bool inModalForm;

void button1_Click(object sender, EventArgs e)
{
    using (var form = new Form2())
    {
        this.BeginInvoke(new Action(() => inModalForm = true));
        form.ShowDialog();
        inModalForm = false;
    }
}

Set the boolean using BeginInvoke() because you will get a window message about the main window's position changing after inModalForm is set, which you don't want.

Then override WndProc() in your main form as follows:

protected override void WndProc(ref Message m)
{
    const int WM_WINDOWPOSCHANGING = 0x46;

    if (inModalForm && (m.Msg == WM_WINDOWPOSCHANGING))
    {
        Debug.WriteLine("Someone's trying to activate the window.");
    }

    base.WndProc(ref m);
}

Make your window flash where I put the Debug.WriteLine(). I should think you will need to use this.BeginInvoke() to call your flash method; you don't want to be doing it from inside WndProc() !

This isn't perfect because I think you can get the occasional spurious message (for example if neither form has the focus and you then click on the modal form), but perhaps it will do.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM