【问题标题】:Cannot find the main window handle of the just stareted Dialog APP刚启动的Dialog APP找不到主窗口句柄
【发布时间】:2015-08-14 11:39:46
【问题描述】:

这是场景:

我有 2 个应用程序。其中一个是我的主应用程序,第二个是基于对话框的应用程序,它是从第一个应用程序开始的。我正在尝试从我的主应用程序中捕获基于对话框的应用程序的主句柄。问题是我无法使用 EnumWindows 找到它。如果我在开始枚举窗口之前休眠一秒钟,问题就会消失。

这是代码:

...

BOOL res = ::CreateProcess( NULL, _T("MyApp.exe"), NULL, NULL, FALSE, NULL, NULL, NULL, &siStartInfo, &piProcInfo );
ASSERT(res);
dwErr = WaitForInputIdle(piProcInfo.hProcess, iTimeout); 
ASSERT(dwErr == 0);

//Sleep(1000); //<-- uncomment this will fix the problem

DWORD dwProcessId = piProcInfo.dwProcessId; 
EnumWindows(EnumWindowsProc, (LPARAM)&dwProcessId);
....

BOOL IsMainWindow(HWND handle)
{
   return GetWindow(handle, GW_OWNER) == (HWND)0 && IsWindowVisible(handle);
}

BOOL CALLBACK EnumWindowsProc(HWND  hwnd,   LPARAM  lParam)
{
    DWORD* pParam = (DWORD*)lParam;
    DWORD dwTargetProcessId = *pParam;
    DWORD dwProcessId = 0;
    ::GetWindowThreadProcessId(hwnd, &dwProcessId);

   if (dwProcessId == dwTargetProcessId )
    {
      TCHAR buffer[MAXTEXT];
      ::SendMessage(hwnd, WM_GETTEXT, (WPARAM)MAXTEXT,(LPARAM)buffer);

      if( IsMainWindow(hwnd))      
      {
          g_hDlg = hwnd;
          return FALSE;
      }
    }

    return TRUE;
}

正好有 2 个窗口属于我的进程并跟踪它们的文本显示:

GDI+ Window
Default IME

我不太确定这是什么意思。这些可能是在初始化之前分配给窗口的默认标题....但我在 WaitForInputIdle 之后调用 EnumWindows ...

任何帮助将不胜感激。

【问题讨论】:

  • 你需要解释一下什么是“主窗口”?它与另一个顶级窗口有何不同?
  • 嗨,主窗口是指主窗口:)。那些处理所有其他人的人。在这种情况下,主窗口是 Dialog。
  • 这就像说“我指的是那个窗口” :) 你称之为“主”的窗口有什么特别之处?你怎么能把它和其他窗口区分开来,比如“GDI+窗口”?
  • 好吧,我用“主窗口”这个词来表示由 CreateWindow 创建的 Dialog Window 可能不太正确。例如。这是父基窗口,这意味着所有其他窗口都是它的子窗口。
  • 所有的窗口都是由 CreateWindow() 创建的。 EnumWindows() 没有枚举任何子窗口。您需要找到其他可以让您的“主”窗口与众不同的东西。

标签: winapi visual-c++ win32gui


【解决方案1】:

CreateProcess 返回,当操作系统创建了包含代表主线程的对象的进程对象时。这并不意味着进程已经开始执行。

如果您需要查询另一个进程以获取仅在该进程运行到某个点后才可用的信息,您将需要安装某种同步。一个明显的选项是命名事件对象(参见CreateEvent),它在第二个进程完成初始化并且对话框启动并运行时发出信号。然后,第一个过程将简单地WaitForSingleProcess,并且只有在事件发出信号后才会继续。 (更强大的解决方案是在事件和进程句柄上调用WaitForMultipleObjects,以响应意外的进程终止。)

另一种选择是让第二个进程向第一个进程发送用户定义的消息 (WM_APP+x),同时传递其 HWND


WaitForInputIdle 听起来是一个可行的解决方案。除了,它不是。 WaitForInputIdle 是为了满足 DDE 的要求而引入的,只是检查目标进程中的线程是否可以接收消息。这实际上意味着该过程中的任何线程。它并不严格依赖于启动和运行的 GUI。

可以在此处找到有关该主题的其他信息:

【讨论】:

  • 因此我使用 WaitForInputIdle。根据 MSDN: WaitForInputIdle :等待直到指定进程完成处理其初始输入并等待用户输入,没有输入挂起,
  • 哈,感谢您的帮助 :)。事实上,WaitForInputIdle 没有按预期工作,至少对于单线程应用程序没有。我同意更好的解决方案是引入事件。
猜你喜欢
  • 2013-11-11
  • 1970-01-01
  • 1970-01-01
  • 2010-12-06
  • 1970-01-01
  • 2010-11-28
  • 2011-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多