我已經創建了一個示例應用程序,花費了整整一天的時間解決了您的問題。
Solution can be downloaded here
做些什麼: 點擊按鈕來創建新的線程窗口。在新線程上爲您創建一個新窗口。創建此新窗口時,主窗口中的此按鈕將被禁用。當你關閉你的新窗口時,主窗口中的創建按鈕再次啓用。
如果它不符合您的需求,請告訴您的要求,我會改進它。在不使用事件橋接類的情況下,也可以使用純Win32函數完成。我正在做。我將盡快發佈win32版本。
- 我在單獨的線程上創建NewWindow。如果你關閉了MainWindow,那麼NewWindow仍然會像新線程一樣運行。
- 我保持它完全獨立,因爲在MainWindow中沒有實例用於指向NewWindow。要解決此問題,我正在使用Win32句柄。
- 對於NewWindow將通知發送到MainWindow,我使用靜態類WindowNotifier與靜態事件。這個班級是兩者之間的橋樑。在NewWindow Closing/Closed/Loaded事件用於觸發事件。
- MainWindow處理此靜態類的各種事件以保持有關NewWindow的更新。使用
Win32函數:
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
ThreadCreator.cs
public static class ThreadCreator
{
private static NewWindow W;
public static void CreateWindow()
{
Thread t = new Thread(ThreadProc);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private static void ThreadProc(object obj)
{
W = new NewWindow();
W.ShowDialog();
}
}
WindowNotifier.cs
public static class WindowNotifier
{
public static event CreatedDelegateCallback IamCreatedEvent;
public delegate void CreatedDelegateCallback(IntPtr handle);
public static event ClosingDelegateCallback IamClosingEvent;
public delegate void ClosingDelegateCallback (IntPtr handle);
public static event ClosedDelegateCallback IamClosedEvent;
public delegate void ClosedDelegateCallback(IntPtr handle);
public static void OnIamCreated(IntPtr handle)
{
if (IamCreatedEvent != null)
IamCreatedEvent(handle);
}
public static void OnIamClosing(IntPtr handle)
{
if (IamClosingEvent != null)
IamClosingEvent(handle);
}
public static void OnIamClosed(IntPtr handle)
{
if (IamClosedEvent != null)
IamClosedEvent(handle);
}
}
MainWindow.xaml.cs
個
...
void WindowNotifier_IamCreatedEvent(IntPtr handle)
{
HandleOfWindowOnNewThread = handle;
Debug.WriteLine(string.Format("I am created : {0}", handle));
btnCreateNewWindow.Dispatcher.Invoke(() => btnCreateNewWindow.IsEnabled = false);
}
void WindowNotifier_IamClosedEvent(IntPtr handle)
{
if (HandleOfWindowOnNewThread == handle)
HandleOfWindowOnNewThread = IntPtr.Zero;
Debug.WriteLine(string.Format("I am closed : {0}", handle));
btnCreateNewWindow.Dispatcher.Invoke(() => btnCreateNewWindow.IsEnabled = true);
}
...
NewWindow.xaml.cs
...
private void Window_Closed(object sender, EventArgs e)
{
WindowNotifier.OnIamClosed(Handle);
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
WindowNotifier.OnIamClosing(Handle);
}
// To get correct handle we need to ensure Window is fully created and active
private void Window_Loaded(object sender, RoutedEventArgs e)
{
_handle = GetForegroundWindow();
WindowNotifier.OnIamCreated(Handle);
}
...
你得到什麼異常? – Sievajet
窗口派生自DispatcherObject,它保存對與創建窗口的線程關聯的Dispatcher的引用。 類似: _window.Dispatcher,BeginInvoke的(()=> ,,,,,); –
@Sievajet wpf窗口在另一個線程上創建,所以我得到一個異常,我無法從另一個線程訪問它。至少用這個方法。我想從主線程調用它。 – konrad