5

In my C++ application, I have the following code:

ShowWindow(hDlg, SW_HIDE);
MakeScreenshot();
ShowWindow(hDlg, SW_SHOW);

This should capture screenshot of screen WITHOUT the current application window. However there is a problem. The SW_HIDE takes some time because my windows 8.1 is configured to use Animation effects. So the hiding of window takes about 400 miliseconds and if screenshot is captured during this interval (which it is), it will contain also the window of the app itself, which I do not like.

Is there any way to hide the current window instantly, so it won't be included in the create screenshot function, which is called immediately after it? If not, is there any other preferred way how to take screenshot of windows desktop excluding the application itself? Adding a delay before the MakeScreenshot is not any good solution. Thank you.

Tomas M
  • 6,919
  • 6
  • 27
  • 33
  • https://msdn.microsoft.com/en-us/library/windows/desktop/aa969524%28v=vs.85%29.aspx – Hans Passant Feb 28 '16 at 18:51
  • @HansPassant: are you thinking of the `DWMWA_CLOAK` attribute? – Remy Lebeau Feb 29 '16 at 01:15
  • @Tomas: Try using `SystemParametersInfo()` to disable animations before hiding the window, and reenable animations after showing the window. Or enable the `WS_EX_LAYERED` style on the window and then set its opacity to 0 and then back to 255. Or, just move the window off-screen and then move it back. – Remy Lebeau Feb 29 '16 at 01:25
  • 1
    Use DWMWA_TRANSITIONS_FORCEDISABLED to disable the frame animation. Another very decent way to do it is with WS_EX_LAYERED + SetLayeredWindowAttributes() to make the window instantly transparent and opaque again. – Hans Passant Feb 29 '16 at 07:20
  • 1
    I never knew that `SW_HIDE` would trigger an animation. Shows how much I know! – Jonathan Potter Feb 29 '16 at 12:07
  • Related: https://stackoverflow.com/questions/23044933/detecting-windows-animation-settings – Adrian McCarthy May 24 '17 at 18:37

2 Answers2

1

You could use MoveWindow (or SetWindowsPos) to move the undesired window outside the visible region of the virtual desktop, and then move it back.

You might need to enumerate the monitors to find a coordinate beyond the reach of all the monitors, which would be a little bit of work. Presumably your screenshot code is computing the coordinates to snapshot, so you could re-use that calculation to find a safe place to park the window.

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
0

What worked for me:

    this->ModifyStyleEx(0, WS_EX_LAYERED | WS_EX_TOPMOST); //just a backup


    COLORREF c;
    BYTE b;
    DWORD flags;
    this->GetLayeredWindowAttributes(&c, &b, &flags); //just a backup

    this->SetLayeredWindowAttributes(0, 0, LWA_ALPHA);


    //CODE TO TAKE A SCREENSHOT


    this->SetLayeredWindowAttributes(c, b, flags); //just a restore

    this->ModifyStyleEx(WS_EX_LAYERED | WS_EX_TOPMOST, 0); //just a restore
sergiol
  • 4,122
  • 4
  • 47
  • 81