【问题标题】:SetWindowPos/ShowWindow with a timeoutSetWindowPos/ShowWindow 超时
【发布时间】:2015-07-10 20:15:17
【问题描述】:

我正在使用SetWindowPos 函数来执行自动化任务以显示一个窗口。我知道 Windows 提供了两种方法来做到这一点:

  • 同步:SetWindowPosShowWindow
  • 异步:SetWindowPosSWP_ASYNCWINDOWPOSShowWindowAsync

现在,我想要两全其美:我希望能够同步显示窗口,因为我希望它在函数返回时完成。 但是我不希望调用挂起我的进程 - 如果需要太长时间,我希望能够中止调用。

现在,在寻找答案时,我唯一能想到的就是使用单独的线程并使用SendMessageTimeout,但即便如此,如果线程挂起,我也无能为力,除了TerminateProcess,这不是一个干净的解决方案。

我也见过this answer,但据我了解,它没有原生WinAPI的替代品。

【问题讨论】:

  • 您是否从一个线程发出命令,该线程的输入队列与拥有窗口的线程不同?
  • @AdrianMcCarthy 是的,还有一个不同的过程。目标是另一个我无法控制的程序。
  • UI 自动化(在您链接到的其他答案中提到)存在于本机 WinAPI 程序中。它只是有点难以使用,因为您在管理 COM 对象时没有获得所有运行时帮助。但是,如果您尝试驱动另一个应用程序(尤其是您未编写的应用程序),UI 自动化通常是最好的选择。

标签: c windows multithreading winapi


【解决方案1】:

您链接到的问题中的答案只是循环,直到出现所需的条件或超时到期。它每次迭代都使用Sleep() 以避免占用处理器。所以WinAPI的一个版本可以很简单的写出来,如下:

bool ShowWindowAndWait(HWND hWnd, DWORD dwTimeout) {
    if (IsWindowVisible(hWnd)) return true;
    if (!ShowWindowAsync(hWnd, SW_SHOW)) return false;
    DWORD dwTick = GetTickCount();
    do {
        if (IsWindowVisible(hWnd)) return true;
        Sleep(15);
    } while (dwTimeout != 0 && GetTickCount() - dwTick < dwTimeout);
    return false;
}

不幸的是,我认为这是你能得到的最好的。 SendMessageTimeout 实际上不能用于此目的,因为(据我所知)没有可以发送的实际消息会导致显示目标窗口。 ShowWindowAsyncSWP_ASYNCWINDOWPOS 都通过调度内部窗口事件来工作,并且此 API 未公开。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    相关资源
    最近更新 更多