-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Positioning a window in WPF (Top and Left Properties) with dpiAwareness in PerMonitorV2 mode #3105
Comments
You should make sure your system version later than Windows 10 Anniversary Update |
My version of windows 10 is 1909. |
Hello, Window: Height = 492 - Width = 509 Test 1 I note that the message WM_DPICHANGED (0x02E0) was sent to my window with 144dpi (0x90) for X and 144dpi (0x90) for Y. (150%) After moving the window, the properties have the following values: Test 2 I note that the message WM_DPICHANGED (0x02E0) was sent to my window with 96dpi (0x60) for X and 96dpi (0x60) for Y. (100%) After moving the window, the properties have the following values: I think there is a problem with positioning the window on an extended desk. The positioning values are logical units (96dpi). Can this change be made in the future because I need to use the positioning values of different windows in a WPF program on several monitors with different scales? |
Try this on netcoreapp3.1 for best experimental results, esp since most AppContext switches don’t have to be set for this TFM. Make sure you have IIRC Window.Left/Top is expressed in WPF’s local device independent 1/96” coordinate space. It must be translated to screen coordinate using |
@Perpete - please let us know if @vatsan-madhavan suggestions is working for you. |
Hello, To use Core 3.1, I had to convert my written test program from VB to C #. You can use my test program contained in the .zip file. Thanks for your help. |
What I tried to explain in my last comment simply related to interpreting If you search for information regarding the reverse transformation (screen -> logical), you'll find plenty of references about how to do that. (Roughly, something like Note that these transformations aren't static - don't try cache them esp. They depend on the current DPI, current position on the screen etc. Just rely on WPF to produce these transformations on-the-fly. You can generalize this information to further debug your problems with When per-monitor dpi-awareness is involved, a critical piece of information that's needed wrt Win32 API's (esp. API's that carry coordinate information in their data-payload) is whether Windows auto-scales the coordinates (in the data-payload) to match the That said, some API's may not do this - either by design, or because they have not been updated. This is why I'm suggesting that you'll have to combine perusing documentation with experimental observations. In the case of Have you considered using Also be aware that the "screen-coordinates" are essentially |
Hello, In my test program, I simply request the displacement of the window with the property Me.Left = XXX whose value is entered in a TextBox. If I am on the 2nd monitor which has a scale 150% and I want to move the window on the 1st monitor which has a scale 100% at the value Left = 100 (96dpi), I must set Me.Left = 66.66 (100 /1.5=66.66). If I am on the 1st monitor which has a 100% scale and I want to move the window on the 2nd monitor which has a 150% scale in the center of it at the value Left = 2880 (96dpi), I must place Me .Left = 2880 (2880/1 = 2880). If I am on the 1st monitor which has a 125% scale and I want to move the window on the 2nd monitor which has a 150% scale in the center of it at the value Left = 2880 (96dpi), I must place Me .Left = 2304 (2880 / 1.25 = 2304). Managing the position with dpiAwareness in PerMonitorV2 mode is much more complicated due to the transformation of the Top and Left properties of the window from the monitor scale. I think that the most easily usable positioning data are the resolutions of the monitors at 96dpi (1920x1080, 1680x1050, ... ...) I'm also going to have another problem with managing the window positioning in a program where the window coordinates are saved and where these windows must be repositioned when this program is opened. My starting question was to know if this management of the position with dpiAwareness in PerMonitorV2 mode of the windows on a extended desktop was correct and frozen in order to be able to start modifying my programs. Thanks for your help. |
|
Hello, You are right, there is no need for programming code for adjusting window sizes with dpiAwareness in PerMonitorV2 mode. My test program works very well with Core 3.1, FrameWork 4.8 and FrameWork 4.7.2. As I was explaining to you before, I have a program that stores window size and positioning values and recreates those windows at the size and position stored. I will use examples to explain myself better. Screen 1 (Main): 1680x1050 1st Example When recreating the window with these values, my new window is found on screen 1 at the position This.Left = 1120 (1120/1) and This.Top = 0 instead of screen 2. The This.Height and This.Width values remain at 509 and 492. 2nd Example When recreating the window with these values, my new window is found on screen 1 at the position This.Left = 933 ((1120x1.25) /1.5) and This.Top = 0 instead of screen 2 . The This.Height and This.Width values remain at 509 and 492. 3rd Example When recreating the window with these values, my new window is found on screen 2 at the position This.Left = 2520 (1680x1.5) instead of 1680 and This.Top = 0. The This.Height and This.Width values remain at 509 and 492. To find the value on the scale of the correct position of the window on all screens, I simply apply the opposite formula used between Windows 10 and WPF from the initial value. It is for these reasons that I need to know the scale of the screens to restore or move the windows to the right position. I think there is a problem with scaling the position between Windows 10 and WPF. Let's take an example : Currently with PerMonitorV2 Let's take another example: Currently with PerMonitorV2 I think the value of 1647 is not correct. To correct this problem, a solution would be that the rectangle pointed by lParam in the WM_DPICHANGED message contains a Top and Left value calculated by considering each screen resolution with its separate scale. At this time, Wpf will receive a correct positioning without any adaptation to be made. Another solution would be to keep the positioning values in logical units (96dpi) without modification between windows 10 and WPF like the modes without PerMonitorV2. For size values, the management between Windows 10 and WPF works perfectly well. |
hi sorry ,does it work now? |
@xmaxrayx Sorry, no. It is a design issues. But you can get the correct postion from win32. |
@xmaxrayx Yeah, you meet a problem with coordinate system transformation. The GetCursorPos is screen coordinate but the |
@xmaxrayx For window positioning references, I always use 100% monitor scale values. If my window is initially positioned on monitor 2: Here is my test code in VB. `
End Sub Here is my code for test (wpf in vb with net 6). I don't understand why this problem hasn't been fixed all this time. |
@Perpete Hi, many thanks it works now <3 this is my code for c#
yeah I found it funny winforms don't have that problem with wpf. |
thx, wish if they remove that " wpf transform" for window locations or at least we have option for |
You are absolutely right. |
I failed to fix this problem three years ago... |
This bug causes any logic for saving/restoring window layouts to fail on any multi DPI system since WPF always uses the main display DPI. When windows are created they always pick up the default DPI and don't consider he fact that they may be moved around programatically. |
Hello,
For a WPF project in VB, I retrieve the mouse coordinates using a Hook mouse (MSLLHOOKSTRUCT) to display a window on the desktop according to the selection rectangle defined by the user.
I noticed that the mouse coordinates do not take into account the screen scales.
Is this normal?
So, I had to retrieve this scale using the GetDpiForMonitor API and created a manifest file with DPI recognition per screen.
PerMonitorV2 .
In a test project, I noticed problems with the bad positioning of my window in relation to the placement request.
Here are my tests with the Left property of a window:
Screen resolution 1: 1680x1050
Screen resolution 2: 1600x900
Screen 1 = 100% - Screen 2 = 150%.**
Window on screen 1, asks to switch to screen 2
Ask left = 1680 after moving : left = 1120 on screen 2
The left was divided by 1.5 after the move.
Window on screen 2, asks to switch to screen 1
Ask left = 100 after moving : left = 150 on screen 1
The left was multiplied by 1.5 after the move.
Screen 1 = 150% - Screen 2 = 100%.
Window on screen 1, asks to switch to screen 2
Ask left = 1680 after moving : left = 2520 on screen 2
The left was multiplied by 1.5 after the move.
Window on screen 2, asks to switch to screen 1
Ask left = 100 after moving : left = 66.66 on screen 1
The left was divided by 1.5 after the move.
Is this management of the values of the positioning properties correct?
These requested positions do not correspond to the physical position where I want to place my window.
Without DPI recognition per screen, the positioning of the window respects the requested coordinates. The Top and Left properties do not change despite the different scales.
You can perform the test using the program contained in the zip file.
WpfApp2.zip
The text was updated successfully, but these errors were encountered: