プログラムで現在のWindowsテーマを変更するにはどうすればよいですか?



1 Answers

確かに、現在のテーマをプログラム的に変更したいという理由があります。 たとえば、自動化されたテストツールでは、アプリケーションが正しく動作するかどうかを確認するために、さまざまなテーマを切り替える必要があります。

ユーザーは、Windwos Explorerで.themeファイルをダブルクリックし、 .themeするコントロールパネルのアプレットを閉じてテーマを変更できます。 コードから同じことを簡単に行うことができます。 以下の手順は私のためにうまく動作します。 私はWindows 7でテストしました。

  1. SHGetKnownFolderPath()を使用して、ユーザーの「ローカルAppData」フォルダを取得します。 テーマファイルは、 Microsoft\Windows\Themesサブフォルダに保存されます。 そこに保存されているテーマファイルは直接適用されますが、他の場所に保存されているテーマファイルは実行時に複製されます。 したがって、そのフォルダのファイルのみを使用するのが最善です。
  2. ShellExecute()を使用して、手順1で.theme.themeファイルを実行します。
  3. テーマが適用されるのを待ちます。 私は単に私のアプリを2秒間寝かせるだけです。
  4. テーマが適用されたときにポップアップしたコントロールパネルウィンドウのハンドルを取得するにはFindWindow('CabinetWClass', 'Personalization')を呼び出しFindWindow('CabinetWClass', 'Personalization') 。 「パーソナライゼーション」キャプションは、英語以外のバージョンのWindowsでは異なる可能性があります。
  5. PostMessage(HWND, WM_CLOSE, 0, 0)を呼び出して、コントロールパネルのウィンドウを閉じます。

これは非常にエレガントな解決策ではありませんが、それは仕事です。

Question

ユーザーがAeroとWindows Classic(1)の間で現在のユーザーテーマを切り替えることを許可します。 私はこれをプログラム的に行うことができる方法はありますか?

私は "表示のプロパティ"をポップアップしたくない、と私はレジストリを変更するだけの疑いがあります。 (変更を有効にするには、ログアウトしてログインする必要があります)。

アプリケーションスキニング( Codejockライブラリを使用)も機能しません。

これを行う方法はありますか?

アプリケーションは、 RDPを介してWindows Server 2008上でホスト/実行されます

(1)問題のアプリケーションはホストされた「リモートアプリケーション」であり、ユーザーはデスクトップに合わせて表示されたアプリケーションの外観を変更できるようにしたい。




"Jan Goyvaerts"の投稿に加えて、私はPostMessageの代わりにSendMessageを使用します。 違いは、SendMessageはコマンドがウィンドウによって取り込まれるのを待つことです。 SendMessagesで、テーマダイアログが閉じられていることを意味します。

だから、もしあなたが "キャンベル"によって提案された怪奇な(しかし有名な)rundll32.exeメソッドでそれを始めるならば。 WM_CLOSEを送信する前に、1秒待つ必要があります。 それ以外の場合、テーマは設定されず、アプリケーションはすぐに終了します。

以下のコードスニペットは、リソース(themepack)からファイルを抽出します。 次に、rundll32.exeでdesk.cplを実行し、3秒待ってから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;
    }



Related