I try to take a screenshot of an application writen in WPF and the application is not captured, must I use a special tool to take the screenshot?
You can use RenderTargetBitmap to generate an image from your WPF control.
public const int IMAGE_DPI = 96;
public Image GenerateImage(T control)
where T : Control, new()
{
Size size = RetrieveDesiredSize(control);
Rect rect = new Rect(0, 0, size.Width, size.Height);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)size.Width, (int)size.Height, IMAGE_DPI, IMAGE_DPI, PixelFormats.Pbgra32);
control.Arrange(rect); //Let the control arrange itself inside your Rectangle
rtb.Render(control); //Render the control on the RenderTargetBitmap
//Now encode and convert to a gdi+ Image object
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
using (MemoryStream stream = new MemoryStream())
{
png.Save(stream);
return Image.FromStream(stream);
}
}
private Size RetrieveDesiredSize(T control)
{
if (Equals(control.Width, double.NaN) || Equals(control.Height, double.NaN))
{
//Make sure the control has measured first:
control.Measure(new Size(double.MaxValue, double.MaxValue));
return control.DesiredSize;
}
return new Size(control.Width, control.Height);
}
Note that this will generate a PNG image ;) If you wish to store it as a JPEG, I suggest you use another encoder :)
Image image = GenerateImage(gridControl);
image.Save("mygrid.png");
You can simply press PrtScr button (windows will copy whole descktop image to buffer), then paste it in Power Point and crop if you like.
I'm having the same issue, I need to take screenshots to document my tests but can't seem to get there.
The Window in question is a Borderless modal Window with rounded corners / transparency allowed. Here's my report:
HP Quality Center's Screenshot tool doesn't recognize it as a window and thus takes its screenshots as if the window weren't there.
SnagIt utilizes a keycombo to enter the capture mode. Once stroke is hit, the popup vanishes. It reappears after the capture has ended.
Standard Windows capture works OK (Alt + Prt Scr) and captures the window as it was intended to be captured.
Next thing I tried was capturing the window with an opened dropdownlist. None of the approaches mentioned above seems to work (the last approach captures the Window the same way it did before, without the open dropdown).
As far as I have understood all the talk correctly, the only thing you can do is implement this into the applications...
Related
I have a WPF-Application which hosts a WinformsPanel
<WindowsFormsHost>
<windowsForms:Panel
x:Name="PlayerHost">
</windowsForms:Panel>
<WindowsFormsHost>
I then use this Panel to display a video. I'm using Mpv.NET lib to do this.
The video player is initialized properly:
//panel.Handle is the windowsForms:Panel named PlayerHost
player = new MpvPlayer(panel.Handle, Common.IO.FindLib.FindMpvLib(binaryPath));
player.Load(videoFilePath);
Now, if I try to draw the panels content, the resulting image remains blank. The code to draw the image is as follows:
using (var bmp = new Bitmap(panel.ClientSize.Width, panel.ClientSize.Height))
{
panel.DrawToBitmap(bmp, panel.ClientRectangle);
bmp.Save(#"Some:\path.bmp", System.Drawing.Imaging.ImageFormat.Bmp);
}
To make it clear: The video gets displayed. I can see the video content. And I start drawing to an image when the media is properly loaded. I even offloaded the drawing command to a button click. So while the video was running I tried to take a "frame capture" so to say. But the image remains blank.
How can I capture the panels content? Has it something to do with the native Handle being provided to the video player? Thanks in advance.
You can save the panels content to a bitmap with the following code:
using (Bitmap b = new Bitmap(panel.Width, panel.Height))
{
panel.DrawToBitmap(b, new Rectangle(0, 0, b.Width, b.Height));
b.Save("test.png");
}
I am trying to render a figure to a PNG using WPF (rather than the old GDI API) and the result is always blank.
I am writing a small program that will produce images routes around a warehouse to various items. I am using WPF API for drawing rather than the old GDI API as the images need to be both saved to disk and displayed within a WPF application. The problem is that all of the png files that it produces are currently entirely black.
To reduce the scope of the problem and prove that it was not a problem with code for drawing the map I made a minimal test method that should simply render a red circle on a black background. However the result is still an entirely black.
[TestMethod]
public void DrawingTest()
{
//define the dimensions of the test image
int width = 100;
int height = 100;
int dpi = 100;
//define where the image should be saved
var path = #"C:\temp\DrawingTest.png";
//create a bitmap to render the image into
RenderTargetBitmap bitmap = new RenderTargetBitmap(
width, height, dpi, dpi, PixelFormats.Default);
//create a drawing context to draw the image onto
DrawingVisual drawingVisual = new DrawingVisual();
using (DrawingContext canvas = drawingVisual.RenderOpen())
{
//draw a circle
canvas.DrawEllipse(Brushes.Red, new Pen(Brushes.Red, 1), new System.Windows.Point(50, 50), 50, 50);
//render the image into a bitmap
bitmap.Render(drawingVisual);
}
//create the file encoder
var encoder = new PngBitmapEncoder();
//encode the bitmap in PNG format
encoder.Frames.Clear();
encoder.Frames.Add(BitmapFrame.Create(bitmap));
//make sure that the file can be saved in this location
var directory = System.IO.Path.GetDirectoryName(path);
if (!System.IO.Directory.Exists(directory))
System.IO.Directory.CreateDirectory(directory);
if (System.IO.File.Exists(path))
System.IO.File.Delete(path);
//save the map to file
using (var stream = System.IO.File.Create(path))
encoder.Save(stream);
}
The test method runs without any errors and produces a png file at the location that I expected. However, this file is simply a black square rather than the red circle in a black square that I was expecting. Can anybody tell me why it is just rendering a black image, and what I can do to make it show the red circle.
You have to call bitmap.Render(drawingVisual) after the DrawingContext is closed.
From the Remarks on DrawingContext.Close:
A DrawingContext must be closed before its content can be rendered ...
So just move the Render call outside the using block:
using (DrawingContext dc = drawingVisual.RenderOpen())
{
dc.DrawEllipse(Brushes.Red, new Pen(Brushes.Red, 1),
new System.Windows.Point(50, 50), 50, 50);
}
bitmap.Render(drawingVisual);
Besides that, the red Pen seems redundant, since the circle is already filled red. So this should be ok:
dc.DrawEllipse(Brushes.Red, null, new System.Windows.Point(50, 50), 50, 50);
Also make sure to create the bitmap with a DPI value of 96, which corresponds to WPF device-independent units. Otherwise you would have to scale the drawing appropriately.
One and a half year later I faced the same problem - how to properly render a canvas without displaying it in the screen.
The solution was simpler than I thought and produces exactly the result one expects.
Long story short - to render the canvas without displaying it call Arrange(Rect finalRect) method on your canvas:
canvas.Arrange(new Rect(new Size(width, height)));
According to the documentation it:
Positions child elements and determines a size for a UIElement. Parent elements call this method from their ArrangeCore(Rect) implementation (or a WPF framework-level equivalent) to form a recursive layout update. This method constitutes the second pass of a layout update.
In a Windows Forms application, how do I take a "screenshot" of certain coordinates?
In the picture below, you see a Window and inside that window is a little gray box, somewhere near the center.
Where every I might place that box, how can I take a "screenshot" of it (including whatever content is inside it) programmatically?
Simple way
Simple, use Graphics.CopyFromScreen
private Bitmap bitmap;
private Graphics graph;
graph.CopyFromScreen(X, Y, 0, 0, Size, CopyPixelOperation.SourceCopy);
Now you can use bitmap, that contains a source copy of the area.
Hacky way
SendKeys.Send("%{PRTSC}"); //Alt + PrtSc to screenshot just the active window.
Bitmap clipboardImage = Clipboard.GetImage(); //Get image from the clipboard
//Here you crop the image using Bitmap.Clone();
//Be happy and question yourself why you are doing this way.
I want to implement zoom for an image. I don't want to resize the PictureBox, but the image itself.
How do I do this?
One solution is:
Create new image of the desired size (for example 200% or 50% of original image size)
Draw original image to new image using Graphics.DrawImage(Image, Rectangle);, which draws the given image to the new image at the given position with the given size
Set new image as source for the PictureBox
Another way is to simple create a new bitmap instance like that:
Size newSize = new Size((int)(originalBitmap.Width * zoomFactor), (int)(originalBitmap.Height * zoomFactor));
Bitmap bmp = new Bitmap(originalBitmap, newSize);
I used a web browser to achieve this.
//loads the image
myWebBrowser.Navigate(#"C:\myimage.png");
From there I used SendKeys to zoom in and out
myWebBrowser.Select(); //Selects browser.
SendKeys.Send("^{+}"); //Sends the control + key combo, causing the browser to zoom in. Replace the "+" with a "-" to zoom out.
It's a bit of a weird method, but it worked really well for me. I hope you find this helpful!
I am using some custom controls one of which is a tooltip controller that can display images, so I am using th ebelow code to instantiate it:
Image newImage = Image.FromFile(imagePath);
e.ToolTipImage = newImage;
obviously could inline it but just testing at the moment. The trouble is the image is sometimes the wrong size, is there a way to set the display size. The only way I can currently see is editing the image using GDI+ or something like that. Seems like a lot of extra processing when I am only wanting to adjust display size not affect the actual image.
Once you have an image object loaded from its source, the Height and Width (and Size, and all ancillary properties) are read-only. Therefore, you are stuck with GDI+ methods for resizing it in RAM and then displaying it accordingly.
There are a lot of approaches you can take, but if you were to encapsulate that out to a library which you could reuse should this problem occur again, you'll be set to go. This isn't exactly optimized (IE, may have some bugs), but should give you an idea of how to approach it:
Image newImage = Image.FromFile(myFilePath);
Size outputSize = new Size(200, 200);
Bitmap backgroundBitmap = new Bitmap(outputSize.Width, outputSize.Height);
using (Bitmap tempBitmap = new Bitmap(newImage))
{
using (Graphics g = Graphics.FromImage(backgroundBitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
// Get the set of points that determine our rectangle for resizing.
Point[] corners = {
new Point(0, 0),
new Point(backgroundBitmap.Width, 0),
new Point(0, backgroundBitmap.Height)
};
g.DrawImage(tempBitmap, corners);
}
}
this.BackgroundImage = backgroundBitmap;
I did test this, and it worked. (It created a 200x200 resized version of one of my desktop wallpapers, then set that as the background image of the main form in a scratch WinForms project. You'll need using statements for System.Drawing and System.Drawing.Drawing2D.
In Winforms, if you contain the image inside a PictureBox control, the PictureBox control can be set to zoom to a particular height/width, and the image should conform.
At least that's what happened in my Head First C# book when I did the exercise.