我正在使用c#,我想创建一个模式窗口,我想使用Windows API中的方法。 SetWindowPos函数可以使一个窗口成为最顶层的窗口,但是我找不到一种方法来使它成为模态...
有没有办法用SetWindowPos这样做,或者如果没有,是否还有其他Windows功能呢?
答案 0 :(得分:3)
考虑到您的问题已标记为c#,您可以随意使用整个.NET Framework,它提供了将窗口(表单)显示为模式对话框的内置功能。没有理由你必须从Windows API调用函数来执行此操作。
通常,从Windows API进行P / Invoke功能的唯一原因是使用尚未通过托管代码公开的功能。普通应用程序必须很少这样做,并且显示模式对话框等基本用例当然不需要它。
在C#(或任何.NET语言)中执行此操作的方法是更改显示相关表单的方式。您应该使用Form.ShowDialog
method。
Form.Show
方法
有两个可用的重载。 first不接受任何参数,并将对话框的所有者设置为当前活动窗口。 second接受一个参数,该参数指定将拥有此对话框的窗口。
Form.Modal
property提供了一种快速检查表单是否以模态方式显示的方法。但是,如文档所述,它是只读的。以模态方式显示表单的唯一方法是调用ShowDialog
方法,如上所述。
就Windows API解决方案而言,没有任何此类功能可以调用。创建窗口后,无法将窗口转换为模态对话框。你最初必须以这种方式显示它。在Win32应用程序中,您可以通过调用DialogBox
function(而不是CreateDialog
)来执行此操作。
MFC使用CDialog::DoModal
function显示模态对话框,但它并未真正显示模式对话框。相反,它使用hack来创建伪(或模拟)模式对话框,该对话框涉及禁用所有者窗口,在DoModal
方法内运行自己的消息循环,并等待预先定义了一系列事件,使模态循环正常退出。我不建议您在自己的应用程序中执行此操作。这根本不是必要的,而且很容易出错。 MFC方法中存在足够的错误,该团队完全掌握了Win32内部的知识。
WinForms中的ShowDialog
方法适用于与MFC非常相似的模型。 Hans的回答here提供了更多信息。请注意,如果您要实现自己的模态对话框循环,则需要记住重新启用
所有者窗口首先,然后销毁模态对话框。如果不按正确的顺序执行此操作,则最终会出现具有焦点的错误窗口。微软的Raymond Chen发布了一篇关于此的博客文章:The correct order for disabling and enabling windows。
编辑:根据提问者的评论添加了更多信息。
我不确定为什么需要您创建的包装器来将保存对话框自定义为UserControl
。它不是一个控件,用户不会在表单上与它进行交互。您只需要从代码中显示它。因此,我认为更好的选择是创建一个新类,称之为SaveDialogHelper
,并公开一个名为ShowSaveDialog
的静态方法或类似的东西。例如:
public static class SaveDialogHelper
{
public string ShowSaveDialog(IWin32Window owner)
{
// Fill the OPENFILENAME struct, and do any necessary customizations
// ...
// Show the save dialog
// ...
// Return the path that was selected by the user
// ...
}
}
请注意,ShowSaveDialog
函数接受类型为IWin32Window
的单个参数(owner
),就像.NET Framework中的ShowDialog
方法一样。调用该函数时,只需指定要拥有对话框的表单:
SaveDialogHelper.ShowSaveDialog(this);
在函数内部,您可以使用Handle
property提取窗口句柄(Win32术语中的hwnd
),并相应地设置hwndOwner
结构的OPENFILENAME
成员:
hwndOwner = owner.Handle;
答案 1 :(得分:1)
如果不是在创作时,你就无法制作模态。但是,您可以通过禁用其 parent 所有者来实现类似的效果。