6

For a WPF application, is there internally a classic message loop (in Windows's GetMessage/DispatchMessage sense), inside Application.Run? Is it possible to catch a message posted from another Win32 application with PostThreadMessage to a WPF UI thread (a message without HWND handle). Thank you.

avo
  • 10,101
  • 13
  • 53
  • 81
  • 2
    It might be possible to watch for a specific message with [ComponentDispatcher.ThreadFilterMessage](http://msdn.microsoft.com/en-us/library/system.windows.interop.componentdispatcher.threadfiltermessage.aspx) event, although the docs say it's intended for keyboard messages. Here's a related question [answered](http://stackoverflow.com/questions/476084/c-sharp-twain-interaction). – noseratio Aug 12 '13 at 09:00

1 Answers1

4

I used .NET Reflector to track the Applicaton.Run implementation down to Dispatcher.PushFrameImpl. It's also possible to obtain the same information from .NET Framework reference sources. There is indeed a classic message loop:

private void PushFrameImpl(DispatcherFrame frame)
{
    SynchronizationContext syncContext = null;
    SynchronizationContext current = null;
    MSG msg = new MSG();
    this._frameDepth++;
    try
    {
        current = SynchronizationContext.Current;
        syncContext = new DispatcherSynchronizationContext(this);
        SynchronizationContext.SetSynchronizationContext(syncContext);
        try
        {
            while (frame.Continue)
            {
                if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0))
                {
                    break;
                }
                this.TranslateAndDispatchMessage(ref msg);
            }
            if ((this._frameDepth == 1) && this._hasShutdownStarted)
            {
                this.ShutdownImpl();
            }
        }
        finally
        {
            SynchronizationContext.SetSynchronizationContext(current);
        }
    }
    finally
    {
        this._frameDepth--;
        if (this._frameDepth == 0)
        {
            this._exitAllFrames = false;
        }
    }
}

Further, here's the implementation of TranslateAndDispatchMessage, which indeed fires ComponentDispatcher.ThreadFilterMessage event along its course of execution inside RaiseThreadMessage:

private void TranslateAndDispatchMessage(ref MSG msg)
{
    if (!ComponentDispatcher.RaiseThreadMessage(ref msg))
    {
        UnsafeNativeMethods.TranslateMessage(ref msg);
        UnsafeNativeMethods.DispatchMessage(ref msg);
    }
}

Apparently, it works for any posted message, not just keyboard ones. You should be able to subscribe to ComponentDispatcher.ThreadFilterMessage and watch for your message of interest.

noseratio
  • 59,932
  • 34
  • 208
  • 486