D3D9 Windowed Mode Multi-monitor - c#

I have just started looking into D3D9 using SlimDX.
I have a device created off the primary display adapter and device.present only flips the backbuffer onto the primary monitor. When the window is moved to the secondary display, the surface is no longer updated. That is expected.
What I'm trying to do though, is that if the window is moved across to the secondary display (fully across to secondary display or partially, occupying both primary and secondary displays), the same rendered image gets presented.
What do I need to do to achieve this (someone suggested CreateAdditionalSwapChain here and here, but I'm not getting the bigger picture of how this could work)?
I only intend to support multi-head cards.

I found the reason it wasn't showing on the secondary screen.
I (or more appropriately, the sample code) had PresentFlags.DeviceClip set when creating the D3D9 device. Removing it allows it to work across the screens.

Related

How to set High DPI scaling override to System (Enhanced) for WinForms app

I have an old-school ordinary WinForms app in VS2019, for which the tabs on a tab control are vertically squished on a high-DPI monitor. In fact, if the app is opened on a high-DPI monitor and dragged to a regular monitor, the tabs remain squished. I want the app to automatically scale the controls properly. As a user, I can make that happen post-installation by adjusting Compatibility Settings on the executable: [Properties->Compatibility->Change high DPI settings->High DPI scaling Override->Override high DPI scaling behavior. Scaling performed by System (Enhanced)]. I don't want the user to have to do that -- I'd rather fix it in the source code.
I've read dozens and dozens of articles on this subject and it seems they are all outdated, as the 'recommended method' has changed several times over the past few years (and none of them seem to work). The bottom line is that it seems likeI need to do the opposite of what most of them advise -- specifying that the app is DPI-aware (i.e. turning 'DPI-awareness' 'on'). It is NOT DPI-aware, but the 'System (Enhanced)' scaling (seemingly intended precisely for non-DPI-aware apps) works great. But maybe I misunderstand what 'DPI-awareness' means.
What is currently the best practice for specifying programmatically (or via the manifest) that 'this app does not have any provisions for scaling itself or being aware of how many pixels per inch your monitor has, but allowing "System (Enhanced)" scaling from Windows 10 works great. Please do that.'?

How to change font size for a monitor in Windows?

I am frequently playing games and though I have a good graphics card, it's not capable of running all games in 4K on my 4K monitor. Since I run all my games in borderless windowed mode, I first have to reduce the monitor resolution down to 1080p before starting the game, and I'm trying to automate this.
I have already created a program that is capable of doing this, but I need to hardcode in a few big strings that are some kind of identifier. The way the program operates is that it first:
Modifies the registry key HKCU\Control Panel\Desktop\PerMonitorSettings\<big id here> and set a key beneath it to lock in the font size
Uses ChangeDisplaySettingsEx to make the resolution and positioning change to the monitor, this has the extra benefit of refreshing the monitor setting from the registry, and reacting to my registry change in point 1
Now, I have two questions but I'll concentrate on one of them here, and that question is this:
Given the device name (id?) \\.\DISPLAY1, is there a way to set the font size of that monitor without monkeying around in that registry key? I can't find a corresponding setting in the DEVMODE or DISPLAY_DEVICE structs that I am already using, and when trying to search for it using Google I can only find ways to make my own software DPI aware, which is not what I want.
I tried using EnumDisplayDevices, and it gives me some device id's and another registry key but I can't find anything in that structure that would let me even read the current font size.
I basically like a programmatical way to change my monitor between 4K # 200% size and 1080p # 100% size.

WPF Issues Creating Window on Secondary Screen Only On Certain Hardware Configurations

I'm using the standard recommendation for creating a Window and having it display on a secondary monitor:
I use the following to get the screens available:
Screen[] availableScreens = Screen.AllScreens;
Extract the working area of the target screen (second screen in my case, not the primary screen):
secondaryScreenWorkingArea = availableScreens[1].WorkingArea;
When creating the window, set the location properties based on the working area (before calling Show()):
Left = secondaryScreenWorkingArea.Left;
Top = secondaryScreenWorkingArea.Top;
Width = secondaryScreenWorkingArea.Width;
Height = secondaryScreenWorkingArea.Height;
Some other things to note about the window:
It is a fullscreen window that is intended to span the entire second
display
It is not the main application window
It is hidden from the taskbar, it is intended to be supplemental to
the main application window
WindowState = WindowState.Maximized;
ShowInTaskbar="False"
WindowStyle = WindowStyle.None;
Running on Windows 10 Enterprise V 1809
Below is a rundown is different configurations that I've tested, and only one of them is not behaving correctly:
When I run this on a workstation setup with two 1920x1080 displays, 100% display scaling, it works as expected.
When I run this on a workstation setup with two 1920x1080 displays, 150% display scaling, it works as expected.
When I run this on a workstation setup with a 1920x1080 display and a secondary USB display (800x480) connected, 100% display scaling, it works
When I run this on a workstation setup with a 1920x1080 display and a secondary USB display (800x480) connected, 150% display scaling, it works
When I run this on a Microsoft Surface Go with the main surface display (1800x1200) and a secondary USB display (800x480) connected to the surface dock, 100% display scaling, it works
When I run this on a Microsoft Surface Go with the main surface display (1800x1200) and a secondary USB display (800x480) connected to the surface dock, 150% display scaling, it DOES NOT work. Instead, once Window.Show() is called, this is triggering the window to relocate to the primary display (The surface go screen). I noticed this because I am receiving a LocationChanged event for the window during my call to Window.Show() and see the Width and Height properties have updated to the sizing of the Surface Go display (1800x1200). But, curiously, the Top and Left properties are NOT updated even though the window has moved.
As you can see from the cases above, it seems to be an issue with Display scaling + the Surface Go. On my workstation, I forced the same resolution as the Surface go (1800x1200) and set display scaling to 150%, but could not replicate the issue from the Surface Go
Furthermore, I performed some testing with another USB display with a slightly higher resolution (1024x600) and have noticed that the same issue occurs, only on the Surface Go, but this time it required me pushing the display scaling to 200% before the issue began to occur in that configuration.
Several things I've tried, but none produced any solutions to this issue:
Tried various configurations of dpiAware and dpiAwareness. These changed the scaling of the coordinates I received when grabbing the AvailableScreens, but using scaled/unscaled coordinates had not affect on this issue
Restarting the Surface Go after changing the display scaling option (per the "Some apps won't respond to scaling changes until you sign of" message displayed in the Display Settings
Tried setting WindowState = WindowState.Maximized both before and after the Loaded event and both yielded the same result.
Any help or other ideas for things to try would be appreciated, not sure if this is a WPF, Windows 10 or a Microsoft Surface Go issue.

How to get the image of a secondary screen and place it into a window on the primary screen?

I'd like to copy an image of the desktop of my secondary screen and place it into a window on the primary screen (using C# and WPF).
I was thinking about using Drawing.CopyFromScreen but that's WinForm-tech and I'd like to see if it's possible using WPF only.
What would be the fasted perfoming way of doing this if I want to continously capture this image?
Can I create an ImageSource for the screen image somehow?
Also, if the mouse-pointer is not captured with this method I'd like to draw it into this image so I can see where the pointer is on the secondary screen without actualy seeing the screen physically.
Only need this for Windows 8.
I think this article is exactly what you need. It describes how to take a screen capture and create a BitmapSource (which inherits from ImageSource) from it.

How should I automatically support single or double monitors in XNA on Windows 7?

I'm creating a game application using Microsoft XNA that will run on one public-facing screen (projector) with controls on the laptop screen (Windows 7.) When the second monitor is not available, I'd like only the public-facing screen to show on the laptop screen. The proportions of the screens will be identical.
Is there a library to allow us to do this automatically, or at worst by changing a setting?
Check if there are two monitors available with GraphicsAdapter.Adapters.Count()
If there are, create another form, and set it to the second monitor (projector). Then, with every frame, render your public-facing interface onto the secondary monitor, and draw the controls onto the primary.
To switch between forms, just swap the handles:
graphics.GraphicsDevice.Present(form1.Handle);
Otherwise, draw the public-facing only.
You can read about how to use WinForms with XNA at http://create.msdn.com/en-US/education/catalog/sample/winforms_series_1
This solution assumes two things:
that the primary display is set to the laptop's display and the second monitor isw set to extend (and not mirror)
you are using XNA through WinForms
The best way I can think of on the top of my head would involve creating a rendering server and a client application.
You can have the rendering server do all the actual rendering to two separate RenderTarget2D (or the main screen and then on a rendertarget) and then transfer one rendertarget to the client for rendering to the secondary screen. This means that the client application is super-lightweight and will only involve rendering a texture to full screen.
Transfering data to the client application can be done in many ways, but my personal favourite in this situation would be a memory mapped file to transfer the byte data of the rendertarget to the second. Otherwise tcp communication should be used for performance. If you need info on extracting byte data or transfering to the other application simply comment on my post.

Categories