In daily life we have to deal with a lot of different types of display size it may be mobile or may be a 4k monitor. The screen resolution vary from display to display. Here another important factor is DPI (Display per inch) which is mainly a scaling factor in windows but have a great relation with screen resolution.
Now I give you an example first suppose I run the visual studio application on a Full HD monitor and the resolution is 1920x1080. Suppose I change my display resolution from full HD (1920x1080) to 1366x768. And after that I run the visual studio again on the same display and I see that the user interface (UI) is get slightly bigger and all the controls,text,icons and buttons are perfectly align according to the current monitor DPI scaling and resolution.
And the UI should get bigger as it happens when we run visual studio and other windows application on lower resolution.
I want to apply that similar effect in my WPF application so that each time the screen resolution and DPI changes, my application will automatically adjust according to the display DPI and resolution. I already try Microsoft per monitor DPI aware for windows 10 and edit the app. Mainfest file and uncomment some code according to the GitHub instructions but nothing works in my case.
I also bind with the screen resolution with my application height and width but it's cover whole the screen I don't want that.
But one thing I understand is I have to get the system DPI and disable scaling for my WPF Application even if windows has some scale per monitor or system-wide scale available.
I disabled the automatic scaling by declaring True/PM
in the application manifest, which means that the application takes full responsibility for scaling, and then ignoring the WM_DPICHANGED
message when it comes.
Here is the Code what I have tried :
In Application Manifest I add this code :
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
<longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
</windowsSettings>
</application>
Here is the Win32/C++ Base C# wrapper code :
public partial class MainWindow : Window
{
private HwndSource hwndSource;
public MainWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
hwndSource = PresentationSource.FromVisual((Visual) sender) as HwndSource;
hwndSource.AddHook(new HwndSourceHook(WndProc));
}
private const int WM_DPICHANGED = 0x02E0;
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
if (msg == WM_DPICHANGED)
{
handled = true;
}
return IntPtr.Zero;
}
}
This Code works very much perfectly there no issue on it. And it is one of the greatest way, by using this method, application will not change scale during the lifetime. But it produce some weird issues and problems.
The problem is, it does not Detect the Initial DPI changes in a WPF Application. How Can I prevent it from scaling the application at very startup?
My Second question is, though this code works beautifully by let the application takes full responsibility for scaling itself but it unable to handle Small UI DPI changes. Pretty much Hard to understand? I give you a decent example. If somehow the Screen resolution/DPI changes, the application Main UI perfectly scale accordingly to it's own need but suppose the Application have a Combo Box and any user click the Combo Box, all we know that a drop down menu will open as it is, the catch is that, drop down menu list will not properly scale. It gives a terrible UI looks because the Main UI is scaled but Small things are not scaled up. The Tooltip Description also not scale properly. Because as we know the Tooltip only appear when I mouse hover any UI element, this hover mechanism only works after the application run initially, it does not come at first it's a some-kind of mouse mechanism.
Also, if the Application have any sub window which can be open by clicking a button after the main application run, that sub windows also not properly scale.
In a single sentence, any UI elements that are not present in the Main application User Interface (UI) at Initial Runtime are not render by the application itself.
Most important point of this question is, most of the time I call it as DPI but in practical this DPI only changes when I change the Screen Resolution, that means the DPI and the Resolution are two interconnected things. I also want to state that I just change my Laptop screen resolution from Full HD (19201080) to 1366768 to take the DPI changes effect on my WPF app.
I know in programming Universe, there multiple solutions of a single problem exists but in my case I take the solution which is easy for me to understand of my problem.
So, I take the Win32/C++ Base C# wrapper approach. If you have any other solution then you can provide me in the answer as well, If your solution works then I definitely accept your answer.
I tried some Stack Overflow code but that does not work.
Here is the Stack Overflow Question Link : https://stackoverflow.com/questions/55538032/is-there-a-way-to-disable-scaling-for-all-the-wpf-application-even-if-windows-ha
Here some other Honorable Stack Overflow Question Link Where experience developer try to discuss the answer and giving their valuable knowledge on this topic.
https://stackoverflow.com/questions/5022397/scale-an-entire-wpf-window
https://stackoverflow.com/questions/3193339/tips-on-developing-resolution-independent-application
https://stackoverflow.com/questions/13858665/disable-dpi-awareness-for-wpf-application