Capturing multiple displays scaling information

I have managed to code a function that semi works in terms of capturing all displays scaling. The only issue is, it captures the default monitors scaling only. The function I found and changed slightly is below:
c#
public static float GetDPIScaling(int monitorIndex)
{
//IntPtr monitorHwnd = GetMonitorHandle(monitorIndex);
IntPtr monitorHwnd = new IntPtr(0);
//Int64 numberTemp = monitorHwnd.ToInt64();
Graphics g = Graphics.FromHwnd(monitorHwnd);
IntPtr desktop = g.GetHdc();

int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

return (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
}
c#
public static float GetDPIScaling(int monitorIndex)
{
//IntPtr monitorHwnd = GetMonitorHandle(monitorIndex);
IntPtr monitorHwnd = new IntPtr(0);
//Int64 numberTemp = monitorHwnd.ToInt64();
Graphics g = Graphics.FromHwnd(monitorHwnd);
IntPtr desktop = g.GetHdc();

int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

return (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
}
With this, it returns 1.25 for 125% scaling. If I change my default monitor to 150%, it will return 1.5. So it does return the scaling. The only issue I have now is passing the monitor index through as a parameter. And then using it in the following way
c#
IntPtr monitorHwnd = new IntPtr(monitorIndex);
c#
IntPtr monitorHwnd = new IntPtr(monitorIndex);
This will throw an error once monitor index is not 0. The error shows the following:
Exception thrown: 'System.OutOfMemoryException' in System.Drawing.dll
An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll
Out of memory.
Exception thrown: 'System.OutOfMemoryException' in System.Drawing.dll
An unhandled exception of type 'System.OutOfMemoryException' occurred in System.Drawing.dll
Out of memory.
According to my understanding of the program. The value of 'monitorHwnd ' will be something like
0x0000
0x0000
when it is 0 and
0x0001
0x0001
when it is 1 and so on. This is how I call my function:
c#
foreach (var monitor in monitorList)
{
float dpiScaling = GetDPIScaling(monitor.Index);
string scalingString = (dpiScaling * 100).ToString();
Console.WriteLine($"DPI Scaling for Monitor {monitor.Index}: {scalingString}%");
}
c#
foreach (var monitor in monitorList)
{
float dpiScaling = GetDPIScaling(monitor.Index);
string scalingString = (dpiScaling * 100).ToString();
Console.WriteLine($"DPI Scaling for Monitor {monitor.Index}: {scalingString}%");
}
The overall reason for me needing the scaling is for a feature I am making that will take a screenshot. This is one of those functions to make the app work on multiple displays.
No description
16 Replies
Jester
Jester6mo ago
ok ill take a look
SparkyCracked
SparkyCracked6mo ago
Thank you!!! I've been working on it for the past 3 days. This is the closest I have gotten. When we pass 0 into the pointer it does give 125% for all screens which as you said may be due to the null hwnd
Jester
Jester6mo ago
EnumDisplayMonitors function (winuser.h) - Win32 apps
The EnumDisplayMonitors function enumerates display monitors (including invisible pseudo-monitors associated with the mirroring drivers) that intersect a region formed by the intersection of a specified clipping rectangle and the visible region of a device context. EnumDisplayMonitors calls an application-defined MonitorEnumProc callback functio...
GetDpiForMonitor function (shellscalingapi.h) - Win32 apps
Queries the dots per inch (dpi) of a display.
SparkyCracked
SparkyCracked6mo ago
I was able to fetch the screens Monitor \.\DISPLAY1: HWND = 65539 Monitor \.\DISPLAY2: HWND = 65541 Monitor \.\DISPLAY3: HWND = 65537
Jester
Jester6mo ago
EnumDisplayMonitors(null, null, your delegate, 0) in your delegate GetDpiForMonitor for each handle it gets
SparkyCracked
SparkyCracked6mo ago
Ok, will give this a try in about 5 min Wanna get coffee real quick Can I ask, do you mind trying to assist me with the existing fuction.
c#
public static float GetDPIScaling(IntPtr monitorHwnd)
{
//IntPtr monitorHwnd = GetMonitorHandle(monitorIndex);
//IntPtr monitorHwnd = new IntPtr(monitorIndex); // You need to obtain the monitor's HWND based on the monitorIndex, or you can pass the correct HWND as an argument.
//Int64 numberTemp = monitorHwnd.ToInt64();
Graphics g = Graphics.FromHwnd(monitorHwnd);
IntPtr desktop = g.GetHdc();

int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

return (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
}
c#
public static float GetDPIScaling(IntPtr monitorHwnd)
{
//IntPtr monitorHwnd = GetMonitorHandle(monitorIndex);
//IntPtr monitorHwnd = new IntPtr(monitorIndex); // You need to obtain the monitor's HWND based on the monitorIndex, or you can pass the correct HWND as an argument.
//Int64 numberTemp = monitorHwnd.ToInt64();
Graphics g = Graphics.FromHwnd(monitorHwnd);
IntPtr desktop = g.GetHdc();

int LogicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.VERTRES);
int PhysicalScreenHeight = GetDeviceCaps(desktop, (int)DeviceCap.DESKTOPVERTRES);

return (float)PhysicalScreenHeight / (float)LogicalScreenHeight;
}
I changed it to look like this now. It now uses the hWnd. So it handles that window
Jester
Jester6mo ago
you should dispose the graphics and hdc at the end
SparkyCracked
SparkyCracked6mo ago
Ok I still get the issue
Out of Memory
Out of Memory
This is so weird I get it here Graphics g = Graphics.FromHwnd(monitorHwnd);
Jester
Jester6mo ago
huhchamp
SparkyCracked
SparkyCracked6mo ago
Pointers are new to me so it's something I don't understand
Jester
Jester6mo ago
its also a really old windows api so it is weird idk how this happened
SparkyCracked
SparkyCracked6mo ago
It may be the invalid window type...in terms of hwnd. But It fetches this hwnd so not sure... After evaluating the variables, this is the variable value of monitorHwnd = 0x00010003 Inside graphics g
Jester
Jester6mo ago
im also busy doing other stuff now so i cant help you too much rn
SparkyCracked
SparkyCracked6mo ago
Ok thats fine. You provided a lot of help already. I will keep trying and will let you know of my findings as I make progress Managed to solve this. Thank you very much @297 лаyс ынтил hаллоwээн 👻 A problem that took 4 days...my word when
Jester
Jester6mo ago
necoarcyay issue trolley takes a while to get familiar with the win32 api
SparkyCracked
SparkyCracked6mo ago
Yeah it does, I can agree
Want results from more Discord servers?
Add your server
More Posts
Make a view include itselfI have a view in Xamarin consisting of a picker and a button. Depending on the value in the picker IBlazor WASM project has logic error involving data fetchingHello there! I'm developing a web app/educational game that is meant to teach migrant workers about Same ASP.NET Identity authorization for multiple WebAPIsI would like to have an unified authorization using the ASP.NET Identity for multiple WebAPIs. Is itMSB4025: The project file could not be loaded. Data at the root level is invalid. Line 1, position 1I'm running this file `test.cs` using the terminal but i keep getting the error `MSB4025: The projecOData filteringHi everyone, I want to ask you something about OData, I have roles for a user. And I separate theseBest way to uniquely hash an array of undefined length?I need to recursively hash a tree of arrays/dicts, is there a preferred/best way to hash the values LDAP authentication stopped working for one userHey all! I had an LDAP auth implemented on my site, which worked fine for past two years, but randomC# programs cause 1.9KB of network traffic despite no online functionalityhttps://cdn.discordapp.com/attachments/1006281886089363456/1194881087076306984/image.png?ex=65b1f6baPublishSingleFile, PublishTrimmed and SelfContained .. breaks serilog (Reflection issue?)My requirements: Have a single executable, as small as possible. Therefor I use the options in the t✅ dotnet build and preprocessor symbol definitionHi, anyone knows how to define a preprocessor symbol when running dotnet build? I want to define a s