模态对话框应该是一个弹出窗口,其中有一个系统菜单,一个标题栏和一个粗边框;也就是说,对话框模板应该指定WS_POPUP,WS_SYSMENU,WS_CAPTION和DS_MODALFRAME样式。虽然应用程序可以指定WS_VISIBLE样式,但Windows始终显示模态对话框,无论对话框模板是否指定WS_VISIBLE样式。应用程序不得创建具有WS_CHILD样式的模态对话框。具有此样式的模态对话框将自动禁用,从而防止任何后续输入到达应用程序。
应用程序使用DialogBox或DialogBoxIndirect功能创建一个模态对话框。DialogBox需要包含对话框模板的资源的名称或标识符; DialogBoxIndirect需要包含对话框模板的内存对象的句柄。DialogBoxParam和DialogBoxIndirectParam函数也创建模态对话框;它们与上述功能相同,但在创建对话框时将指定的参数传递给对话框过程。
创建模式对话框时,Windows将使其成为活动窗口。对话框保持活动,直到对话框过程调用EndDialog功能或Windows激活另一个应用程序中的窗口。在模态对话框被销毁之前,用户和应用程序都不能使所有者窗口处于活动状态。
当所有者窗口尚未禁用时,Windows会在创建模态对话框时自动禁用该窗口和属于该窗口的任何子窗口。所有者窗口保持禁用,直到对话框被销毁。虽然对话框过程可能会随时启用所有者窗口,但是使用者无法使用模态对话框的目的,因此不推荐使用。当对话框过程被破坏时,Windows会再次启用所有者窗口,但只有在模式对话框导致所有者被禁用的情况下。
当Windows创建模态对话框时,它会将WM_CANCELMODE消息发送到当前捕获鼠标输入的窗口(如果有)。接收此消息的应用程序应该释放鼠标捕获,以便用户可以在模式对话框中移动鼠标。由于Windows禁用所有者窗口,如果所有者在收到此消息后无法释放鼠标,则所有鼠标输入都将丢失。
要处理模态对话框的消息,Windows将启动自己的消息循环,为整个应用程序临时控制消息队列。当Windows检索对话框未显式的消息时,它会将消息分派到相应的窗口。如果它检索到WM_QUIT消息,它会将消息发回应用程序消息队列,以便应用程序的主消息循环最终可以检索消息。
当应用程序消息队列为空时,Windows会将WM_ENTERIDLE消息发送到所有者窗口。当对话框保留在屏幕上时,应用程序可以使用此消息来执行后台任务。当应用程序以这种方式使用消息时,应用程序必须频繁地进行控制(例如,通过使用PeekMessage函数),以便模态对话框可以接收任何用户输入。要防止模式对话框发送WM_ENTERIDLE消息,应用程序可以在创建对话框时指定DS_NOIDLEMSG样式。
应用程序使用EndDialog功能来销毁模态对话框。在大多数情况下,当用户从对话框的“系统”菜单中选择“关闭”命令或在对话框中选择“确定”或“取消”按钮时,对话框过程将调用EndDialog.该对话框可以通过DialogBox函数(或其他创建函数)返回值,方法是在调用EndDialog函数时指定一个值。Windows在销毁对话框后返回此值。大多数应用程序使用此返回值来确定对话框是否成功完成或被用户取消。在对话框过程调用EndDialog函数之前,Windows不会从创建对话框的函数中返回控件。