2013-01-04 84 views
3

我有一個WPF項目下面的C#代碼:WPF窗口應該是有模式,以本地所有者窗口,但不

private static void RunConfig(string owner) 
{ 
    long ownerHandle; 
    var settingsWindow = new SettingsWindow(); 
    if (long.TryParse(owner, out ownerHandle)) 
    { 
     WindowInteropHelper helper = new WindowInteropHelper(settingsWindow); 
     helper.Owner = new IntPtr(ownerHandle); 
    } 
    settingsWindow.ShowDialog(); 
} 

的SettingsWindow沒有正確模態的所有者窗口(即我可以在SettingsWindow仍然打開的情況下關注所有者窗口,與之交互,甚至關閉所有者窗口)。我究竟做錯了什麼?

對於上下文,此代碼是屏幕保護程序的一部分,所有者窗口是控制面板屏幕保護程序選擇窗口(通過命令行參數傳入句柄以用作所有者)。我知道IF語句正在評估真實和正確解析句柄。

我已經使用SetWindowLongPtr方法從user32.dll也嘗試(編譯爲64位,因此不使用SetWindowLong),其是簡要描述here並且在使用中here所示。此方法適用於WinForms,但在WPF中似乎不起作用。幫助我Obi-Wan Kenobi,你是我唯一的希望。

+0

是'SettingsWindow'一個winforms窗口?因爲如果'SettingsWindow'是WPF,'ShowDialog()'應該阻止對主WPF窗體的訪問 –

+0

不,SettingsWindow是一個WPF窗口。我的程序沒有打開任何其他窗口,沒有「主」窗口。控制面板屏幕保護程序選擇窗口是一個本地窗口,它應該被設置爲settingsWindow的所有者。 ShowDialog()會阻止我的程序的UI線程,但這不是問題。我需要settingsWindow來防止焦點和與控制面板窗口的交互,直到settingsWindow關閉(即[模態窗口](http://en.wikipedia)。org/wiki/Modal_window) – Jargon

+0

我注意到,當使用WindowInteropHelper來設置窗口的所有者時,窗口現在總是位於所有者之上,即使所有者仍然可以獲得焦點並與之交互。 所以它正在做一些事情,而不是它應該做的一切...... – Jargon

回答

5

事實證明,使用WindowInteropHelper將本機窗口設置爲WPF窗口的所有者確實工作,但它並不能完成整個工作。當以這種方式設置時,即使本機窗口具有焦點,WPF窗口仍會在本機窗口頂部顯示。但是,這是獲得的唯一效果。 WPF窗口不會阻止與本機窗口的交互,並且本地窗口甚至可以關閉,而不會關閉或影響WPF窗口。

爲了獲得所需的行爲的其餘部分,我們需要使用EnableWindow功能user32.dll禁用本地窗口的WPF窗口調用ShowDialog之前,再一次WPF窗口關閉,以重新啓用它。

修改後的代碼看起來是這樣的:

private static void RunConfig(string owner) 
{ 
    long ownerHandle; 
    var settingsForm = new SettingsWindow(); 
    if (long.TryParse(owner, out ownerHandle)) 
    { 
     WindowInteropHelper helper = new WindowInteropHelper(settingsForm); 
     helper.Owner = new IntPtr(ownerHandle); 
     NativeMethods.EnableWindow(helper.Owner, false); 
     settingsForm.ShowDialog(); 
     NativeMethods.EnableWindow(helper.Owner, true); 
    } 
    else 
    { 
     settingsForm.ShowDialog(); 
    } 
} 

(注:上面的代碼一般是正確的,但在屏幕保護程序的情況下,這實際上是被用來做什麼的這段代碼不完整在代碼用於屏幕保護程序的配置窗口的情況下,爲所有者句柄傳入的字符串不是要用作所有者的控制面板窗口的句柄,而是用於控制的句柄,它是控制面板「窗口中的子控件,這種情況下的額外步驟是獲取該控件的父控件的句柄,我們可以通過調用GetParent(也可以在user32.dll中)在傳入的控件上執行此操作。 n個真正的手柄,我們要使用的所有者和EnableWindow電話。)

如果微軟沒有人發現這一點,也許考慮修改WindowInteropHelper正確設置所有的這件事時Owner分配和使用ShowDialog,因爲這是模態窗口的正確完整行爲。

相關問題