2015-07-10 49 views
-1

我正在使用SetWindowPos函数实现自动化任务以显示窗口。我知道Windows提供了两种方式来执行此操作:带有超时值的SetWindowPos/ShowWindow

  • 同步:SetWindowPosShowWindow
  • 异步:SetWindowPosSWP_ASYNCWINDOWPOSShowWindowAsync

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

现在,在寻找答案时,我能想出的唯一方法是使用单独的线程并使用SendMessageTimeout,但即使如此,如果线程挂起,除了TerminateProcess之外没有太多的工作可以结束,这不是一个干净的解决方案。

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

+0

您是否从拥有与拥有窗口不同的输入队列的线程发出命令? –

+0

@AdrianMcCarthy是的,还有一个不同的过程。目标是另一个我无法控制的程序。 – Paul

+1

UI自动化(在您链接的其他答案中提到)存在于本机WinAPI程序中。这只是有点难以使用,因为你没有获得管理COM对象的所有运行时帮助。但是如果你想驱动另一个应用程序(特别是你没有写的应用程序),UI自动化通常是最好的方法。 –

回答

2

您链接的问题中的答案只是循环,直到出现所需条件或超时过期。它每次迭代使用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未公开公开。