Here is what I'm trying to do:
- I have a winforms control in a C# project that displays a map.
- I want to capture an image of the loaded map, and I need this image to be a very large continuous portion of the map. To do this I can create the dimensions of the map control to be huge (> 4k x 4k pixels)
- The problem I have is that I cannot capture that control's client area to a bit map without issues.
I have tried the following without much luck:
This will save the image, but it captures any window on top as well as the taskbar and offscreen content is white:
var controlGraphic = mapControl.CreateGraphics(); var img = new Bitmap(mapControl.Width, mapControl.Height, controlGraphic); var imgGraphic = Graphics.FromImage(img); var controlGraphicDc = controlGraphic.GetHdc(); var imgGraphicDc = imgGraphic.GetHdc(); BitBlt(imgGraphicDc, 0, 0, mapControl.ClientRectangle.Width, mapControl.ClientRectangle.Height, controlGraphicDc, 0, 0, SRCCOPY); controlGraphic.ReleaseHdc(controlGraphicDc); imgGraphic.ReleaseHdc(imgGraphicDc); img.Save(fileName, ImageFormat.Png);
I tried code similar to the last post in this link, but it doesn't seem to work any better: Capture the screen shot using .NET
So I don't think it has anything to do with the map control per se, and I think you could use any control (i.e. WebBrowser) and resize it to be huge and get the same effect.
I'm wondering if anybody has done something similar, or maybe there is a way to maybe nest the control in some scrollable control and somehow capture its contents, or maybe a different context and do a capture? I might be able to use WPF if that helps in anyway.
Thanks.
Example with WebBrowser control that shows same result (new winforms with WebBrowser control on it and button):
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WebBrowserCaptureTest
{
public partial class Form1 : Form
{
[DllImport("gdi32.dll")]
private static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
int dwRop // raster operation code
);
private const int SRCCOPY = 0xCC0020;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.SetBounds(0, 0, 4096, 4096);
webBrowser1.Navigate(@"http://www.google.com");
}
private void CaptureControl(System.Windows.Forms.Control control, string fileName)
{
var controlGraphic = control.CreateGraphics();
var img = new Bitmap(control.Width, control.Height, controlGraphic);
var imgGraphic = Graphics.FromImage(img);
var controlGraphicDc = controlGraphic.GetHdc();
var imgGraphicDc = imgGraphic.GetHdc();
BitBlt(imgGraphicDc, 0, 0, control.ClientRectangle.Width, control.ClientRectangle.Height, controlGraphicDc, 0, 0, SRCCOPY);
controlGraphic.ReleaseHdc(controlGraphicDc);
imgGraphic.ReleaseHdc(imgGraphicDc);
img.Save(fileName, ImageFormat.Png);
}
static void DrawControlToBitmap(Control ctrl, string fileName)
{
System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(ctrl.Width, ctrl.Height);
ctrl.DrawToBitmap(bmp, ctrl.ClientRectangle);
bmp.Save(fileName);
}
private void button1_Click(object sender, EventArgs e)
{
CaptureControl(this.webBrowser1, "Capture.png");
DrawControlToBitmap(webBrowser1, "Capture_B.png");
}
}
}
Note 2 things:
- Control.DrawToBitmap results in a Totally White image in the example using a WebBrowser control and
- The map control I am using is an activeX control that doesn't support that method.