DPI and Rect

I have a small problem that I can not find the answer to. I have an application that receives certain processes and gets the window size. The only problem is that it takes up a percentage of the actual screen size (which the user sees).

I want to take a screenshot of the application, but if I use Rect windows, I get a smaller screen than it is, because the resolution is 125%. This means that my original resolution, which is displayed ( 1280 * 800 ), is less than my screen resolution ( 1600 * 1000 ), you can understand that this small hiccup makes my program unreliable. My question is how to fix this?

I created a manifest that I set DPIAware to true. I also disabled Visual Studio hosting in debugging. But that does not help. I still get the same values ​​and the same problem. Here is my code snippet for the actual screenshot:

 RECT Rect = new RECT(); System.Diagnostics.Process[] p = System.Diagnostics.Process.GetProcessesByName("Process"); ShowWindow(p[0].MainWindowHandle, 9); SetForegroundWindow(p[0].MainWindowHandle); if (GetWindowRect(p[0].MainWindowHandle, ref Rect)) { var bmp = new Bitmap(Rect.Width, Rect.Height); var graphics = Graphics.FromImage(bmp); graphics.CopyFromScreen(Rect.Left, Rect.Top, 0, 0, new Size(Rect.Width, Rect.Height), CopyPixelOperation.SourceCopy); bmp.Save(@"C:\Screenshots\temp1.png"); } 

This gives a screenshot of 1280 * 800 , not enough to cover the whole process, which is 1600 * 1000 . Everything is off because the screen coordinates are incorrect. If I multiply everything by 1.25, everything will be fine, but this is not a solution, because I do not know what the DPI settings are on another PC.

EDIT 3:

I will post the full code using RECT.

 RECT Rect = new RECT(); System.Diagnostics.Process[] p = System.Diagnostics.Process.GetProcessesByName("LoLPatcherUx"); ShowWindow(p[0].MainWindowHandle, 9); SetForegroundWindow(p[0].MainWindowHandle); if (GetWindowRect(p[0].MainWindowHandle, ref Rect)) { int processH = Rect.Bottom - Rect.Top; int processW = Rect.Right - Rect.Left; float processWidth; float processHeight; SizeF dpi = GetCurrentDpi(); // Calc the scale. SizeF scale = new SizeF() { Width = dpi.Width / 96f, Height = dpi.Height / 96f }; // Scale the rectangle. processWidth = Rect.Width * scale.Width; processHeight = Rect.Height * scale.Height; var bmp = new Bitmap(lolPatcherBreedte, lolPatcherHoogte); Graphics graphics = Graphics.FromImage(bmp); graphics.CopyFromScreen(Rect.Left, Rect.Top, 0, 0, new Size(processW, processH)); bmp.Save(@"C:\Screenshots\temp1.png"); } public struct RECT { private int _Left; private int _Top; private int _Right; private int _Bottom; public RECT(RECT Rectangle) : this(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom) { } public RECT(int Left, int Top, int Right, int Bottom) { _Left = Left; _Top = Top; _Right = Right; _Bottom = Bottom; } public int X { get { return _Left; } set { _Left = value; } } public int Y { get { return _Top; } set { _Top = value; } } public int Left { get { return _Left; } set { _Left = value; } } public int Top { get { return _Top; } set { _Top = value; } } public int Right { get { return _Right; } set { _Right = value; } } public int Bottom { get { return _Bottom; } set { _Bottom = value; } } public int Height { get { return _Bottom - _Top; } set { _Bottom = value + _Top; } } public int Width { get { return _Right - _Left; } set { _Right = value + _Left; } } public Point Location { get { return new Point(Left, Top); } set { _Left = value.X; _Top = value.Y; } } public Size Size { get { return new Size(Width, Height); } set { _Right = value.Width + _Left; _Bottom = value.Height + _Top; } } public static implicit operator Rectangle(RECT Rectangle) { return new Rectangle(Rectangle.Left, Rectangle.Top, Rectangle.Width, Rectangle.Height); } public static implicit operator RECT(Rectangle Rectangle) { return new RECT(Rectangle.Left, Rectangle.Top, Rectangle.Right, Rectangle.Bottom); } public static bool operator ==(RECT Rectangle1, RECT Rectangle2) { return Rectangle1.Equals(Rectangle2); } public static bool operator !=(RECT Rectangle1, RECT Rectangle2) { return !Rectangle1.Equals(Rectangle2); } public override string ToString() { return "{Left: " + _Left + "; " + "Top: " + _Top + "; Right: " + _Right + "; Bottom: " + _Bottom + "}"; } public override int GetHashCode() { return ToString().GetHashCode(); } public bool Equals(RECT Rectangle) { return Rectangle.Left == _Left && Rectangle.Top == _Top && Rectangle.Right == _Right && Rectangle.Bottom == _Bottom; } public override bool Equals(object Object) { if (Object is RECT) { return Equals((RECT)Object); } else if (Object is Rectangle) { return Equals(new RECT((Rectangle)Object)); } return false; } } 
+5
source share
1 answer

You can get the current DPI setting with

properties.

Thus, you should be able to calculate it correctly (as is done in one of my projects).

Just get them by creating a dummy Form and Graphics object from it (if your code runs outside the context of the form):

 public static SizeF GetCurrentDpi() { using (Form form = new Form()) using (Graphics g = form.CreateGraphics()) { var result = new SizeF() { Width = g.DpiX, Height = g.DpiY }; return result; } } 

Control.CreateGraphics Method


Using:

 if (GetWindowRect(p[0].MainWindowHandle, ref Rect)) { var bmp = new Bitmap(Rect.Width, Rect.Height); Graphics graphics = Graphics.FromImage(bmp); // Use the helper function to get the current dpi. SizeF dpi = GetCurrentDpi(); // Calc the scale. SizeF scale = new SizeF() { Width = dpi.Width / 96f, Height = dpi.Height / 96f }; // Scale the rectangle. Rect.Width *= scale.Width; Rect.Height *= scale.Height; graphics.CopyFromScreen(Rect.Left, Rect.Top, 0, 0, new Size(Rect.Width, Rect.Height), CopyPixelOperation.SourceCopy); bmp.Save(@"C:\Screenshots\temp1.png"); } 

Demo

 class Program { [DllImport("user32.dll", SetLastError = true)] static extern bool GetWindowRect(IntPtr hwnd, ref RECT lpRect); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetForegroundWindow(IntPtr hWnd); static void Main(string[] args) { RECT rect = new RECT(); Process[] processes = System.Diagnostics.Process.GetProcessesByName("iexplore"); Process iexplore = processes.First(); ShowWindow(iexplore.MainWindowHandle, ShowWindowCommands.Restore); SetForegroundWindow(iexplore.MainWindowHandle); var result = GetWindowRect(iexplore.MainWindowHandle, ref rect); RectangleF rectF = new RectangleF() { Location = new PointF(rect.Left, rect.Top), Size = new SizeF(rect.Right - rect.Left + 1, rect.Bottom - rect.Top + 1) }; var bmp = new Bitmap((int)rectF.Width, (int)rectF.Height); Graphics graphics = Graphics.FromImage(bmp); graphics.CopyFromScreen((int)rectF.Left, (int)rectF.Top, 0, 0, new Size((int)rectF.Width, (int)rectF.Height), CopyPixelOperation.SourceCopy); bmp.Save(@"C:\temp\screenshot1.jpg", ImageFormat.Jpeg); } } enum ShowWindowCommands { Hide = 0, Normal = 1, ShowMinimized = 2, Maximize = 3, ShowMaximized = 3, ShowNoActivate = 4, Show = 5, Minimize = 6, ShowMinNoActive = 7, ShowNA = 8, Restore = 9, ShowDefault = 10, ForceMinimize = 11 } [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left; public int Top; public int Right; public int Bottom; } 
+4
source

Source: https://habr.com/ru/post/1209938/


All Articles