96 Dpi is a pretty low res monitor. Mine is 218 dpi. Anyway see this thread
https://stackoverflow.com/questions/13858665/disable-dpi-awareness-for-wpf-application
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Is there a way to disable scaling for all the WPF application even if windows has some scale per monitor or system-wide scale?
I need to have WPF windows that is always 1:1 with physical pixels (DPI is always 96), and by this time I found no way to do this: application manifest or API methods for the awareness are useless, they just changing ways how the content is being scaled: as a bitmap or by the application. I need application always has the fixed, 100% scale, even if system settings are 200% per monitor or per whole system. Do you guys know some ways that could help?
Hi,@MERUN KUMAR MAITY. Welcome to Microsoft Q&A. You could try to see if solution a and b helps you.
OMG! , Sir finally you come here to rescue me, I am waiting for you for long time. Thank you very much for your comment.
I already tried those solution before posting this Question here in this Microsoft forum, but none of these are properly working. Though, your both solution are outstanding but I don't know why these are not working in my case.
But still, they are modern day industry standard. For me, your option 'b' is more productive, efficient and more realistic. Can you please simplify the answer of your option 'b'? Because I am unable to understand that how can I apply those Scale X and Scale Y transformation to my Main Window? or Should I apply those scale transformation to my Main Grid?
These concepts are pretty much confusing and very hard to understand. I hope you help me to figure it out. Please give your simplify and descriptive answer and I definitely accept your answer.
Hi,@MERUN KUMAR MAITY. You could try the following code to see if it helps you.
The LayoutTransform property allows you to apply transformations to the visual element (in this case, the MainGrid) to counteract any scaling that occurs due to the system's DPI settings.
By inverting the scale factors obtained from TransformToDevice, you effectively cancel out the scaling effect, ensuring that your application renders at a consistent size.
Setting your application as DPI-aware in the manifest file is crucial to prevent Windows from automatically scaling your application based on the display settings.
<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/PM</dpiAware>
</windowsSettings>
</application>
</assembly>
MainWindow:
<Window x:Class="WpfApp1.MainWindow"
...
Title="DPI Aware Application" Height="400" Width="600"
Loaded="Window_Loaded">
<Grid x:Name="MainGrid">
<Button Content="Click Me" Width="100" Height="30" />
</Grid>
</Window>
Window_Loaded:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
// Get the current scale of the application
double scaleX = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice.M11;
double scaleY = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice.M22;
// Invert the scale values
double invertScaleX = 1 / scaleX;
double invertScaleY = 1 / scaleY;
// Apply the inverted scales to the LayoutTransform of the MainGrid
ScaleTransform scaleTransform = (ScaleTransform)MainGrid.LayoutTransform;
scaleTransform.ScaleX = invertScaleX;
scaleTransform.ScaleY = invertScaleY;
}
}
Thank you very much sir for giving me a decent answer but unfortunately your code does not work in my project, whenever I try to run this code in my project on my Laptop it's give me black screen and freeze the output window, it's not a working solution.
I suggest you to give me the answer with that XAML binding like exactly shown on your Stack overflow, may be that's specific way the solution is working I hope.
Hi,@MERUN KUMAR MAITY.The above example simplifies the solution in the link.
A black screen and freezing output window in a WPF application can occur due to various reasons, especially when applying transformations or handling DPI settings. Here are some steps to troubleshoot and resolve this issue:
1.Check for Errors Ensure there are no exceptions or errors in your output window or logs that might give clues about what’s going wrong. Errors could be related to the PresentationSource or LayoutTransform.
Try commenting out the LayoutTransform line and see if the application still freezes. This will help determine if the issue is directly related to the scaling transformation.
Remove the DPI-aware configuration from the manifest temporarily to see if the application runs correctly without it. If it does, there may be additional adjustments needed for handling DPI settings in your application.
Thanks for your comment. Dear sir, I already tested all of your thoughts and codes but none of them are working and that's why I come here in this forum. I hope some Microsoft engineer are able to solve this problem.
As far as I know, you can suppress all 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.
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
</windowsSettings>
</application>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
var source = PresentationSource.FromVisual(this) as HwndSource;
source?.AddHook(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;
}
}
But one problem of this code is, It has no effect on the initial rendering. To solve this code issue we have to handle this WM_DPICHANGED
message properly. it's a pure Win32 base Code and I hope you have a very deep knowledge on Win32 (C++).
Can you please solve the issue? How to handle the initial rendering.
Hi,@MERUN KUMAR MAITY. When WM_DPICHANGED
is received, you could update your UI to handle the DPI change correctly. You can see if the following methods for handling DPI changes (including scaling adjustments) help you.
Update the MainWindow
Code:
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
var source = PresentationSource.FromVisual(this) as HwndSource;
source?.AddHook(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)
{
// Extract the new DPI from lParam
int newDpiX = (int)(lParam.ToInt64() & 0xFFFF);
int newDpiY = (int)((lParam.ToInt64() >> 16) & 0xFFFF);
// Handle DPI change
HandleDpiChange(newDpiX, newDpiY);
handled = true;
}
return IntPtr.Zero;
}
private void HandleDpiChange(int dpiX, int dpiY)
{
// Calculate scale factors
double scaleX = dpiX / 96.0; // 96 DPI is the baseline
double scaleY = dpiY / 96.0;
// Apply scaling to the layout transform
this.LayoutTransform = new ScaleTransform(scaleX, scaleY);
// Update any other necessary elements or layout settings here
// Force a layout update
this.InvalidateVisual();
this.UpdateLayout();
}
For the initial rendering, ensure you apply the scaling transformation as soon as possible after the window is initialized but before it is fully displayed. The HandleDpiChange method should be called initially with the current DPI values if needed.
Thank you very much sir for your reply, there is no need to Handle the DPI changes inside if (msg == WM_DPICHANGED) { }
, Because that is already handle by the application itself that's why there handled = true;
Code is there, Our work is to just preserve that Scaling so that if the application close and restart again in that lower resolution the scaling should be perfect like previous, I hope you understand what I want to say. Though your lParam code is perfect.
But a very important question comes into my mind that Suppose I design my WPF application UI on full HD (1920x1080) monitor and if a user run my application first time on their lower resolution (1366x768) monitor, Does in that case the WM_DPICHANGED
event fire? because they run it very first time. They don't run the application at previously on other screen resolution and DPI.
Hi,@MERUN KUMAR MAITY.
When the application is first launched, Windows applies DPI scaling based on the current monitor’s DPI settings. This means that if your application is launched on a monitor with a different DPI than what was used during development, Windows will handle scaling according to the application’s DPI awareness settings defined in the manifest.
Initial Scaling: Windows handles the initial scaling of the application’s UI automatically based on its DPI-awareness settings. The WM_DPICHANGED
message is not triggered in this case because no DPI change event has occurred while the application was running.
Runtime DPI Changes: The WM_DPICHANGED
message is specifically for handling DPI changes that occur while the application is running, such as when a user moves the application between monitors with different DPI settings or when the system DPI settings are changed.
You can ensure that proper scaling is applied during initialization in the OnSourceInitialized
method to handle different DPI settings on first launch.
For more details, you could refer to WM_DPICHANGED message.
Thank you very much sir, sorry for my late reply but ultimately I found the solution, But the solution need some more modification. I found a random demo project on Github where it's beautifully, implemented.
Just have a look : https://github.com/chjfth/window-finder-control
The problem is, I am unable to run the project on my Laptop due to some error like "WinApp exited with code 9009". If you able to run the project, then 100% the problem will be solved. The solution is WinForms based. To run the code better make sure that you create a demo WinForm project on latest .NET Version 8 and apply all of those code there.
Most important part is please look the "exe-sample" folder very much carefully. Where you find total four exe files which are BtnLook0, BtnLook1, BtnLook2, BtnLook3.
Ultimately if you run the BtnLook2, BtnLook3. where this permonitor Dpi Aware is implemented, one is normal permonitor Dpi Aware and another is permonitor Dpi Aware V2.
Just run those exe and change your Windows OS scaling and you can see it is not effected by the windows system scaling where other exe like BtnLook0, BtnLook1 which are Dpi-unware and sys Dpi are changed with OS scaling.
Those BtnLook2, BtnLook3 functionality is our main goal. We have to implement that in our WPF project.
And if you able to run the demo project successfully then there some way in the code, where all the steps are shown. Because those exe files are just target exe to detect windows. The main application is within the project.
By the way, thank you very much for the hard work you put in, I definitely accept your answer just check that GitHub repository.
96 Dpi is a pretty low res monitor. Mine is 218 dpi. Anyway see this thread
https://stackoverflow.com/questions/13858665/disable-dpi-awareness-for-wpf-application
Thanks for your comment, I already tested all of that but don't get any desire result. If you have any code solution then you can give me.
Respected Sir, I hope you get this comment notification, I just want to get 125% (1.25) Scaling across any device on which my WPF application will run. In a simple sentence the Windows OS (in my case Windows 10) should not scale my WPF application UI at different DPI settings like - 100% (1), 125% (1.25), 150% (1.50) and 175% (1.75).
That's it, that is my only requirement. If you able to solve this question then I definitely accept your answer.