In one of my articles, I have considered
. I tried to look in-depth of
, showed some IL sources of .NET and tried to explain what it is.
While reading MSDN about the threading model, I saw a section, which said that
can be used to create something like WPF dialog windows. That window takes control after calling
and doesn’t return control to the parent window until closed. So, I wondered, how to create such window?
During this article, you will also learn how to get full control on process of showing and hiding custom modal windows and how to control blocking and unblocking of another windows.Custom ShowModal()
For the first, I tried to open a new window in a separate thread. It works! But when I clicked on suspended parent window 5-10 times, that window gets “Not responded”. Not good!
I really wondered how to block parent window, but prevent it from suspension. I thought about how to use
here. Obviously, if the main thread is blocked, then the parent window will be also blocked, because of blocked dispatcher. So, there is no way to use
in such a solution.
After that, I decided to use Reflector to see how
is implemented in WPF. So, what do I see? WINAPI is used there to block each window in the current thread.
[SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("user32.dll", EntryPoint="EnableWindow", CharSet=CharSet.Auto)]
public static extern bool IntEnableWindowNoThrow(HandleRef hWnd, bool enable);
This method is called for each window with
enable = false
. As you guessed, the solution comes closer. To implement my own
, I should perform following steps:
- Block parent window
- Add event handler on modal closed and unblock parent window inside this handler
- Show modal window and call PushFrame()
internal static extern bool EnableWindow(IntPtr hwnd, bool bEnable);
public void ShowModal()
IntPtr handle = (new WindowInteropHelper(Application.Current.MainWindow)).Handle;
DispatcherFrame frame = new DispatcherFrame();
this.Closed += delegate
frame.Continue = false;
First, we define
method which uses WINAPI to enable/disable windows. Exactly that method is used in WPF
. Then we blocks window, show modal and push new
Why do we have to use
here? The answer is to prevent returning from
method. When a new frame is pushed, the main loop is suspended and a new loop starts. This new loop processes system messages and execution point in main loop doesn’t go forward. When modal closes,
DispatcherFrame.Continue = false
, and this frame is exited. And after that, the application is back to normal flow.
This approach has no obvious advantages compared to
method. Dialog behaviour is totally the same.
But there is one benefit that can be very useful in some cases. The benefit provided by this method is full control on blocking and unblocking windows from modal window. Say, what if you needed to block only 2 of 4 active windows? Or unblock window while dialog is shown? It could be problematic with classic
method. Of course, you can use WinAPI, but this is not so obvious as with custom
Also, you can put windows blocking and unblocking command anywhere. Just put
frame.Continue = false
, to places of code, where you want to stop or continue default application flow, and you will get it. It can be useful if you want to continue main frame flow without closing of modal window or otherwise don't continue it after closing.