2013-01-04 44 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,因为这是模态窗口的正确完整行为。

相关问题