Skip to content

Commit

Permalink
Merge pull request #2046 from cwensley/curtis/wpf-messagebox-theme
Browse files Browse the repository at this point in the history
Fix MessageBox themes in WPF apps without a custom manifest in .NET 5+
  • Loading branch information
cwensley committed Oct 23, 2021
2 parents c41de8a + dfededa commit d3e5545
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 51 deletions.
1 change: 1 addition & 0 deletions src/Eto.Wpf/Eto.Wpf.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ You do not need to use any of the classes of this assembly (unless customizing t
<LastGenOutput>FontDialogResources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="XPThemes.manifest" />
</ItemGroup>

<!-- Automatically added by WindowsDesktop SDK -->
Expand Down
57 changes: 20 additions & 37 deletions src/Eto.Wpf/Forms/EnableThemingInScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ internal class EnableThemingInScope : IDisposable
IntPtr cookie;
static ACTCTX enableThemingActivationContext;
static IntPtr hActCtx;
static bool contextCreationSucceeded = false;
static bool? contextCreationSucceeded;

public EnableThemingInScope(bool enable)
{
Expand Down Expand Up @@ -72,58 +72,41 @@ bool EnsureActivateContextCreated()
{
lock (typeof(EnableThemingInScope))
{
if (!contextCreationSucceeded)
if (contextCreationSucceeded != null)
return contextCreationSucceeded.Value;

// Use a custom manifest from resources and write it to a temp file
var manifestLoc = Path.GetTempFileName();
try
{
// Pull manifest from the .NET Framework install
// directory

string assemblyLoc = null;

FileIOPermission fiop = new FileIOPermission(PermissionState.None);
fiop.AllFiles = FileIOPermissionAccess.PathDiscovery;
fiop.Assert();
try
{
assemblyLoc = typeof(Object).Assembly.Location;
}
finally
{
CodeAccessPermission.RevertAssert();
}

string manifestLoc = null;
string installDir = null;
if (assemblyLoc != null)
var stream = typeof(EnableThemingInScope).Assembly.GetManifestResourceStream("Eto.Wpf.XPThemes.manifest");
if (stream == null)
return false;

using (var fs = File.Create(manifestLoc))
{
installDir = Path.GetDirectoryName(assemblyLoc);
const string manifestName = "XPThemes.manifest";
manifestLoc = Path.Combine(installDir, manifestName);
stream.CopyTo(fs);
}

if (manifestLoc != null && installDir != null)
if (manifestLoc != null)
{
enableThemingActivationContext = new ACTCTX();
enableThemingActivationContext.cbSize = Marshal.SizeOf(typeof(ACTCTX));
enableThemingActivationContext.lpSource = manifestLoc;

// Set the lpAssemblyDirectory to the install
// directory to prevent Win32 Side by Side from
// looking for comctl32 in the application
// directory, which could cause a bogus dll to be
// placed there and open a security hole.
enableThemingActivationContext.lpAssemblyDirectory = installDir;
enableThemingActivationContext.dwFlags = ACTCTX_FLAG_ASSEMBLY_DIRECTORY_VALID;

// Note this will fail gracefully if file specified
// by manifestLoc doesn't exist.
hActCtx = CreateActCtx(ref enableThemingActivationContext);
contextCreationSucceeded = (hActCtx != new IntPtr(-1));
}
}
finally
{
if (File.Exists(manifestLoc))
File.Delete(manifestLoc);
}

// If we return false, we'll try again on the next call into
// EnsureActivateContextCreated(), which is fine.
return contextCreationSucceeded;
return contextCreationSucceeded.Value;
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/Eto.Wpf/XPThemes.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<description>Windows Forms Common Control manifest</description>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
</assembly>
14 changes: 0 additions & 14 deletions test/Eto.Test.Wpf/app.manifest
Original file line number Diff line number Diff line change
Expand Up @@ -64,18 +64,4 @@
</windowsSettings>
</application>

<!-- Enable themes for Windows common controls and dialogs (Windows XP and later) -->
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>

</assembly>

0 comments on commit d3e5545

Please sign in to comment.