Screen() behavior in Windows HiDPI builds with multiple displays/scaling factors

Thanks, @Eugene Dakin. I think I’ve seen this example in another thread.
While it works, I still have the same question… Your example for example reports: \\\\.\\DISPLAY4 or Monitor Number 4.
Xojo refers to this as Screen(0). So I still wonder how to make the “link” between Xojo’s Screen-Objects and the Monitors from the Windows API.

If you’re interested, have a look at this example project.
What it does: simply shows a modal dialog centerred within the parent window.
With the buttons on the Left, it will do that using Xojo methods (position with .Left/.Top or .Bounds).
The button on the right will do that using Windows API. And the “Fit on Monitor” just makes sure that the “main window” is fully visible within it’s current screen.

With Xojo 2018r3, Windows 10 and 2-3 Monitors (all with different ScaleFactors), the Xojo methods are a mess… It seems to me that this example WindowsAPI approach at least positions the modal dialogs appropriately.

So back to what’s missing… There are situations, where I know that I have to position Dialog Y on (Xojo)Screen(1).
So that’s where I’m still struck… how do I get to know which MonitorHandle is repesenting Xojo’s Screen(1)?

I implemented a method from Michel’s code on the forum called WhichScreen, and here is an example which shows the MonitorHandle and the Xojo Screen that the mouse pointer is located:
DPIResolutionV2.zip/file

Here is a screen grab from the program which shows both the handle and screen number:

In my example program the location of the mouse shows that there are three different screens. In the helpful Monitors_v1 example program you provided, there are only two screens shown. In the TextArea1 control it shows there are three. When I run the Monitors_v1 program and place the Window1 near the far-right location on Screen 1 of my configuration (seen below), then the centered modal window appears partially in Screen 3 and Screen 1.

Code will need to be adjusted in the Monitors_v1 program to determine where Screen 3 stops and Screen 1 begins. The DPIResolutionV2 example program does this change between monitor screen numbers which has a different handle.

The thing with Screen(i).left is, that it reports different values in 2016r3 or 2018r3 (same Multi-Monitors/Multi-ScaleFactors)… so I guess I can’t trust that…?
Or maybe it needs to be different depending on XojoVersion…
Anyway, I’ll probably only come back to this next week - weekend start here :wink:

It looks like you found a bug :slight_smile:

I get two different screen numbers when changing the x-axis value on the far-right screen (Screen 2 and Screen 0) at about the half-way point in the third screen. I am also not able to place the mouse at x-axis position 3421.

A feedback case was created
<https://xojo.com/issue/54234>

Have a relaxing weekend!

Edit: Changed wording to far-right screen.

There are quite some related to Screen and Positioning in Multi-Monitor/Multi-Scale situations on Windows… :frowning:
And for this very reason I’m trying to find a way to be able to place “child windows/dialogs” in a way that works.
I’ve updated the example above with a “position a dialog relative to a parent window”, which seems to work, too.
Once we have a Window, we can do positioning and monitor-querying from that, using the window as “parent” and go relative from there.

It’s just the situation at the very beginning - where to reliably place the first window (at a specific monitor and position)?
Or if you want/need to show a dialog on a specific screen (where you haven’t had another Window before to get the Monitor Handle).
That’s where my question comes in: how to match Xojo’s Screen(X) with MonitorHandle. Doing it by using the Screen’s values is likely going to be wrong. There has to be some API-way to get the all the Monitor Handles in the same order as Xojo’s Screens - I hope :wink:

This occurs when positioning using the WindowsAPI? If so - let me know if you figure out why that happens… I haven’t seen this in a 3-monitor-situation (at work - so I won’t be able to trying to reproduce it over the weekend).

btw: if you don’t align your monitors with all the same Top-y-Position, things will go even worse (with Xojo’s methods).

The screen number and position work as-expected when using Windows API calls. The problem is when using Xojo’s Screen call.

I’ve updated the example project.
The ‘Pos’ Buttons on the bottom allow to position a Window relative to a currently visible one. Compared to the previous example I’ve fixed to respect the Window Decoration.

While doing that, I’ve discovered yet another bug :frowning: <https://xojo.com/issue/54242>
By setting oWnd2.Left=some-value, the Window’s .Height gets unexpectedly a different value (+/- 1). This is also “fixed” when using the Windows API to position.

Now all that is missing is a way to enumerate and build an array of Monitor Handles (which has the same order such as Xojo’s Screens). That would allow us to use this as a workaround to handle Multi-Monitors/Multi-ScaleFactor situations with the current and recent XojoVersions…
Any ideas, suggestions, attempts or solutions are greatly appreciated :slight_smile:

Another update to the example project. The TextAreas on the Top shows Xojo’s Screens, and now on the right I hope I could retrieve the Monitors via WindowsAPI.
I only have 1 Monitor right now… so I don’t know what happens with multiple monitors (and if the retrieved Handles are in the same order such as Xojo’s Screens).
Could anyone with 2-3 Monitors run the example and drag the window between the monitors?
then please let me know if:

  • Xojo’s Screens (0,1,2) and the Monitors (0,1,2) are in the same order/position (e.g. if both Screen(1) and Monitor(1) are your “far-right” one)
  • the Monitor Handles in the Labels (retrieved from the Window, updated in Timer) match the ones in the TextArea (queried all Monitors at startup of example project)
    If that’s working and matching Xojo’s order of Screens, then this would allow to reliably position windows/modal-dialogs at specific screens/monitors and position…

While I still hope someone gets to test this with 2-3 Monitors… I already prepared for absolute positioning in the example project (v3).

The goal of v3 is:
It should now be possible to position windows/dialogs both relative to a parent, and on a specified Monitor at a specified Position, working around the Xojo Frameworks bugs in MultiMonitor/MultiScaleFactor situations. And… it should work on macOS, too.

Since I couldn’t test over the weekend, this v3 might still need a couple of tweaks. I’m curious to read how it works for you in your multi-monitor-environment. I hope it’s better compared to what the buttons on the left are doing :wink:

Hi Jurg,

I downloaded your program and using the Windows API Center Modal button works on all three monitors in the correct order.

Using Xojo’s API, the Center modal works on both of the lower resolution monitors and fails on the high resolution HiDPi monitor.

Thanks @Eugene Dakin for testing.

I’d like to know if this example is working for others, too. And/or if the 3 positioning possibilities (relative to a parent Window | absolute | on a specific Screen at a specific position) are working in various Multi-Monitor (and Multi-Scale-Factor) situations.
I’ve updated v3 with some fixes - so please re-download it again.
I hope this example provides a way to reliably position a Window/dialog in the situations that often occur:

  • centerred in a parent window
  • relative to a parent window (.x right/left of the parent, .y up/down the parent)
  • place a dialog explicitly on Screen Z, at position X/Y

Note:

  • Using the buttons on the Left, it’s done the “Xojo way” - and things are likely to be positioned wrong.
  • using the buttons on the Right, it’s done via Windows API - and I hope this works reliably for Xojo built apps
  • Some differences are expected: with Xojo, you can position a Window at 0,0 - and that will be the content area. So the WindowTitle and MenuBar won’t be visible at all. In this example’s WindowsAPI implementation, it always makes sure that the positioned window/dialog is fully visible on a Monitor. That’s why a window positioned like that will be “moved down” (on purpose).
  • when using the WindowsAPI Methods provided in the Module, it should fallback to work on macOS, too.

If that’s working as a workaround for now (I really hope Xojo fixes these Screen/Positioning/HiDPI/ScaleFactor issues sooner rather than later or never)… then HiDPI might be an option to enable for Windows apps built with Xojo that are not only used internally.

Let me rephrase “absolute”. What I mean with that I’ve written now like this in the example project: Position at Xojo Window .Left/Top
That’s for the situation where you store aWindow.Left, aWindow.Top (once aWindow .Close’s - and maybe temporarily save the ‘last position’ somewhere), in order to restore that Window at some later time at the previous location where the user has closed it. So you need a way to assign that .Left and .Top value again - in a way that the Window shows at the expected position.
I think to have that working, but could only test on 2 Monitors until now :slight_smile:

Such as @Graham Busch and @David Miller have mentioned and explained at the beginning of this Thread, it is very well possible that on 3 monitors a Xojo Window will report .Left=2100 on both Screen(1) and Screen(2). So it’s still not reliably possible to use these .Left/.Top positions to place a dialog.

What is working for me: The example project reports the “at relative Monitor Position (x, y)”. That along with the MonitorIndex allows to place a dialog on every available Monitor, at a relative Monitor position.

You can test this by showing “Window2” in the example project (by clicking any of the positioning buttons), then move it to some Monitor of yours. Read the “relative Monitor Position”, and place the values in the appropriate fields. Set the “on Screen/Monitor”, and the “Pos” on the right.
This seems to be working for me, even if monitors 1,2 are place above/below each other.

[quote=404209:@David Miller]I just spent a while flipping “off” the HiDPI switch and retesting. As expected, everything “works properly” under Win10 this way, regardless of the screen arrangement and individual screen scaling factors.

What it means to me at the moment is: I can’t use HiDPI for a potential production release build without going down the route of making my own fixed Screen() function and getting it to “line up” correctly with how Window properties behave when a Window is placed and positioned on that screen - and even then, not feeling this will be solid enough to release. It’s a shame, because Retina support works fine on the Mac and there are many graphics in the UI that are nice and ready-to-go at upscaled resolutions. A fix in the framework - which is where it “should” be fixed - is the right thing to wait for.

I’m hopeful…! It’s easy for me to test: a fix in the framework, I can just switch HiDPI back on, rebuild, and run it. It’ll be obvious whether it starts doing the right thing.

In the meantime: what would be useful in the r3 alphas would be: separate, per-platform settings having to do with higher DPI builds. Right now, the HiDPI switch covers both OSX and Windows and you have to remember to set it one way or the other. How about adding a new “Retina” switch that applies only to OSX builds; to go along with the existing “HiDPI” switch (and have it only apply to Windows builds)? (Just like, there’s now a Dark Mode switch in the same part of the IDE, which only applies to OSX builds but which would be ignored for Windows builds - there’s room for some platform specificity there).[/quote]
very good thanks bro

My solution which appears to work on Windows HDPI for setting the screen position to take up entire second / third screen is as follows, it uses MBS plugins to get correct values - i am sure the api’s are easy enough to find.

  1. Get a list of MBS WindowsDisplays and extract out primary,x,y from the results. These are the correct screen positions for the screens.
  2. Reorder the results with primary screen first and the rest in sequential order, this is to match up to Xojo’s Screen() funtion.
  3. Use the SetWindowPos api to locate your window using the x,y positions.
  4. use Xojo.Window.width and height values to assign width and height (There is an odd bug that the setwindowpos api incorrect sets the size based on scaling or something based on the window frame type, Modal Dialog works, Global Floating Window does not.)

I have tests on a lot of different screen sizes / scalings / resolutions and hardware (Screens) and all appear to work as expected.

If you are wanting to save and load screen locations i assume using left and top from xojo would work but aligning to something else you need to do half of it outside of Xojo.

Meanwhile: what might be valuable in the r3 alphas would be: independent, per-stage settings having to do with higher DPI fabricates. At this moment, the HiDPI switch covers both OSX and Windows and you need to make sure to set it one way or the other. What about including another “Retina” switch that applies just to OSX works; to oblige the current “HiDPI” switch (and have it just apply to Windows assembles)? (Much the same as, there’s presently a Dark Mode switch in a similar piece of the IDE, which just applies to OSX assembles yet which would be overlooked for Windows constructs - there’s space for some stage particularity there