Open vsfeedback opened 2 years ago
Can you please share a minimal repro to check this further?
A good solution with minimal code change is to replace the calls to MessageBox with calls to TaskDialog
MessageBox has been superseded by TaskDialog so I suppose future Windows version will not fix the MessageBox High DPI bug(s)
Repro with .Net7 (tested on Win10): https://github.com/mayphi/WpfBlurryMessageBox
Start the programm an move it to another monitor with a different resolution (for example from 1920x1080 to 3840x2160).
@singhashish-wpf is this repro enough? Do you need more informations?
@mayphi - We haven't got a chance to look at the repro yet. Will check it as soon as possible and will report back. Thanks.
Is there any news for this?
MessageBox is a native Windows function, there isn't much WPF can do. You can try filing an issue using Feedback Hub, but as @bronxzv said, the newer TaskDialog API works as expected, so I am not sure there would be enough business case to fix MessageBox.
If it helps, since Windows 1809 you can use SetThreadDpiAwarenessContext
to switch to GDI scaling before showing the MessageBox and reverting after it returns - as far as I can tell that avoids blurry MessageBoxes.
Thank you. Can you show me an example of how to use correctly SetThreadDpiAwarenessContext with c#? Because I try to use it but I don't know how.
Sure, try this:
[DllImport("user32.dll")]
private static extern IntPtr SetThreadDpiAwarenessContext(IntPtr context);
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var previous = SetThreadDpiAwarenessContext(-5); // GDI scaling
MessageBox.Show("MyMessageBoxText", "MyCaption", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
SetThreadDpiAwarenessContext(previous);
}
I would probably turn it into a fancy IDisposable
class.
Thank you, that works. And how is the correct way to implement IDisposble
? What should I put in the method Dispose
?
class MainWindow : IDisposable { private bool disposed;
[DllImport("user32.dll")]
private static extern IntPtr SetThreadDpiAwarenessContext(IntPtr context);
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
var previous = SetThreadDpiAwarenessContext(-5); // GDI scaling
MessageBox.Show("MyMessageBoxText", "MyCaption", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
SetThreadDpiAwarenessContext(previous);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// What do I put here?
}
}
disposed = true;
}
}
If you do something like
public class ThreadDpiAwareness : IDisposable
{
[DllImport("user32.dll")]
private static extern IntPtr SetThreadDpiAwarenessContext(IntPtr context);
private const int UNAWARE_GDISCALED = -5;
private IntPtr _previousContext;
private ThreadDpiAwareness(int context)
{
_previousContext = SetThreadDpiAwarenessContext(context);
}
public void Dispose()
{
SetThreadDpiAwarenessContext(_previousContext);
}
public static IDisposable GdiScaled => new ThreadDpiAwareness(UNAWARE_GDISCALED);
}
then you can use
using (ThreadDpiAwareness.GdiScaled)
MessageBox.Show("Nazdar");
_This issue has been moved from a ticket on Developer Community._
[severity:It bothers me. A fix would be nice] 1st monitor: 100 %, primary 2nd monitor: 150 %
If you have the App window on the 2nd monitor where a MessageBox is displayed, it will be displayed blurred in the correct size. On the other hand, if the 1st monitor also has a scaling of 150%, the MessaageBox on the 2nd monitor will be displayed in focus.
This affects WPF apps with .NET Framework 4.8 under Windows 11.
So the MessageBox is always created with the scaling of the primary monitor and then stretched to the scaling of the 2nd monitor. However, it should work the same way as other dialogs, e.g. OpenFileDialog and FolderBrowserDialog.
Original Comments
(no comments)
Original Solutions
(no solutions)