Click here to Skip to main content
15,867,594 members
Articles / Programming Languages / C#
Article

Capturing Minimized Window: A Kid’s Trick

Rate me:
Please Sign up or sign in to vote.
4.72/5 (44 votes)
5 Oct 2007CPOL5 min read 224.5K   12.5K   86   53
Capture a window even if it is minimized or fully hidden by other windows
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)

C#
[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)

C#
[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)

C#
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)

C#
[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)

C#
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)

C#
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)

C#
[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)

C#
ShowWindow(hWnd, ShowWindowEnum.Restore);

And for minimizing it again, we can use:

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

C#
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)

C#
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.

C#
[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)


Written By
Software Developer
Iran (Islamic Republic of) Iran (Islamic Republic of)
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
AnswerRe: Capture image of embedded flash in browser Pin
Hessam Jalali11-Aug-14 4:21
Hessam Jalali11-Aug-14 4:21 
QuestionIt's exactly what i'm looking for Pin
Roberto Pulvirenti3-Jul-14 4:38
Roberto Pulvirenti3-Jul-14 4:38 
AnswerRe: It's exactly what i'm looking for Pin
Hessam Jalali3-Jul-14 23:41
Hessam Jalali3-Jul-14 23:41 
QuestionPath where sanp image save Pin
Mayank2yk31-May-14 18:14
Mayank2yk31-May-14 18:14 
AnswerRe: Path where sanp image save Pin
Hessam Jalali2-Jun-14 19:40
Hessam Jalali2-Jun-14 19:40 
GeneralRe: Path where sanp image save Pin
Mayank2yk4-Jun-14 10:12
Mayank2yk4-Jun-14 10:12 
QuestionAbsolutely great Pin
subuv26-Apr-12 17:55
subuv26-Apr-12 17:55 
GeneralThanks for great article Pin
mahboobeh mohamadi3-Oct-10 2:14
mahboobeh mohamadi3-Oct-10 2:14 
GeneralSuperb Pin
el_tel2-Sep-10 12:21
el_tel2-Sep-10 12:21 
Questionexcelent by, why this?? Pin
TotDog23-Apr-09 10:23
TotDog23-Apr-09 10:23 
Questioncapturing slow and using ALOT of ram, what did I break now? Pin
willpv227-Mar-09 2:54
willpv227-Mar-09 2:54 
AnswerRe: capturing slow and using ALOT of ram, what did I break now? Pin
willpv228-Mar-09 16:34
willpv228-Mar-09 16:34 
GeneralRe: capturing slow and using ALOT of ram, what did I break now? Pin
Hessam Jalali31-Mar-09 3:26
Hessam Jalali31-Mar-09 3:26 
QuestionRe: capturing slow and using ALOT of ram, what did I break now? Pin
borchanii23-Dec-10 23:19
borchanii23-Dec-10 23:19 
QuestionPrintWindow Problem? Pin
leonxsk1-Mar-09 20:09
leonxsk1-Mar-09 20:09 
AnswerRe: PrintWindow Problem? Pin
Hessam Jalali5-Mar-09 6:02
Hessam Jalali5-Mar-09 6:02 
GeneralWMP Pin
Vuvirt18-Oct-08 4:42
Vuvirt18-Oct-08 4:42 
Generalsurprise Pin
cigogo1-Jul-08 17:39
cigogo1-Jul-08 17:39 
GeneralSuperb Pin
Booma19-Mar-08 1:30
Booma19-Mar-08 1:30 
GeneralRe: Superb Pin
Hessam Jalali20-Mar-08 11:30
Hessam Jalali20-Mar-08 11:30 
GeneralRe: Superb Pin
Booma21-Mar-08 21:34
Booma21-Mar-08 21:34 
GeneralRe: Superb Pin
Booma16-Apr-08 3:45
Booma16-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 possible Pin
Steven Roebert22-Feb-08 13:07
Steven Roebert22-Feb-08 13:07 
GeneralRe: Great Article, would love to see some improvement if possible [modified] Pin
Hessam Jalali24-Feb-08 10:42
Hessam Jalali24-Feb-08 10:42 
GeneralRe: Great Article, would love to see some improvement if possible Pin
Steven Roebert24-Feb-08 11:50
Steven Roebert24-Feb-08 11:50 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.