2015-07-10 2 views
-1

Я использую функцию SetWindowPos для задачи автоматизации, чтобы показать окно. Я знаю, что есть два способа, которые предоставляет Windows, чтобы сделать это:SetWindowPos/ShowWindow с таймаутом

  • Синхронно: SetWindowPos или ShowWindow.
  • Асинхронно: SetWindowPos с SWP_ASYNCWINDOWPOS или ShowWindowAsync.

Теперь я хотел бы получить лучшее из обоих миров: я хочу иметь возможность показывать окно синхронно, потому что я хотел бы, чтобы это было сделано, когда функция возвращается. Но Я не хочу, чтобы вызов зависал мой процесс - если это занимает слишком много времени, я хочу, чтобы можно было прекратить вызов.

Теперь, когда вы ищете ответ, единственное, что я мог придумать, это использовать отдельный поток и использовать SendMessageTimeout, но даже тогда, если зависает нить, я не могу сделать это, чтобы закончить его, кроме TerminateProcess , что не является чистым решением.

Я также видел this answer, но, насколько я понимаю, у него нет альтернативы для собственного WinAPI.

+0

Вы выдаете команду из потока, который имеет другую входную очередь, чем та, которая владеет окном? –

+0

@AdrianMcCarthy да, и другой процесс. Цель - еще одна программа, в которой я не контролирую. – Paul

+1

UI Automation (упомянутый в другом ответе, который вы связали) существует для собственных программ WinAPI. Это немного сложнее в использовании, потому что вы не получаете всю помощь во время работы с COM-объектами. Но если вы пытаетесь запустить другое приложение (особенно, которое вы не пишете), UI Automation - это, как правило, лучший способ. –

ответ

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 фактически не может использоваться для этой цели, потому что (насколько я знаю, в любом случае) нет фактического сообщения, которое вы могли бы отправить с ним, что приведет к отображению целевого окна. ShowWindowAsync и SWP_ASYNCWINDOWPOS оба работают, планируя события внутреннего окна, и этот API не публично открыт.

Смежные вопросы