пример - tags files windows




Как программно изменить текущую тему Windows? (4)

Я хочу, чтобы мои пользователи переключали текущую тему пользователя между Aero и Windows Classic (1). Есть ли способ, которым я могу сделать это программно?

Я не хочу всплывать «Свойства экрана», и я сомневаюсь в просто изменении реестра. (Для этого необходимо выйти из системы и войти в систему, чтобы изменения вступили в силу).

Скрытие приложений (с использованием библиотек Codejock ) также не работает.

Есть ли способ сделать это?

Приложение размещено / запущено на Windows Server 2008 по RDP .

(1) Данное приложение является размещенным «удаленным приложением», и я хочу, чтобы пользователи могли изменять внешний вид отображаемого приложения в соответствии с их рабочим столом.


Я считаю, что лучшее, что вы можете сделать, это открыть ваш целевой файл .msstyles (в c:\windows\resources\themes ), который отобразит окно свойств дисплея. На этом этапе вы можете использовать оконный подкласс для программного нажатия правой кнопки.


Вы можете установить его, используя следующую команду:

rundll32.exe %SystemRoot%\system32\shell32.dll,Control_RunDLL %SystemRoot%\system32\desk.cpl desk,@Themes /Action:OpenTheme /file:"C:\Windows\Resources\Themes\aero.theme"

Caveat - это то, что это отобразит диалог выбора темы. После этого вы можете убить этот диалог.


Помимо должности «Ян Гойвартс»: я использую SendMessage вместо PostMessage. Разница в том, что SendMessage ожидает, что команда будет введена в окне. Это означает, что в SendMessages возвращается, вы знаете, что диалог темы закрыт.

Поэтому, если вы начнете его с чудовищного (но гениального) метода rundll32.exe, предложенного «Campbell». Перед отправкой WM_CLOSE вы должны дождаться секунды. В противном случае тема не будет установлена, и приложение сразу закроется.

В приведенном ниже фрагменте кода извлекается файл из ресурса (тегепак). Затем выполняется desk.cpl с rundll32.exe, ждет 3 sceonds, затем отправляет WM_CLOSE (0x0010), ожидает, что команда будет процессом (время, необходимое для установки темы).

    private Boolean SwitchToClassicTheme()
    {
        //First unpack the theme
        try
        {
            //Extract the theme from the resource
            String ThemePath = System.Environment.GetFolderPath(Environment.SpecialFolder.Windows) + @"\Resources\Themes\ClassicTheme.themepack";
            //WriteFileToCurrentDirectory("ClassicTheme.theme", TabletConfigurator.Resources.ClassicTheme);
            if(File.Exists(ThemePath))
            {
                File.Delete(ThemePath);
            }
            if(File.Exists(ThemePath))
            {
                throw new Exception("The file '" + ThemePath + "' exists and can not be deleted. You can try to delete it manually.");
            }
            using (BinaryWriter sw = new BinaryWriter(new FileStream(ThemePath, FileMode.OpenOrCreate)))
            {
                sw.Write(TabletConfigurator.Resources.ClassicTheme);
                sw.Flush();
                sw.Close();
            }

            if(!File.Exists(ThemePath))
            {
                throw new Exception("The resource theme file could not be extracted");
            }

            //Set the theme file as like a user would have clicked it
            Boolean bTimedOut = false;
            String ThemeOutput = 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 + "\"", ref bTimedOut);

            System.Threading.Thread.Sleep(3000);
            //Wait for the theme to be set
            IntPtr hWndTheming = FindWindow("CabinetWClass", null);
            SendMessage(hWndTheming, (uint)WM_CLOSE, 0, 0);

            //using (Bitmap bm = CaptureScreenShot())
            //{
            //    Boolean PixelIsGray = true;
            //    while (PixelIsGray)
            //    {
            //        System.Drawing.Color pixel = bm.GetPixel(0, 0)
            //    }
            //}

        }
        catch(Exception ex)
        {
            ShowError("An exception occured while setting the theme: " + ex.Message);
            return false;
        }
        return true;
    }

Я знаю, что это старый билет, но кто-то спросил меня, как это сделать сегодня. Итак, начиная с поста Майка выше, я очистил все, добавил комментарии и опубликую полный код приложения консоли 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
    }
}





themes