简体   繁体   English

如何通过P / Invoking在Windows 8 / 8.1中以编程方式更改视觉主题?

[英]How do I change a visual theme programatically in Windows 8/8.1 by P/Invoking?

In C# or else VB.Net , knowing the ubication of a visual theme .theme file, I would like to apply that visual theme in Windows, without depending on other applications such as RunDll32.exe , just P/Invoking, but avoiding weird/strange things such as opening the personalization window and then using FindWindow function to close it, the procedure should be automated from platform invoking not interacting with other windows. C#VB.Net中 ,知道视觉主题.theme文件的普及之后,我想在Windows中应用该视觉主题, 而不依赖于其他应用程序(例如RunDll32.exe) ,仅使用P / Invoking,但避免使用奇怪的/奇怪的事情,例如打开个性化窗口,然后使用FindWindow函数将其关闭,应从平台调用不与其他窗口进行交互的过程中自动执行该过程。

This question about how to apply a theme was asked before in SO by many people (Included by me, with a solution via registry modification plus service stoping/resuming that only works under Windows 7), I think its time for an expert to illustrate us with a WinAPI approach that does not involve RunDll32.exe neither opening the personalization window. 之前,很多人都曾问过有关如何应用主题的问题(包括我在内,其中包括通过注册表修改加上服务停止/恢复的解决方案,该解决方案仅在Windows 7下有效),我认为现在是专家来说明我们的时候了使用不涉及RunDll32.exe的WinAPI方法,也不会打开个性化窗口。

I wonder this could be done by setting some values on the registry key HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager and then posting/sending a message via SendMessage or PostMessage or other function, or maybe notifying about an environment change via SendMessageTimeOut function or SHChangeNotify or SystemParametersInfo or another function, because in the uxtheme.dll library seems there is nothing usefull for this task, the question is what function and with what parameters to apply a visual theme change, there are some commercial applications that can do this, which are the steps to do it then?, I tried all those functions without success. 我想知道是否可以通过在注册表项HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager上设置一些值,然后通过SendMessagePostMessage或其他函数发布/发送消息,或者通过SendMessageTimeOut函数通知环境更改来完成此操作或SHChangeNotifySystemParametersInfo或其他函数,因为在uxtheme.dll库中似乎没有什么可用于此任务的问题,问题是什么函数以及使用哪些参数来应用视觉主题更改,有些商业应用程序可以做到这一点,那么要执行哪些步骤?,我尝试了所有这些功能,但均未成功。


This is the solution I did for Windows 7 in the past, I remember that is not perfect because for some themes the colors were not applied properlly and only has beeen solved with an user session re-logon to affect changes properlly after modifications: 这是我过去为Windows 7所做的解决方案,我记得那不是完美的,因为对于某些主题,颜色没有正确应用,只能通过用户会话重新登录解决,才能在修改后正确影响更改:

Private Sub SetAeroTheme(ByVal themeFile As String,
                         Optional ByVal colorName As String = "NormalColor",
                         Optional ByVal sizeName As String = "NormalSize")

    Dim regKeyPath As String = "Software\Microsoft\Windows\CurrentVersion\ThemeManager"

    Using themeService As New ServiceController("Themes")

        If themeService.Status = ServiceControllerStatus.Running Then
            themeService.Stop()
            themeService.WaitForStatus(ServiceControllerStatus.Stopped)
        End If

        Using regKey As RegistryKey = Registry.CurrentUser.OpenSubKey(regKeyPath, writable:=True)

            regKey.SetValue("LoadedBefore", "0", RegistryValueKind.String)
            regKey.SetValue("DllName", themeFile, RegistryValueKind.String)
            regKey.SetValue("ColorName", colorName, RegistryValueKind.String)
            regKey.SetValue("SizeName", sizeName, RegistryValueKind.String)

        End Using

        If themeService.Status = ServiceControllerStatus.Stopped Then
            themeService.Start()
            themeService.WaitForStatus(ServiceControllerStatus.Running)
        End If

    End Using

End Sub

In windows 8 I think because DWM composition changes just that code didn't worked anymore. 在Windows 8中,我认为是因为DWM组成发生了变化,只是代码不再起作用了。

There is an undocumented function named "SetSystemVisualStyle" described on pinvoke.net that allows you to change the current "msstyles" file. pinvoke.net描述了一个未公开的名为“ SetSystemVisualStyle”的函数,该函数使您可以更改当前的“ msstyles”文件。 As this function is undocumented it comes with the caveat: "use at your own risk". 由于未记录此功能,因此附带警告:“使用后果自负”。

The following function signatures are from the site referenced above. 以下功能签名来自上面引用的站点。

C# signature C#签名

[DllImport("UxTheme.Dll", EntryPoint = "#65", CharSet = CharSet.Unicode)]
public static extern int SetSystemVisualStyle(string pszFilename, string pszColor, string pszSize, int dwReserved);

usage: 用法:

// This will set your Visual Style to Luna
SetSystemVisualStyle(@"C:\WINDOWS\resources\Themes\Luna\Luna.msstyles", "Metallic", "NormalSize", 0);

VB.Net signature VB.Net签名

<DllImport("UxTheme.DLL", BestFitMapping:=False, CallingConvention:=CallingConvention.Winapi, CharSet:=CharSet.Unicode, EntryPoint:="#65")> _
Shared Function SetSystemVisualStyle(ByVal pszFilename As String, ByVal pszColor As String, ByVal pszSize As String, ByVal dwReserved As Integer) As Integer
End Function

The OP asked that the following information be added to this answer. OP要求在此答案中添加以下信息。

The function itself does not properlly change some dialog colors and some control styles when a 3rd party theme is applied with a custom msstyles, but doing an experiment by testing all the possible values from 0 to Int32.Max to pass it to the reserved parameter of the SetSystemVisualTheme function, by the moment I discovered that a value of 65 fixes this colorization and styles issue. 当使用自定义msstyles应用第3方主题时,该函数本身不会适当地更改某些对话框的颜色和某些控件的样式,而是通过测试从0到Int32.Max的所有可能值以将其传递给的保留参数来进行实验。现在,我发现SetSystemVisualTheme函数的值为65可以解决此着色和样式问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM