DarkNet
DarkNet copied to clipboard
[Question] Dark theme for Interaction.MsgBox
I'm developing a WPF application and I use Interaction.MsgBox
instead of MessageBox.Show
, because I want to get Windows 11 native visual style (modern buttons and icons).
MessageBox.Show:
Interaction.MsgBox:
Thanks to DarkNet, I activated the dark theme for everything I wanted, except for this dialog box. Can you help me to do this?
The beginning of my App.xaml.cs:
namespace App
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
System.Windows.Forms.Application.EnableVisualStyles(); // this is required to enable native visual styles
DarkNet.Instance.SetCurrentProcessTheme(Theme.Auto);
Dialog box in MainWindow.xaml.cs:
private void MainWindow_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
string question = "Do you really want to quit?";
MessageBoxResult result = (MessageBoxResult)
Interaction.MsgBox(question, MsgBoxStyle.YesNo, "App");
if (result == MessageBoxResult.Yes)
{
this.Close();
}
}
}
I had to do something similar in an automated test for a different project, let me see if that technique also works here.
This brute force technique may not be the best, but I was able to turn the message box title bar dark by having another thread that finds the window by class name and PID using the mwinapi
library, then uses DarkNet to set the window to dark mode using its HWND. The background task thread does this while the main thread is blocked waiting for the dialog box to return a result. I don't notice any delay before the theme is applied.
SystemWindow? dialogBox = null;
int selfPid;
using (Process selfProcess = Process.GetCurrentProcess()) {
selfPid = selfProcess.Id;
}
Task.Run(() => {
while (dialogBox == null) {
dialogBox = SystemWindow.DesktopWindow.FilterDescendantWindows(false, window => {
if (window.ClassName != "#32770") return false;
using Process process = window.Process; // expensive
return process.Id == selfPid;
}).FirstOrDefault();
if (dialogBox != null) {
DarkNet.Instance.SetWindowThemeRaw(dialogBox.HWnd, Theme.Auto);
}
}
});
DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("hello", "app", MessageBoxButtons.YesNo, MessageBoxIcon.None); // Forms message box
// MsgBoxResult msgBoxResult = Interaction.MsgBox("hello", MsgBoxStyle.YesNo, "App"); // Interaction message box
It works the same with both Forms and Interactions message boxes.
You could also add sleeps or a maximum timeout via cancellation token if those are helpful to your scenario. Also, you may be able to speed up the window finding logic if the dialog box is a child of some other window you know about, but in my testing I could only find it by searching through all windows.
There seems to be a bit of a race condition where the title bar sometimes looks deactivated, but it fixes itself if you blur and focus the window again. I'm not sure what's going on there.
This logic comes from an automated test I wrote recently which asserts that an error message is shown properly in the dialog box of a Winamp plugin, then closes the dialog box automatically, without deadlocking the test.
@Aldaviva D you now how to change the background color of the text and icon of message boxes
@Aldaviva
Thank you I get it worked
@memoarfaa Can you share the code?