Skip to content

Conversation

@JeremyKuhne
Copy link
Member

@JeremyKuhne JeremyKuhne commented Aug 9, 2025

Theming isn't easy for the system message box and requires using undocumented APIs. To get theming, including a simple themed message box that roughly follows the existing layout.

Move the project to the standard SDK which enables using source generators. The existing SDK was a hack for building before WPF and WinForms were officially released on .NET Core.

Push the C# version to 12 for collections expressions, default parameters for lambdas, etc.

Add CsWin32 for PInvoke source generation. Add PInvokes for getting the modern shell icons for the new dialog. System.Drawing has the new Icons in .NET, but we're still targetting 4.6.2. (Note that some PInvokes have to still be manually defined because we're targetting AnyCPU. Some headers in Windows are defined with nonstandard packing, which makes the SDK generate metadata that is platform specific. For safety they don't generate any of these and they must be manually evaluated. The manual ones I added come from System.Drawing. If we targetted specific architectures this wouldn't be necessary.)

If we're able to move to .NET Core in the future we can get more explicit, coherent theming support through WPF or MAUI.

Existing:

Screenshot 2025-08-09 100920

Themed:
(The light version is not as fully realized, as the theme for that wasn't in the current sources, I did the bare minimum with the intent of following up on the theme sources at some point.)

Screenshot 2025-08-09 100956 Screenshot 2025-08-09 101140 Screenshot 2025-08-09 101033

(The preset dialog doesn't have a real preset string in it, just ran it in the about menu with version text to make sure it was working correctly.)

Theming isn't easy for the system message box and requires using undocumented APIs. To get theming, including a simple themed message box that roughly follows the existing layout.

Move the project to the standard SDK which enables using source generators. The existing SDK was a hack for building before WPF and WinForms were officially released on .NET Core.

Push the C# version to 12 for collections expressions, default parameters for lambdas, etc.

Add CsWin32 for PInvoke source generation. Add PInvokes for getting the modern shell icons for the new dialog. System.Drawing has the new Icons in .NET, but we're still targetting 4.6.2. (Note that some PInvokes have to still be manually defined because we're targetting AnyCPU. Some headers in Windows are defined with nonstandard packing, which makes the SDK generate metadata that is platform specific. For safety they don't generate any of these and they must be manually evaluated. The manual ones I added come from System.Drawing. If we targetted specific architectures this wouldn't be necessary.)

If we're able to move to .NET Core in the future we can get more explicit, coherent theming support through WPF or MAUI.
Copy link
Member

@brianrob brianrob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks @JeremyKuhne! Just to confirm - this does not use any undocumented APIs, right? I think I read from your description that the solution you used to avoid undocumented APIs is to create your own dialog, but just want to make sure.

<PackageReference Include="Microsoft.IdentityModel.Tokens" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Web.WebView2" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Windows.CsWin32">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirming - do we need any of these artifacts at runtime, or just at compile time?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a development dependency and the PrivateAssets entry controls this.

You might be using a dependency purely as a development harness and might not want to expose that to projects that will consume your package. In this scenario, you can use the PrivateAssets metadata to control this behavior.

The Microsoft.Windows.CsWin32 package takes the information from NativeMethods.txt and genrates the PInvoke data.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @MagicAndre1981. That was my assumption, but just wanted to be sure as I've not used it before.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @MagicAndre1981. That was my assumption, but just wanted to be sure as I've not used it before.

after this is merged the currently used DLLimport code at several places should be also moved to generated code by CsWin32

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, this just source generates the interop from the Windows published metadata

@JeremyKuhne
Copy link
Member Author

LGTM. Thanks @JeremyKuhne! Just to confirm - this does not use any undocumented APIs, right? I think I read from your description that the solution you used to avoid undocumented APIs is to create your own dialog, but just want to make sure.

Yeah, I spun a custom one to avoid undocumented features.

Copy link
Member

@brianrob brianrob left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you @JeremyKuhne!

@brianrob brianrob merged commit 51c3343 into microsoft:main Aug 18, 2025
5 checks passed
@JeremyKuhne JeremyKuhne deleted the themedialog branch August 18, 2025 23:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants