J J
2013-04-14 17:00:37
Hello,
I'm planning to learn more C# and make a neat program that can perform some nifty tasks. To start off I've been working on something to grab an image of a minimized window. I searched around and found that PrintWindow would be a pretty viable way. So after looking through source code I managed to get it working and it can take screenshots like this from processes.
Taking a screenshot of firefox while it's behind other windows:

Taking a screenshot of RuneScape @ firefox however..
So after some research PrintWindow does not work properly for everything. Apparantly Java is under that.
–
So I went back to something I originally found interesting, the Desktop Window Manager functions (http://msdn.microsoft.com/en-us/library/windows/desktop/aa969527%28v=vs.85%29.aspx) After going through the source of a really nice program (http://community.bartdesmet.net/blogs/bart/archive/2006/10/05/4495.aspx) and trial and error I managed to get it working.

So I thought it was rendering to the ImageBox but it's actually just rendering to the program.
After this wall of text here is the actual question.
I'm looking to get the thumbnail as a Bitmap, what would be the best way to do this? With the DWM functions you can only render it, is there anyway I can access this?
Or is there a way to modify PrintWindows to make it work?
TL;DR:
How to grab the rendered image using Desktop Window Manager functions?
PS:
Something cool I found is that it actually keeps updating the Automation Tool image while I'm typing this. I've added the .exe for anyone that wants to try it. You need to have firefox open then press the button. I will add the source later for those that are interest and/or don't trust random .exe files :P Oh, and you need Windows Vista or higher because that's when DWM got implemented.
Possible people that know anything
@Brandon; @masterBB; @Wizzup?;
Source:
Structs.cs where I define some structs to be used.
This is my test code after clicking on the button of the form
I'm planning to learn more C# and make a neat program that can perform some nifty tasks. To start off I've been working on something to grab an image of a minimized window. I searched around and found that PrintWindow would be a pretty viable way. So after looking through source code I managed to get it working and it can take screenshots like this from processes.
Taking a screenshot of firefox while it's behind other windows:

Taking a screenshot of RuneScape @ firefox however..
So after some research PrintWindow does not work properly for everything. Apparantly Java is under that.–
So I went back to something I originally found interesting, the Desktop Window Manager functions (http://msdn.microsoft.com/en-us/library/windows/desktop/aa969527%28v=vs.85%29.aspx) After going through the source of a really nice program (http://community.bartdesmet.net/blogs/bart/archive/2006/10/05/4495.aspx) and trial and error I managed to get it working.
So I thought it was rendering to the ImageBox but it's actually just rendering to the program.
After this wall of text here is the actual question.
I'm looking to get the thumbnail as a Bitmap, what would be the best way to do this? With the DWM functions you can only render it, is there anyway I can access this?
Or is there a way to modify PrintWindows to make it work?
TL;DR:
How to grab the rendered image using Desktop Window Manager functions?
PS:
Something cool I found is that it actually keeps updating the Automation Tool image while I'm typing this. I've added the .exe for anyone that wants to try it. You need to have firefox open then press the button. I will add the source later for those that are interest and/or don't trust random .exe files :P Oh, and you need Windows Vista or higher because that's when DWM got implemented.
Possible people that know anything
@Brandon; @masterBB; @Wizzup?;
Source:
Structs.cs where I define some structs to be used.
using System.Drawing;
using System.Runtime.InteropServices;
namespace AutomationTool
{
#region Interop structs
[StructLayout(LayoutKind.Sequential)]
internal struct DWM_THUMBNAIL_PROPERTIES
{
public int dwFlags;
public Rect rcDestination;
public Rect rcSource;
public byte opacity;
public bool fVisible;
public bool fSourceClientAreaOnly;
}
[StructLayout(LayoutKind.Sequential)]
internal struct Rect
{
internal Rect(int left, int top, int right, int bottom)
{
Left = left;
Top = top;
Right = right;
Bottom = bottom;
}
public int Left;
public int Top;
public int Right;
public int Bottom;
}
[StructLayout(LayoutKind.Sequential)]
internal struct PSIZE
{
public int x;
public int y;
}
#endregion
}
This is my test code after clicking on the button of the form
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Drawing.Imaging;
namespace AutomationTool
{
public partial class Form1 : Form
{
#region DWM functions
[DllImport("dwmapi.dll")]
static extern int DwmRegisterThumbnail(IntPtr dest, IntPtr src, out IntPtr thumb);
[DllImport("dwmapi.dll")]
static extern int DwmUnregisterThumbnail(IntPtr thumb);
[DllImport("dwmapi.dll")]
static extern int DwmQueryThumbnailSourceSize(IntPtr thumb, out PSIZE size);
[DllImport("dwmapi.dll")]
static extern int DwmUpdateThumbnailProperties(IntPtr hThumb, ref DWM_THUMBNAIL_PROPERTIES props);
#endregion
#region Constants
static readonly int DWM_TNP_VISIBLE = 0x8;
static readonly int DWM_TNP_OPACITY = 0x4;
static readonly int DWM_TNP_RECTDESTINATION = 0x1;
#endregion
private IntPtr thumb;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void FindHandleButton_Click(object sender, EventArgs e)
{
Console.WriteLine("FindHandleButton has been clicked");
Process[] processList = Process.GetProcesses();
foreach (Process process in processList)
{
String processName = process.ProcessName;
int pid = process.Id;
Console.WriteLine("Process name: {0}, PID: {1}", processName, pid);
if (processName.Equals("firefox"))
{
Console.WriteLine("Found process!");
IntPtr hWnd = process.MainWindowHandle;
Console.WriteLine("Hwnd ptr: {0}", hWnd);
/*
Rect rc;
GetWindowRect(hWnd, out rc);
Console.WriteLine("Constructing bmp");
Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
Console.WriteLine("Attempting to print window");
PrintWindow(hWnd, hdcBitmap, 0);
Console.WriteLine("Releasing stuff");
gfxBmp.ReleaseHdc(hdcBitmap);
gfxBmp.Dispose();
Console.WriteLine("Made BMP!");
bmp.Save("J:\\AutomationTool\\screenshot at " + DateTime.Now.ToString("HH-mm-ss tt") + ".png", ImageFormat.Png);
Console.WriteLine("Saved bmp!");
bmp.Dispose();
/*
Rectangle rc;
GetWindowRect(hwnd, out rc);
Console.WriteLine("RC: " + rc);
Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
Graphics gfxBmp = Graphics.FromImage(bmp);
IntPtr hdcBitmap = gfxBmp.GetHdc();
PrintWindow(hwnd, hdcBitmap, 0);
gfxBmp.ReleaseHdc(hdcBitmap);
gfxBmp.Dispose();
bmp.Save("J:\\AutomationTool");
Console.WriteLine("Saved image!");
*/
Console.WriteLine("Attempting to register thumbnail!");
int i = DwmRegisterThumbnail(this.Handle, hWnd, out thumb);
Console.WriteLine("Succesfully registered thumbnail!");
UpdateThumb();
Console.WriteLine("Succesfully updated thumb!");
break;
}
}
}
private void UpdateThumb()
{
if (thumb != IntPtr.Zero)
{
PSIZE size;
DwmQueryThumbnailSourceSize(thumb, out size);
DWM_THUMBNAIL_PROPERTIES props = new DWM_THUMBNAIL_PROPERTIES();
props.fVisible = true;
props.dwFlags = DWM_TNP_VISIBLE | DWM_TNP_RECTDESTINATION | DWM_TNP_OPACITY;
props.opacity = 255;
props.rcDestination = new Rect(pictureBox.Left, pictureBox.Top, pictureBox.Right, pictureBox.Bottom);
/*
if (size.x < pictureBox.Width)
props.rcDestination.Right = props.rcDestination.Left + size.x;
if (size.y < pictureBox.Height)
props.rcDestination.Bottom = props.rcDestination.Top + size.y;
*/
DwmUpdateThumbnailProperties(thumb, ref props);
Console.WriteLine("Succesfully handled thumbnail stuff");
/*
Console.WriteLine("Making BMP!");
Bitmap bmp = new Bitmap(size.x, size.y, PixelFormat.Format32bppArgb);
Console.WriteLine("Made BMP; width = " + bmp.Width + ", height = " + bmp.Height);
//bmp.Save("J:\\AutomationTool\\screenshot at " + DateTime.Now.ToString("HH-mm-ss tt") + ".png", ImageFormat.Png);
bmp.Save(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\screenshot at " + DateTime.Now.ToString("HH-mm-ss tt") + ".png", ImageFormat.Png);
Console.WriteLine("Saved bmp!");
bmp.Dispose();
*/
}
}
}
}
