Why are Window.Height and Window.Width not exact? (C#, WPF) - c#

I noticed when setting a windows Height and Width (or Min/MaxHeight and Min/MaxWidth in that regard) to a specific value like 800x450 that the window itself can be smaller then the set values. The only time those values are actually accurate is when setting the WindowStyle to None.
MainWindow:
Size set in XAML: 800x450
Actual Size: 786x443
SecondWindow (Light Blue one in the Background)
Size set in XAML: 800x450
WindowStyle: None
Actual Size: 800x450
What causes the the window to be smaller than intended? Also is it always a difference of 7px in Height and 14px in Width?

It is the gap between old, traditional window bounds (location and size) and "extended frame bounds". The latter is actually visible window bounds and can be obtained by DwmGetWindowAttribute function with DWMWA_EXTENDED_FRAME_BOUNDS. These two bounds match, in the case of WPF, when WindowStyle=None and AllowsTransparency=True.
As far as I know, the thickness of gap is 7px (left, right, bottom) when monitor DPI is 96 (default, 100%) and increases as monitor DPI increases. You can find a number of tips to deal with this gap by searching the above keywords.

Related

Auto Scale text to fit the screen in mono

I'm trying to scale a given text, e.g "123\nV.1-4", to fit the screen in mono.
I tried increasing the font size till the screen is not bigger.
My main problem is that I cannot retrieve the size of the label with a new font quickly?
(I'm retrieving with label.GetSizeRequest(out width, out height);)
So any solutions on how to scale the font/text?
Thanks
When the label is resized as you change the font size, the SizeRequest and SizeAllocated events will fire. What you could do is set the font size, then in the SizeAllocated event for the label, set the font size again. You will clearly have to stop the loop at some point, I assume you would cease increasing the font size when your label dimensions outstrip those of the window or screen etc.
However, have you considering using Pango and a drawing area instead?

how to get and set the size of a window in pixels

I have a Window in C# (System.Windows.Window).
I've looked into the documentation and for some reason, the window's width and height are not measured in Pixels but in (1/96)Inch.
is there Any way to set and get a window's size in Pixels instead of the aforementioned unit?
I've found ways of getting the size of the current working area in pixels (which is not necessarily my window) but not of setting it.
additional info:
OS: windows.

How to guarantee contents dimensions of WPF window are always the same regardless of window trim thickness?

Using this image to clearly show the problem:
Red box background image
If I do this in Visual Studio...
Designer layout A
... the image gets clipped because the trim of the window is fatter at runtime than the pseudo-trim in VS designer:
Runtime dimensional change A
If I increase the window size in Visual Studio to look like this...
Designer layout B (with window size increased to match Windows 7 trim thickness)
... the result looks correct:
Runtime dimensions look correct... for Windows 7 trim thickness only
I've tried the same steps with and without a window Grid. The result is the same.
————
As a point of reference, macOS/Cocoa windows are defined by the size of their content area to avoid this problem.
In other words, if I set a window in Xcode to be 300 x 300, at runtime its content view frame will always be 300 x 300 regardless of how Apple changes the window trim dimensions from version to version of the OS.
————
What is the WPF method of achieving window-trim-agnostic content dimensions?
Use GetSystemMetrics to tell you the width and hight of the border to the window (via SM_CXSIZEFRAME & SM_CYSIZEFRAME) and add it to the size of window you are opening or resizing.

Dealing with multiple DPI screens

Let's suppose that I have two screens, side by side:
1920x1080 100% DPI
1360x768 125% DPI
For my Window, this means:
1920x1080: Ok
1088x614: Not ok, it's divided by 1,25 because of the scaling factor.
Turning into this:
1920x1080 + 1088x614: 3008x1080
I want to use the CopyFromScreen/BitBlt methods.
These methods ignore all DPI info, making the Left and Top properties (of a window, for example) useless if inside a high dpi screen. Or left to a high dpi screen, since it behaves like 1 screen, example:
So whenever I need to get a screen point from within a set of screens with at least one having a high DPI, it will return a smaller point.
Is there any way to get the true (by true, ignoring the scaling factor) XY info from a set of screens with (at least one) high DPI?
I already tried the managed PointToScreen and the unmanaged ClientToScreen methods, both resulting the same "right" point.
Please, read
I want to take screenshots of the screen based of the position of my Window.
I have two monitors, one with 100% DPI, other with 125% DPI.
If my Window is inside the 1st monitor, the screenshot based on the Left/Top properties of my Window works.
If my Window is inside the second monitor, the screenshot won't take the right spot!
Because
The BitBlt API method ignores the scaling of the screens. Example:
Screenshot of the point 100;100 will be right, because it's inside the 1st screen.
Screenshot of the point 1950;100 won't be right, because it's inside the 2nd screen. Notice that it's 30 pixels to the right.
Why?
As said earlier, for my app, the 125% DPI reduces the screen resolution to 1088x614, but for the BitBlt method, it is still 1360x768.
So I can't convert the Left/Top properties, because it will be wrong, since there is a 100% DPI screen to the left.
Example of the Left property:
I believe this is the right way to convert:
1920px + 50px: 100% + 125%: 1920 + 62: 1982px
And this is the proposed version:
1920px + 50px: 100% + 125%: 2400 + 62: 2462px
See, if I simple convert the current Left property based on the DPI of the current Window, on this case my second screen, I'll also be converting the values of my first screen. This should not happen.

MeasureString() gives different size for different screen resolutions

We are using Measurestring() to calculate size based on the length of text. For different screen resolution, MeasureString() gives different size.
Graphics g;
Size size = g.MeasureString(GetItemText(this.Items[n]), this.Font).ToSize();
width=size.width;
For Screen resolution 125%, size.width=76 and
For Screen resolution 100% and 150%, size.width=61.
How can i get same width in this code, please suggest me some ideas to measure size using measurestring().
Waiting for suggestions........
It's because the 125% behaves differently by default. For example, in Windows 7, if you change the DPI setting, because of the Windows XP style mode, the applications will aware of the current DPI setting. However, if you set 150%, this checkbox is not set by default, so the applications will work in DPI unaware mode, which means, that the MeasureString will return the same result as in case of 96 DPI, and the resizing will be performed automatically by Windows.
Normally you can ignore the result, because the sizes will be upscaled in your application anyway. If you still want to obtain the actual DPI value of Windows, see my answer here: https://stackoverflow.com/a/33412669/5114784
And then you can upscale your drawing like this (but as I said, normally this is not needed):
// See GetSystemDpi in the referenced post
float zoomFactor = (float)GetSystemDpi() / 96f;
size.Width = (int)(size.Width * zoomFactor);
size.Height = (int)(size.Height * zoomFactor);

Categories