finnw
finnw

Reputation: 48629

Reliable way to wait for another Windows process to redraw its main window

I am moving a window (belonging to another process) to the front in order to take a screenshot of it. I am able to do this using SetForegroundWindow, however that function returns immediately. The other process takes a varying amount of time to redraw its main window (which requires it to access a database) so I cannot be sure that when I take the screenshot the window is fully rendered. Sometimes all I get in the screenshot is the outline of the target window, on top of whatever window was previously in the foreground.

Is there a reliable way to wait until another process's window is fully painted? I suspect there isn't but it's worth a shot. Maybe there's a message I can send to the window that will have this effect?

Note: The implementation language is not important but I need a solution using the native Windows API, either directly from C/C++ code or via P/Invoke (e.g. from C# or VB.NET). Unfortunately I cannot use any WinForms functions.

Upvotes: 0

Views: 661

Answers (2)

finnw
finnw

Reputation: 48629

I am getting good results using the following strategy:

  1. Call PrintWindow to render the target window into a bitmap and discard the result.
  2. Call SetForegroundWindow to bring the target window to the front (this also triggers a repaint, but the repaint is usually fast because the synchronous WM_PRINTCLIENT has already forced the process to page in the data required for rendering.)
  3. Sleep for a short time (10ms)
  4. Take a screenshot using BitBlt
  5. Restore the original Z-order of the target window

Upvotes: 3

Chris Becke
Chris Becke

Reputation: 36026

UpdateWindow will repaint the window if any part of it needs repainting, and then return.

Upvotes: 2

Related Questions