Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix MessageBox themes in WPF apps without a custom manifest in .NET 5+ #2046

Merged
merged 1 commit into from
Oct 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>