我想允许我的用户在Aero和Windows Classic 之间切换当前用户主题(1).有没有办法可以以编程方式执行此操作?
我不想弹出"显示属性",我只是想改变注册表.(这需要注销并重新登录才能使更改生效).
应用程序换肤(使用Codejock库)也不起作用.
有办法做到这一点吗?
该应用程序通过RDP在Windows Server 2008上托管/运行.
(1)有问题的应用程序是托管的"远程应用程序",我希望用户能够更改显示的应用程序的外观以匹配他们的桌面.
您可以使用以下命令进行设置:
rundll32.exe %SystemRoot%\system32\shell32.dll,Control_RunDLL %SystemRoot%\system32\desk.cpl desk,@Themes /Action:OpenTheme /file:"C:\Windows\Resources\Themes\aero.theme"
警告是,这将显示主题选择器对话框.您可以直接杀死该对话框.
想要以编程方式更改当前主题肯定有充分的理由.例如,自动化测试工具可能需要在各种主题之间切换,以确保应用程序与所有主题一起正常工作.
作为用户,您可以通过双击.theme
Windwos Explorer中的文件,然后关闭弹出的控制面板小程序来更改主题.您可以通过代码轻松完成相同的操作.以下步骤对我来说很合适.我只在Windows 7上测试过.
使用SHGetKnownFolderPath()
获得"本地应用程序数据"文件夹的用户.主题文件存储在Microsoft\Windows\Themes
子文件夹中.存储在那里的主题文件直接应用,而存储在别处的主题文件在执行时会重复.所以最好只使用该文件夹中的文件.
使用ShellExecute()
执行.theme
你在步骤1中找到的文件.
等待主题应用.我只是让我的应用程序睡眠2秒钟.
调用FindWindow('CabinetWClass', 'Personalization')
以获取应用主题时弹出的"控制面板"窗口的句柄.对于非美国英语版本的Windows,"个性化"标题可能会有所不同.
调用PostMessage(HWND, WM_CLOSE, 0, 0)
以关闭"控制面板"窗口.
这不是一个非常优雅的解决方案,但它可以完成这项工作.
我知道这是一张旧票,但今天有人问我该如何做.所以从迈克的帖子开始,我清理了一些内容,添加了评论,并将发布完整的C#控制台应用代码:
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Microsoft.Win32; namespace Windows7Basic { class Theming { /// Handles to Win 32 API [DllImport("user32.dll", EntryPoint = "FindWindow")] private static extern IntPtr FindWindow(string sClassName, string sAppName); [DllImport("user32.dll")] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); /// Windows Constants private const uint WM_CLOSE = 0x10; private String StartProcessAndWait(string filename, string arguments, int seconds, ref Boolean bExited) { String msg = String.Empty; Process p = new Process(); p.StartInfo.WindowStyle = ProcessWindowStyle.Minimized; p.StartInfo.FileName = filename; p.StartInfo.Arguments = arguments; p.Start(); bExited = false; int counter = 0; /// give it "seconds" seconds to run while (!bExited && counter < seconds) { bExited = p.HasExited; counter++; System.Threading.Thread.Sleep(1000); }//while if (counter == seconds) { msg = "Program did not close in expected time."; }//if return msg; } public Boolean SwitchTheme(string themePath) { try { //String themePath = System.Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\Resources\Ease of Access Themes\basic.theme"; /// Set the theme Boolean bExited = false; /// essentially runs the command line: rundll32.exe %SystemRoot%\system32\shell32.dll,Control_RunDLL %SystemRoot%\system32\desk.cpl desk,@Themes /Action:OpenTheme /file:"%WINDIR%\Resources\Ease of Access Themes\classic.theme" String ThemeOutput = this.StartProcessAndWait("rundll32.exe", System.Environment.GetFolderPath(Environment.SpecialFolder.System) + @"\shell32.dll,Control_RunDLL " + System.Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\desk.cpl desk,@Themes /Action:OpenTheme /file:\"" + themePath + "\"", 30, ref bExited); Console.WriteLine(ThemeOutput); /// Wait for the theme to be set System.Threading.Thread.Sleep(1000); /// Close the Theme UI Window IntPtr hWndTheming = FindWindow("CabinetWClass", null); SendMessage(hWndTheming, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); }//try catch (Exception ex) { Console.WriteLine("An exception occured while setting the theme: " + ex.Message); return false; }//catch return true; } public Boolean SwitchToClassicTheme() { return SwitchTheme(System.Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\Resources\Ease of Access Themes\basic.theme"); } public Boolean SwitchToAeroTheme() { return SwitchTheme(System.Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\Resources\Themes\aero.theme"); } public string GetTheme() { string RegistryKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes"; string theme; theme = (string)Registry.GetValue(RegistryKey, "CurrentTheme", string.Empty); theme = theme.Split('\\').Last().Split('.').First().ToString(); return theme; } // end of object Theming } //--------------------------------------------------------------------------------------------------------------- class Program { [DllImport("dwmapi.dll")] public static extern IntPtr DwmIsCompositionEnabled(out bool pfEnabled); /// ;RunProgram("%USERPROFILE%\AppData\Local\Microsoft\Windows\Themes\themeName.theme") ;For User Themes /// RunProgram("%WINDIR%\Resources\Ease of Access Themes\classic.theme") ;For Basic Themes /// ;RunProgram("%WINDIR%\Resources\Themes\aero.theme") ;For Aero Themes static void Main(string[] args) { bool aeroEnabled = false; Theming thm = new Theming(); Console.WriteLine("The current theme is " + thm.GetTheme()); /// The only real difference between Aero and Basic theme is Composition=0 in the [VisualStyles] in Basic (line omitted in Aero) /// So test if Composition is enabled DwmIsCompositionEnabled(out aeroEnabled); if (args.Length == 0 || (args.Length > 0 && args[0].ToLower(CultureInfo.InvariantCulture).Equals("basic"))) { if (aeroEnabled) { Console.WriteLine("Setting to basic..."); thm.SwitchToClassicTheme(); }//if }//if else if (args.Length > 0 || args[0].ToLower(CultureInfo.InvariantCulture).Equals("aero")) { if (!aeroEnabled) { Console.WriteLine("Setting to aero..."); thm.SwitchToAeroTheme(); }//if }//else if } // end of object Program } }