如何在Windows 8/8.1中通过P/Invoking程序更改视觉主题

本文关键字:程序 Invoking 视觉 Windows | 更新日期: 2023-09-27 17:59:12

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

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

我想知道这可以通过在注册表项HKEY_CURRENT_USER'Software'Microsoft'Windows'CurrentVersion'ThemeManager上设置一些值,然后通过SendMessagePostMessage或其他功能发布/发送消息,或者通过SendMessageTimeOut功能、SHChangeNotifySystemParametersInfo或其他功能通知环境变化来实现,因为在uxtheme.dll库中似乎没有什么用于此任务,问题是,应用视觉主题更改的功能和参数是什么,有一些商业应用程序可以做到这一点,那么具体步骤是什么?,我尝试了所有这些功能,但都没有成功。


这是我过去为Windows7做的解决方案,我记得这并不完美,因为对于某些主题,颜色没有正确应用,只有通过用户会话重新登录才能解决,以在修改后正确影响更改:

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

在windows8中,我认为因为DWM的组成发生了变化,所以代码不再工作。

如何在Windows 8/8.1中通过P/Invoking程序更改视觉主题

pinvoke.net上描述了一个名为"SetSystemVisualStyle"的未记录函数,它允许您更改当前的"msstyles"文件。由于该功能未记录在案,因此它附带了一条警告:"使用风险自负"。

以下功能签名来自上述网站。

C#签名

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

用法:

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

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

OP要求在答复中添加以下信息。

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