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

C# 如何在Windows 8/8.1中通过P/Invoking以编程方式更改视觉主题?,c#,vb.net,windows,winapi,pinvoke,C#,Vb.net,Windows,Winapi,Pinvoke,在C#或其他VB.Net中,知道可视化主题.theme文件的应用,我想在Windows中应用该可视化主题,而不使用,这取决于其他应用程序,如RunDll32.exe,只需p/调用,但是,为了避免一些奇怪的事情,比如打开个性化窗口,然后使用FindWindow函数关闭它,这个过程应该从平台自动调用,而不是与其他窗口交互 这个关于如何应用主题的问题以前在S.O中被很多人提出过(包括我在内,通过注册表修改加上服务停止/恢复的解决方案,仅在Windows 7下有效),我认为是时候让一位专家用一种WinA

C#或其他VB.Net中,知道可视化主题.theme文件的应用,我想在Windows中应用该可视化主题,而不使用,这取决于其他应用程序,如RunDll32.exe,只需p/调用,但是,为了避免一些奇怪的事情,比如打开个性化窗口,然后使用
FindWindow
函数关闭它,这个过程应该从平台自动调用,而不是与其他窗口交互

这个关于如何应用主题的问题以前在S.O中被很多人提出过(包括我在内,通过注册表修改加上服务停止/恢复的解决方案,仅在Windows 7下有效),我认为是时候让一位专家用一种WinAPI方法来说明我们了,这种方法既不涉及RunDll32.exe,也不涉及打开个性化窗口

我想知道可以通过在注册表项
HKEY\U CURRENT\U USER\Software\Microsoft\Windows\CurrentVersion\TheManager
上设置一些值,然后通过
SendMessage
PostMessage
或其他功能发布/发送消息来实现这一点,或者可以通过
SendMessageTimeOut
函数或
SHChangeNotify
systemparameters sinfo
或其他函数通知环境更改,因为在
uxtheme.dll
库中似乎对此任务没有任何用处,问题是应用视觉主题更改的功能和参数,有一些商业应用程序可以做到这一点,那么具体步骤是什么?我尝试了所有这些功能,但都没有成功


这是我过去为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

在windows 8中,我认为因为DWM组合更改了,所以代码不再工作。

有一个名为的未记录函数,允许您更改当前的“msstyles”文件。由于此功能未记录在案,因此附带警告:“使用时自担风险”

以下功能签名来自上述站点

C#签名 用法:

// This will set your Visual Style to Luna
SetSystemVisualStyle(@"C:\WINDOWS\resources\Themes\Luna\Luna.msstyles", "Metallic", "NormalSize", 0);
Net签名
_
共享函数将SystemVisualStyle(ByVal pszFilename作为字符串,ByVal pszColor作为字符串,ByVal pszSize作为字符串,ByVal dwReserved作为整数)设置为整数
端函数
OP要求在回答中添加以下信息

当使用自定义msstyles应用第三方主题时,函数本身不会适当地更改某些对话框颜色和某些控件样式,而是通过测试从0到Int32.Max的所有可能值来进行实验,以将其传递给SetSystemVisualTheme函数的保留参数,当我发现值为65时,解决了这个颜色和样式问题


看到这个:?我以前见过这个问题,但是没有什么可以帮助我,它不能满足我问题的要求(没有RundL32,没有个性化窗口+fundwindow功能),谢谢你。你可以使用UI自动化()来完成它无论如何,谢谢你,但我假装这样做没有与其他窗口交互或在其他窗口上实现自动化(我想你的意思是在个性化窗口上使用UI自动化)。这个问题真的不能通过调用适当的函数来解决吗?有人知道是否存在可能性?我想您正在寻找SetSystemVisualStyle函数?请参阅:注意,此函数没有文档记录。我刚刚测试了它,它在Win8.1下工作。
// This will set your Visual Style to Luna
SetSystemVisualStyle(@"C:\WINDOWS\resources\Themes\Luna\Luna.msstyles", "Metallic", "NormalSize", 0);
<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