Вопрос

I have a simple WPF form with a textbox and button and on lost focus it simply simply shows a message box. My code looks like this

   private void TextBox_LostFocus(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine("Lost Focus 1");
        Dispatcher.BeginInvoke(new Action(() =>
               {
                   //Uncomment below lines to get button click
                   //Thread.Sleep(100);
                   //System.Windows.Forms.Application.DoEvents();
                   MessageBox.Show("Lost focus");
               }
            ));
    }
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine("Button_Click");
    }

If my textbox has focus and when I click on button then Button click is not fired if the messagebox is shown but if I call Application.DoEvents() before I show messagebox then my button click get fired.

My actual application is bit more complex but I have tried to simulate this behavior with a simple textbox and a button. In actual application one of my background worker thread post on dispatcher to show a modal messagebox (or even WPF form) and any UI pending messages in queue seems to be handled by messagebox (I suspect) so for e.g. If I click on a canvas control Ideally I get "Mouse Down" and "Mouse Up" but if a Modal messagebox comes in between this 2 message then I only get "Mouse Down" and "Mouse Up" message is lost.

Note: I don't see this behavior is not seen in case of Non-Modal dialogs.

Also just for my knowledge if someone can point me out on nice articles of how does windows forms handles windows message pump in case of Modal dialog and Non-Modal dialog would be helpful.

Это было полезно?

Решение

You can set the priority you want for your Dispatcher action using the DispatcherPriority parameter of the BeginInvoke() method. Lowest priority I usually use would be ApplicationIdle, thus allowing the Dispatcher to finish processing all its pending operations before processing yours.

Dispatcher.BeginInvoke(new Action(() =>
{
   MessageBox.Show("Lost focus");
}), DispatcherPriority.ApplicationIdle);

Другие советы

The text control loses focus before the button click occurs (possibly before it even gets the mouse-button-down message, not sure about that), causing the MessageBox to be shown. The MessageBox this calls up is modal and disables the button before the button gets the button-up message that makes the button "click".

Modal dialog boxes have their own message loop so that they don't have to return from ShowDialog immediately, but they also disable their calling/owner/parent (I forget which) window until they return.

It is not a matter of which message loop is handling the mouse-button-up message, but of the relative timing of this message and the button control being disabled by the modal form being shown. Think about what the timing would be if you clicked and held the mouse button for a second or two. I suspect you would find that the MessageBox appears before you release the mouse button.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top