1

As the title says, I'd like to capture an image from a minimized window. Is that even possible? I use the CaptureAnImage from MSDN and it works, unless the window is minimized.

One solution I tried was maximizing it, capturing the image, then returning it to it's original state. Only problem is the animation looks ugly and I'd like to find an alternative. Here is how I tried it:

WINDOWPLACEMENT wInfo;
UINT originalPlacement;

GetWindowPlacement(hWnd, &wInfo);
originalPlacement = wInfo.showCmd;

wInfo.showCmd = SW_MAXIMIZE;
SetWindowPlacement(hWnd, &wInfo);
wInfo.showCmd = originalPlacement;

CaptureAnImage(hWnd); // Capture the image while it's maximized

SetWindowPlacement(hWnd, &wInfo);

So here I'm looking for one of these solutions:

  1. Would it be possible to capture the image even while it's minimized?

    or

  2. Would it be possible to maximize it, capture it, then return it to it's original state without showing any kind of animation?

PS: I found that link while searching for my problem, but it's in C# and I'm unable to make it work in C++.

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
MyUsername112358
  • 1,320
  • 14
  • 39

1 Answers1

6

You cannot capture a minimized window, you must restore it first. But you can optionally restore it off-screen, or with an alpha opacity of 1, so the user does not see it but the OS will. And be sure to temporarily disable the restore/minimize animations as well, using SystemParametersInfo(SPI_SETANIMATION) (only do so if SPI_GETANIMATION reports animations are enabled), to reduce the time needed to show and then re-hide the window.

For example:

WINDOWPLACEMENT wp = {0};
wp.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(hWnd, &wp);

ANIMATIONINFO ai = {0};
bool restoreAnimated = false;

if (wp.showCmd == SW_SHOWMINIMIZED)
{
    ai.cbSize = sizeof(ANIMATIONINFO);
    SystemParametersInfo(SPI_GETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);

    if (ai.iMinAnimate != 0)
    {
        ai.iMinAnimate = 0;
        SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
        restoreAnimation = true;
    }

    // optionally move the window off-screen, or
    // apply alpha using SetLayeredWindowAttributes()...

    ShowWindow(hWnd, SW_SHOWNOACTIVATE);
}

// capture as needed ...
    
if (wp.showCmd == SW_SHOWMINIMIZED)
{
    SetWindowPlacement(hWnd, &wp);

    // optionally remove alpha using SetLayeredWindowAttributes()...

    if (restoreAnimation)
    {
        ai.iMinAnimate = 1;
        SystemParametersInfo(SPI_SETANIMATION, sizeof(ANIMATIONINFO), &ai, 0);
    }
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • If a window is minimized, when we hover the mouse cursor over it's icon on the taskbar, Windows OS will popup a small window on top of the icon showing the window's screen, is Windows OS doing your code behind the scenes? :) – Shayan May 04 '20 at 10:48
  • 1
    @Shayan no. A minimized window is not actually minimized, it is moved offscreen at the OS level. Windows can still render it, the user just doesn't see it. The Taskbar also allows an app to render its own preview of a window, if it wants to. So the app could be rendering the minimized window to a bitmap for the Taskbar to display. – Remy Lebeau May 04 '20 at 15:45
  • @RemyLebeau - Hi. But if a "minimized" window is not minimized but just offscreen, why can't you capture it? – Gabriel Mar 03 '23 at 07:39
  • @Gabriel The OS doesn't render new frames of minimized windows. The preview that you see is the last cached frame from when the window was active. – Ben May 18 '23 at 09:36
  • @Ben unless the window actively provides the Taskbar with a new preview image. Think of a window that has video playing on it. The preview will still show the video playing even if the window is "minimized" – Remy Lebeau May 18 '23 at 15:06
  • @RemyLebeau Why? same rule applies to windows that plays a video - When an application window is minimized, the window cannot (and does not) receive WM_PAINT messages, meaning that it is impossible to ask the window to redraw itself while it is minimized (or, "take a picture of it"). This is a limitation (or a rule) of the Windows API. – Ben May 21 '23 at 08:23
  • 1
    @Ben an app can render its window content on the Taskbar preview, *even when minimized*, by enabling the `DWMWA_FORCE_ICONIC_REPRESENTATION` and `DWMWA_HAS_ICONIC_BITMAP` window attributes and then handling the `WM_DWMSENDICONIC(THUMBNAIL|LIVEPREVIEWBITMAP)` messages – Remy Lebeau May 21 '23 at 16:48