Click here to Skip to main content
Click here to Skip to main content

Capturing Minimized Window: A Kid’s Trick

By , 5 Oct 2007
 
Screenshot - minimizedCapture.jpg

Background

I needed to capture from the minimized window for one of my projects. After several tries of using ordinary methods and failing; I searched the Web a lot (OK, not a lot) but couldn't find a solution, so I decided to work on a new one.

First Words

First of all, thank God for saving my head from blowing out, because I needed to do that really.

Maybe this method is not such a reliable one, but it solved my problem and may be useful for some others, so I thought putting it on The Code Project is better than not doing so.

By the way, this is my first CodeProject article, so forgive me if you see any flaws in it, and please help me with your suggestions for my further actions.

The Problem

OK, the core of this method is the PrintWindow API which draws the face of the window on the specific Device Context.

This method can be used to capture a window regardless of its order and transparency level (it can capture from a partially or fully hidden window), but the main problem is, it cannot capture the minimized window, actually when the window is minimized, it won't be drawn anymore, so if we use PrintWindow it only gives the title of the window back to us.

I tried several methods for capturing a minimized window but I failed, except this one.

How to Capture

I assumed there is no way to capture from the minimized window, so this assumption changed the approach.

I tried to make the window back to normal and capture it then, and then minimize it again; for having a hidden capture, before we pop-up the window from minimized, it must be transparent and it can be done using the SetLayeredWindowAttributes API, but there was another problem. Again the animation of popping up window was shown, even if the window was fully transparent.

By using SPY++, I monitored the messages for explorer and then unchecked "Animate Windows when minimizing and maximizing" and found this message SPI_SETANIMATION then, with a few searches, I found that it can be changed through the SystemParametersInfo API.

This effect can be disabled through the registry, but it's not real-time.

HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics\MinAnimate

If the value is 0, the effect is disabled, and for 1 it is enabled.

So here are the steps I followed to capture a minimized window:

  1. Disable MinAnimate effect
  2. Transparent the window (PrintWindow can take a snap from such a window)
  3. Restore the Window
  4. Capture
  5. Minimize it again
  6. Remove transparency
  7. Enable MinAnimate effect

Now let's check the codes.

1 & 7 - Disable/Enable MinAnimate Effect

I forgot to mention, I say MinAnimate because it's the name in the Registry.

As I mentioned before, it can be done by using SystemParametersInfo, here it is:

(This snippet is in XPAppearance.cs)

[DllImport("user32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SystemParametersInfo(SPI uiAction, uint uiParam,
 ref ANIMATIONINFO pvParam, SPIF fWinIni);

SPI is an enumeration of SPI messages, we want to disable/enable the MinAnimate so we must set uiAction to SPI_SETANIMATION.

We can get/set the effect status in ANIMATIONINFO structure.

As a note, cbsize member of ANIMATIONINFO must be set to the size of the structure, and pvParam must also be equal to cbSize.

Here is the structure:

(This snippet is in XPAppearance.cs)

[StructLayout(LayoutKind.Sequential)]
private struct ANIMATIONINFO
{

   public ANIMATIONINFO(bool iMinAnimate)
   {
      this.cbSize = GetSize();
      if (iMinAnimate) this.iMinAnimate = 1;
      else this.iMinAnimate = 0;
   }

   public uint cbSize;
   private int iMinAnimate;

   public bool IMinAnimate
   {
      get
      {
         if (this.iMinAnimate == 0) return false;
         else return true;
      }
      set
      {
         if (value == true) this.iMinAnimate = 1;
         else this.iMinAnimate = 0;
      }
   }

   public static uint GetSize()
   {
      return (uint)Marshal.SizeOf(typeof(ANIMATIONINFO));
   }
}

And here is the method I used for disable/enable MinAnimate:

(This snippet is in XPAppearance.cs)

public static void SetMinimizeMaximizeAnimation(bool status)
{
   ANIMATIONINFO animationInfo=new ANIMATIONINFO(status);
   SystemParametersInfo(SPI.SPI_GETANIMATION, ANIMATIONINFO.GetSize(),
    ref animationInfo, SPIF.None);

   if (animationInfo.IMinAnimate != status)
   {
      animationInfo.IMinAnimate = status;
      SystemParametersInfo(SPI.SPI_SETANIMATION, ANIMATIONINFO.GetSize(),
       ref animationInfo, SPIF.SPIF_SENDCHANGE);
   }
}

I think there is nothing to explain with the code above.

2 & 6 - Add/Remove Transparency

For making the window invisible but with capturing ability, we can make it transparent.

It can be done somewhat like this:

(This snippet is in WindowSnap.cs)

[DllImport("user32")]
private static extern int GetWindowLong(IntPtr hWnd, int index);

[DllImport("user32")]
private static extern int SetWindowLong(IntPtr hWnd, int index, int dwNewLong);

[DllImport("user32")]
private static extern int SetLayeredWindowAttributes(IntPtr hWnd, byte crey,
 byte alpha, int flags);

(This snippet is in EnterSpecialCapturing method in WindowSnap.cs)

winLong = GetWindowLong(hWnd, GWL_EXSTYLE);
SetWindowLong(hWnd, GWL_EXSTYLE, winLong | WS_EX_LAYERED);
SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);

For removing applied transparency, we can do it by setting the old winLong again.

(This snippet is in the ExitSpecialCapturing method in WindowSnap.cs)

SetWindowLong(hWnd, GWL_EXSTYLE, winLong);

3 & 5 - Restore/Minimize The Window

This part is fairly easy, it can be done using the ShowWindow API.

(This snippet is in WindowSnap.cs)

[DllImport("user32")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowEnum flags);

private enum ShowWindowEnum{Hide = 0,
ShowNormal = 1,ShowMinimized = 2,ShowMaximized = 3,
Maximize = 3,ShowNormalNoActivate = 4,Show = 5,
Minimize = 6,ShowMinNoActivate = 7,ShowNoActivate = 8,
Restore = 9,ShowDefault = 10,ForceMinimized = 11};

(This snippet is in EnterSpecialCapturing method in WindowSnap.cs)

ShowWindow(hWnd, ShowWindowEnum.Restore);

And for minimizing it again, we can use:

(This snippet is in the ExitSpecialCapturing method in WindowSnap.cs)

ShowWindow(hWnd, ShowWindowEnum.Minimize);

4 - Capture

Nothing to say, there are dozens of articles about it; here is the code:

(This snippet is in the GetWindowImage method in WindowSnap.cs)

Bitmap bmp = new Bitmap(size.Width, size.Height);
Graphics g = Graphics.FromImage(bmp);
IntPtr dc = g.GetHdc();

PrintWindow(hWnd, dc, 0);

g.ReleaseHdc();
g.Dispose();

Capturing Child Windows

Capturing from MDI children is very similar to capturing ordinary windows, but with one exception, if the child window is partially hidden by the parent (and not another child), that part would be drawn as blank. For solving this problem, we can use GetParent and SetParent APIs to make it as an ordinary window and back.

[DllImport("user32")]
private static extern IntPtr GetParent(IntPtr hWnd);
[DllImport("user32")]
private static extern IntPtr SetParent(IntPtr child, IntPtr newParent);  

We can pass IntPtr.Zero to newParent in the GetParent method for making it normal (not child).

Last Words

That's all, and for the last words, you can take a snap from Windows using WindowSnap class. It has two methods, GetAllWindows and GetWindowSnap. The first one returns a collection of window snaps from all available windows, and the second one returns a snap of the specific window.

Finally, I thank you for spending your time and reading this article. I hope it would be useful. Please help me with your suggestions and ideas for making this article better.

Updates

  • 6th October, 2007
    • Capturing Child Windows: Support for child windows added. Special thanks to mmjc23 who mentioned that. For more details, see Capturing Child Windows section.
    • MinAnimate Bug Fix: In the previous version, if MinAnimate effect was disabled, WindowSnap would enable it after SpecialCapturing (capturing from minimized window). Special thanks to Kalabuli who notified me about this bug.
  • 10th October, 2007
    • Child Dialog Capturing Fix: Capturing from Modal child dialogs fixed. Special thanks to Hitesh who notified me about this bug.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Hessam Jalali
Iran (Islamic Republic Of) Iran (Islamic Republic Of)
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionAbsolutely greatmembersubuv26 Apr '12 - 17:55 
Exactly what I was looking for. I use Windows Pager (multiple desktop views) and this program works across them. Thanks
GeneralThanks for great articlemembertara_m663 Oct '10 - 2:14 
من دوهفته الاف اين كد بودم!!!تا يه جاهايشو مي دونستم ولي توابع ترنسپرنت رو نميدونستم.خيلي كمكيدي.مرسيييييييييييRose | [Rose]
و این منم زنی تنها در آستانه فصلی سرد...

GeneralSuperbmemberel_tel2 Sep '10 - 12:21 
Just what I was looking for, nice of you to share this code.
 
Worked straight out of the box (well after an auto conversion process)
on windows 7 , visual studio 2010.
Questionexcelent by, why this??memberTotDog23 Apr '09 - 10:23 
I have windows xp and i have a wpf proyect open in visual stdio 2008, then i run the program to get the image, but the image is incomplet.
why...?? some body know how repair this...
 
TotDog

Questioncapturing slow and using ALOT of ram, what did I break now?memberwillpv227 Mar '09 - 2:54 
I am using this code in a program I am creating to capture a window (duh) the issue that I have is that it seems to take a VERY long time. so much processing seems to take place that it freezes up the program. has anyone else run into this issue?
 
In addition when i store the image I am replacing it with the new image on each capture (about every 5 seconds) and my program keeps growing in memory usage at the rate of about 10k every 5 seconds until it gets to about 150 - 250k mem before it starts over again. is the bitmap not being stored and released correctly?
 
I plan on looking into these two issues when I reach beta phase (about a week away) but would like to get a head start on it.
AnswerRe: capturing slow and using ALOT of ram, what did I break now?memberwillpv228 Mar '09 - 16:34 
well it seems the slow up is at the following two lines:
 
ShowWindow(hWnd, ShowWindowEnum.Restore); (in EnterSpecialCapturing)
ShowWindow(hWnd, ShowWindowEnum.Minimize); (in ExitSpecialCapturing)
 
it's about 1.5 - 2 seconds for each line (aka a 3-4 second pause on each loop). any ideas on how to speed this up some? (
 
i could have sworn I tested your program once with break points at the enter and exit methods and i was getting the screen shots just fine on each press of the get snap button (with the handle in the text box and the program minimized) and i was getting a .5 second or less turn around on the image (perfect image) and it never used the EnterSpecialCapturing or ExitSpecialCapturing methods.
GeneralRe: capturing slow and using ALOT of ram, what did I break now?memberHessam Jalali31 Mar '09 - 3:26 
Hi,
 
First about the memory usage,i think it happens because you didn't dispose previous frame you captured, so the time for releasing memory is up to GC.
 
and about being slow,I modified the sample of the article to capture snaps in intervals and log the duration of capturing process, mine never exceeded 150 ms (I was capturing from IE8 playing a flash animation (minimized) every 33 ms).
 
The two lines you pointed out are plain API, so I don't think they are causing this. However if the program you are capturing from do something after being restored,it may cause some delay.
 
so if you provide me more details about how you used the code or any special program you're capturing, I may can help Smile | :)
 
here is the modified sample I used: MinimizeCapture1.1.zip
QuestionRe: capturing slow and using ALOT of ram, what did I break now?memberborchanii23 Dec '10 - 23:19 
any one have the new version or a fix for this memory bug ??
QuestionPrintWindow Problem?memberleonxsk1 Mar '09 - 20:09 
Great Article!
 
But there seems some problems about the PrintWindow. If I capture the window in a loop with some interval like 100ms, the captured window can't be shown normally. It can't refresh itself after calling the PrintWindow function.
 
So could you please check this and is there any solution to solve this problem.
 
Thanks a lot!
AnswerRe: PrintWindow Problem?memberHessam Jalali5 Mar '09 - 6:02 
First of all, thanks, and sorry for the late reply
 
I tested some scenarios (on vista basic) after reading your message, I think the problem occurs if WindowState is Suddenly changed during capture Process, and because of the short interval, the probability of occurrence of the problem is high.
 
Unfortunately I couldn't find anything that can call a solution Frown | :( ,I think the best way is to avoid changing windowState during Capture Process by monitoring messages for the window and delay Related WindowState messages (such as "WM_SIZE") after single capture (this can be done using Hooks and maybe a little code injection), but simply using InvalidateRect API will redraw the window.
 
would you please update me if you find any solution for it.
 
Best Regards
Hessam
GeneralWMPmemberX3m18 Oct '08 - 4:42 
Great article!! You have my 5.
However it cannot seem to capture a Windows Media Player running a video.
Can you please check it and tell me if you can find a solution?
 
Best regards,
X3m

Generalsurprisemembercigogo1 Jul '08 - 17:39 
surprise,thank you. Smile | :)
GeneralSuperbmemberBooma19 Mar '08 - 1:30 
Hai,
Excellent work! Laugh | :laugh:
 
But I want to know the, where do u storing the value of the MinAnimate.
GeneralRe: SuperbmemberHessam Jalali20 Mar '08 - 11:30 
thanks Booma and sorry for the late
 
MinAnimate state will be stored in MinAnimateChanged field (line 193)
 
actually if current state is false (can be checked from XPAppearance.MinAnimate property) so there is no need to change the state and "MinAnimateChanged" would be false otherwise it will be true
 
these operations will be done in EnterSpecialCapturing and ExitSpecialCapturing methods
GeneralRe: SuperbmemberBooma21 Mar '08 - 21:34 
Hai Hessam,
 
thank u so much for this information.
this capturing is used for my part of the application.
And this will so important for me.
 
Thanks very much. Laugh | :laugh:
GeneralRe: SuperbmemberBooma16 Apr '08 - 3:45 
Hai,
 
I have an doubt
while capture the specified window using handle.while i maximized that window and do some actions like(save, find using with menus).But i can't capture menus and submenus.Why?
But,I think while making the window transperncy,it will not catch this event. wat todo?
 
Thanks.
GeneralGreat Article, would love to see some improvement if possiblememberSteven Roebert22 Feb '08 - 13:07 
Loved the article, really does the trick for minimized windows. However, one thing that does still happen, is that you can see windows switching when you look at the taskbar and the window borders. Is there any way to restore the windows, but not give it focus?
GeneralRe: Great Article, would love to see some improvement if possible [modified]memberHessam Jalali24 Feb '08 - 10:42 
Hi Steven
 

Steven Roebert wrote:
Loved the article, really does the trick for minimized windows

 
First of All, thanks I appreciate it.
 

Steven Roebert wrote:
Is there any way to restore the windows, but not give it focus?

 
yes I think it is possible to fix it !!!
After I saw your reply, I reviewed the code and did some modification, Here they are (sorry I didn't have time to update the article ,so I put the changes in the message and update the article as soon as possible Sigh | :sigh: )
 
1- "EnterSpecialCapturing" method must be replaced with the snippet below in "WindowSnap.cs"
 
        private static void EnterSpecialCapturing(IntPtr hWnd)
        {
            if (XPAppearance.MinAnimate)
            {
                XPAppearance.MinAnimate = false;
                minAnimateChanged = true;
            }
 

            winLong = GetWindowLong(hWnd, GWL_EXSTYLE);
            SetWindowLong(hWnd, GWL_EXSTYLE, winLong | WS_EX_LAYERED);
            SetLayeredWindowAttributes(hWnd, 0, 1, LWA_ALPHA);
 
            //ShowWindow(hWnd, ShowWindowEnum.Restore);
            ShowWindow(hWnd, ShowWindowEnum.ShowNormalNoActivate);
 
            SendMessage(hWnd, WM_PAINT, 0, 0);
        }
 
2- and at last "ExitSpecialCapturing" method must be replaced with the snippet below in"WindowSnap.cs"
 
        private static void ExitSpecialCapturing(IntPtr hWnd)
        {
            //ShowWindow(hWnd, ShowWindowEnum.Minimize);
            ShowWindow(hWnd, ShowWindowEnum.ShowMinNoActivate);
 
            SetWindowLong(hWnd, GWL_EXSTYLE, winLong);
 
            if (minAnimateChanged)
            {
                XPAppearance.MinAnimate = true;
                minAnimateChanged = false;
            }
 
        }
 
As you can see in the codes I changed the line ShowWindow(hWnd, ShowWindowEnum.Restore); with ShowWindow(hWnd, ShowWindowEnum.ShowNormalNoActivate); in EnterSpecialCapturing method, and ShowWindow(hWnd, ShowWindowEnum.Minimize); with ShowWindow(hWnd, ShowWindowEnum.ShowMinNoActivate);
 
which ShowNormalNoActivate Equivalent is SW_SHOWNOACTIVATE described in MSDN as
"Displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except the window is not actived."
 
and ShowMinNoActivate Equivalent is SW_SHOWMINNOACTIVE described in MSDN as
"Displays the window as a minimized window. This value is similar to SW_SHOWMINIMIZED, except the window is not activated."
 
I cannot find out why I didn't this before because they were there!!! OMG | :OMG: however, I tested it on Windows Vista Ultimate with and Without Aero and the new code is works fine I think!!!.
 
I hope it's going to be useful and, I would be glad to have your suggestions
 
modified on Sunday, February 24, 2008 6:26 PM

GeneralRe: Great Article, would love to see some improvement if possiblememberSteven Roebert24 Feb '08 - 11:50 
great! it seems to work perfectly, thanks
GeneralVista Minimize Windowmembereissuah17 Dec '07 - 22:57 
Hello,
 
Great job!
 
I might implement this in our software but i'd like to see it work more like the Vista Minimize windows where the screencaptures are "live". I'll see how it works out doing 10 captures a second x).
QuestionLovely program; Found a problemmemberinexplicable9 Oct '07 - 22:07 
This is really a lovely program and I think your library can be very useful in creating specific applications.
 
Issue
 
I found one issue while running your app. If any application has a modal dialog open, the app takes a screenshot of both, the main window and the modal dialog. This is all right.
 
However, thereafter it closes the modal dialog and the application stops responding.
 
You can try this by launching task manager and opening the 'choose column' option from the view menu. Leave the dialog open and then run the app to collect screenshots to see the problem I am describing.
 
This is consistently reproducible on my system (Windows 2003 R2).

 
Hitesh
AnswerRe: Lovely program; Found a problemmemberHessam Jalali10 Oct '07 - 10:38 
thanks for the notice,
 
I fixed it, the problem was about MDI child Capturing part which had some side effects on not MDI child Modal Dialogs, I hope it's going to word well now
 
thanks for your Help
 
Smile | :)
GeneralRe: Lovely program; Found a problemmemberinexplicable12 Oct '07 - 0:42 
Thanks Hessam, that was quick.
 
Promise to study the new implementation over the weekend. I shall let you know my experience.
 
BR,
Hitesh
GeneralGreat workmemberRajesh Naik Ponda Goa9 Oct '07 - 20:22 
I have been looking for similar code for long time...
 
Thanks and keep up the good work. Smile | :)
 

GeneralRe: Great workmemberHessam Jalali10 Oct '07 - 10:34 
Thanks very much,I appreciate it Smile | :)



General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 5 Oct 2007
Article Copyright 2007 by Hessam Jalali
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid