It was not an easy one. So below a working example using WPF and WinForms.
I found out that when the display is scaled from the OS settings, it comes in play when working with the raw graphics (regarding coordinates/sizes).
In the WPF example I called this SCALE_FACTOR
. Because my windows scale is set to 150%, I scale with factor 1.5
. WPF example works then for me:
WPF example:
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private const double SCALE_FACTOR = 1.5; // 150% in windows 10 settings
private void button_Click(object sender, RoutedEventArgs e)
{
// take window location
var x = (int)(Application.Current.MainWindow.Left);
var y = (int)(Application.Current.MainWindow.Top);
// convert to System.Drawing.Point
var currentLocationPoint = new System.Drawing.Point(x, y);
CaptureImage(
// current TOP, LEFT location of the window on the screen
currentLocationPoint,
// TOP, LEFT location of the destination
new System.Drawing.Point(0, 0),
// size of the current window AND of the destination window/buffer/image
new System.Drawing.Rectangle(
0,
0,
// need to scale the width because of the OS scaling
(int)(this.ActualWidth * SCALE_FACTOR),
// need to scale the heigt because of the OS scaling
(int)(this.ActualHeight * SCALE_FACTOR)),
@"c:\temp\screen.bmp");
}
public static void CaptureImage(System.Drawing.Point SourcePoint, System.Drawing.Point DestinationPoint, System.Drawing.Rectangle SelectionRectangle, string FilePath)
{
// create new image with the specified size = current window size
using (Bitmap bitmap = new Bitmap(SelectionRectangle.Width, SelectionRectangle.Height))
{
using (Graphics g = Graphics.FromImage(bitmap))
{
g.CopyFromScreen(
// X start for copy is current window LEFT - scaled
(int)(SourcePoint.X * SCALE_FACTOR),
// Y start for copy is current window TOP - scaled
(int)(SourcePoint.Y * SCALE_FACTOR),
// X start in destination window is 0
0,
// Y start in destination window is 0
0,
// size of destination window is the same as the current window
SelectionRectangle.Size);
}
bitmap.Save(FilePath, ImageFormat.Bmp);
}
}
}
Windows Forms example:
In my test the windows has the size of (250,250)
in pixels.
SourcePoint
is the start, so it should be actually (0,0)
.
DestinationSize is height and width - you don't need the conversions.
//CaptureImage(this.Location, new Point(0, 0), new Rectangle(0, 0, 250, 250), @"c:\temp\screen.bmp");
CaptureImage(this.Location, new System.Drawing.Point(0, 0), new Rectangle(this.Location.X, this.Location.Y, this.Width , this.Height),@"c:\temp\screen.bmp");

