I'm working on a project to integrate WPF Windows into a large application written in Visual FoxPro. The project has been progressing for a couple of years with success.
One downside to this project is the limitation of the UI thread. FoxPro is an STA app, so there is only one thread that both UI and application services must share. While the application is retrieving data, the UI is locked up. It is my hope that the method we're using to integrate WPF into this app gives us an opportunity to introduce a separate UI thread for the WPF Windows we're using.
How do we integrate WPF into a STA app?
We build a .NET COM server, not an ActiveX control. Instead we're using a simple COM control that exposes events. Our FoxPro client app subscribes to the events and handles UI requests through these events.
We start with a couple of .NET classes that the COM server will use.
// This class allows us to initialize an Application within a COM server
// since there is no App.xaml to do that for us.
[ComVisible(false)]
public class MyApp : System.Windows.Application
{ }
// This class allows us to assign the FoxPro app's main window as the owner
[ComVisible(false)]
public abstract class MyWindow : System.Windows.Window
{
private System.Windows.Interop.WindowInteropHelper _helper;
public void AssignOwner(int hWnd)
{
_helper = new WindowInteropHelper(this);
_helper.Owner = new IntPtr(hWnd);
}
}
The FoxPro app instantiates an instance of the COM server, subscribes to COM events, then calls a method to show the WPF window. The COM server's Show method first causes this bit of code to execute once per VFP app by delegating it to a static class.
if (Application.Current == null)
_ = new MyApp();
if (Application.Current != null)
{
Application.Current.ShutdownMode = ShutdownMode.OnExplicitShutdown;
Application.Current.DispatcherUnhandledException += Application_DispatcherUnhandledException;
}
The Show method then builds a Window and displays it. There's nothing special here.
// Build a business model to access data and services through COM events
var model = new MyModel(this);
// ShellView is an implementation of MyWindow
var window = new ShellView { DataContext = new ShellViewModel(model) };
if (hWnd > 0)
window.AssignOwner(hWnd); && hWnd is a handle to the FoxPro window
window.Show();
The Question
Does the static code that builds the WPF Application instance give us the opportunity to construct a separate UI thread for the Dispatcher used by the WPF components?