为什么IsDialogMessage()永远不会返回?

时间:2009-11-11 16:58:35

标签: winapi

我正在调试一个应用程序,它在消息循环中调用IsDialogMessage()。偶尔,IsDialogMessage()永远不会返回(绝不会是大于1小时的间隔)。根据Microsoft的符号服务器提供的user32.dll符号,它似乎停留在GetNextDlgGroupItem()(或相同的内部变体)中,迭代某些窗口。

应用程序是多线程的,并且经常接收外部事件的通知,这些事件作为DCOM调用到达。我怀疑这种调用的处理方式不正确会破坏某些窗口状态。如果我可以了解哪种状态腐败可能导致IsDialogMessage()中的无限循环,我想我将更容易识别腐败的来源。

4 个答案:

答案 0 :(得分:3)

我知道这是陈旧的,但回答后代,因为这里没有人提到它。

正在发生的事情很可能是Windows管理器确定转发消息的位置的问题。如果你有一个windows层次结构,那么你需要确保包含控件本身的非顶级窗口必须设置WS_EX_CONTROLPARENT样式。如果是对话框,则使用DS_CONTROL样式。这些标志的存在会修改IsDialogMessage的行为;他们将窗口标识为具有自己的控件,可以接收焦点并处理Tab键顺序等,而不仅仅是控件本身。

例如,如果你有一个主框架窗口,它有一个带WS_EX_CONTROLPARENT的子窗口,它有一个子窗口没有 WS_EX_CONTROLPARENT,它有一个具有焦点的子窗口,你点击了TAB ,你可能会在你提到的同一个地方遇到无限循环。

将第二个子项的扩展样式设置为包含WS_EX_CONTROLPARENT将解决此问题。

答案 1 :(得分:0)

您是否可以在不首先检查该控件是否具有焦点的情况下禁用控件(使用::EnableWindow())?如果是,则焦点会丢失,GetNextDlgGroupItem()会混淆。

答案 2 :(得分:0)

这种情况可能发生的另一个原因是,如果您重新显示无模式对话框。至少wxWidgets会发生这种情况......

答案 3 :(得分:0)

我做了一些调查,试图回答这个问题。但只有在情况下,父窗口在本机MFC项目中,子窗口是托管C#Windows窗体。如果您有这种情况,那么您可以尝试3种分辨率:

  1. 在Windows窗体端运行MFC对话框消息循环。以下是更多信息:Integrate Windows Forms Into Your MFC Applications Through C++ Interop
  2. 创建2个线程:一个用于Windows窗体对话框,另一个用于本机对话框。在这里,您可以在Windows窗体中创建对话框,然后使用SetParent()将其父级设置为本机对话框。但是要洁具:如果你将TabControl添加到Windows窗体,而不是挂起“IsDialogMessage()永远不会返回”。
  3. 为Windows窗体对话框创建一个包装器,以便在本机项目中使用。例如,包装器可能是WPF,请参见此处:Windows Form as child window of an unmanaged app
  4. 我主要从http://msdn.microsoft.com/en-us/library/ms229600.aspx

    获取信息

    临时治愈可以改变焦点行为。例如,禁用它们,或仅将SetFocus()禁用到父窗口或子窗口。但我强烈建议调查真正的原因,为什么IsDialogMessage()永远不会返回你的情况。