Как программно изменить цвет рамки Windows 7 Aero / Window?

Я думаю о создании программы, которая изменяла бы цвет Windows 7 Aero в зависимости от уровня заряда батареи. Я новичок в C # и хотел бы знать, как программно изменить Windows 7 Aero.

У меня есть этот код

[DllImport("dwmapi.dll", EntryPoint = "#127", PreserveSig = false)]
    public static extern void DwmGetColorizationParameters(out WDM_COLORIZATION_PARAMS                   parameters);

[DllImport("dwmapi.dll", EntryPoint = "#131", PreserveSig = false)]
public static extern void DwmSetColorizationParameters(WDM_COLORIZATION_PARAMS parameters, uint uUnknown);

public struct WDM_COLORIZATION_PARAMS {
    public uint Color1;
    public uint Color2;
    public uint Intensity;
    public uint Unknown1;
    public uint Unknown2;
    public uint Unknown3;
    public uint Opaque;
}

Хотя, я не знаю, как им пользоваться и ставить нестандартный цвет.


person Trontor    schedule 23.07.2013    source источник


Ответы (2)


Для этого нет задокументированного API. Это полностью сделано намеренно: этот параметр предназначен для изменения пользователем, а не приложениями. И есть встроенный апплет, который пользователь может использовать для этого: панель управления Personalize.

Но, как и в коде, на который вы намекаете, существует недокументированный API, который вы можете использовать - DwmSetColorizationParameters. Вам просто нужно тщательно проверить, работает ли ваш код во всех целевых операционных системах, и знать, что он может выйти из строя с любыми новыми версиями Windows и / или любыми обновлениями текущей версии Windows.

Я знаю, что раньше он работал в Windows 7, но я не тестировал его со всеми последними пакетами обновлений и другими обновлениями, и я не знаю, работает ли он в Windows 8. Это все, что вам нужно проверить. Использование недокументированных API - это большая работа.

Но тебе повезло. Кто-то другой уже сделал для вас реверс-инжиниринг. (И, вероятно, другие люди тоже, например человек, написавший код, который вы показываете в своем вопросе. Было бы неплохо отдать им должное. Возможно, это было этот парень?)

Вот как вы это используете:

using System;
using System.Drawing;
using System.Globalization;
using System.Runtime.InteropServices;

class DwmManager
{
   private struct DWM_COLORIZATION_PARAMS
   {
      public uint clrColor;
      public uint clrAfterGlow;
      public uint nIntensity;
      public uint clrAfterGlowBalance;
      public uint clrBlurBalance;
      public uint clrGlassReflectionIntensity;
      public bool fOpaque;
   }

   [DllImport("dwmapi.dll", EntryPoint = "#127", PreserveSig = false)]
   private static extern void DwmGetColorizationParameters(out DWM_COLORIZATION_PARAMS parameters);

   [DllImport("dwmapi.dll", EntryPoint = "#131", PreserveSig = false)]
   private static extern void DwmSetColorizationParameters(ref DWM_COLORIZATION_PARAMS parameters,
                                                           bool unknown);

   // Helper method to convert from a Win32 BGRA-format color to a .NET color.
   private static Color BgraToColor(uint color)
   {
      return Color.FromArgb(Int32.Parse(color.ToString("X"), NumberStyles.HexNumber));
   }

   // Helper method to convert from a .NET color to a Win32 BGRA-format color.
   private static uint ColorToBgra(Color color)
   {
      return (uint)(color.B | (color.G << 8) | (color.R << 16) | (color.A << 24));
   }

   // Gets or sets the current color used for DWM glass, based on the user's color scheme.
   public static Color ColorizationColor
   {
      get
      {
         // Call the DwmGetColorizationParameters function to fill in our structure.
         DWM_COLORIZATION_PARAMS parameters;
         DwmGetColorizationParameters(out parameters);

         // Convert the colorization color to a .NET color and return it.
         return BgraToColor(parameters.clrColor);
      }
      set
      {
         // Retrieve the current colorization parameters, just like we did above.
         DWM_COLORIZATION_PARAMS parameters;
         DwmGetColorizationParameters(out parameters);

         // Then modify the colorization color.
         // Note that the other parameters are left untouched, so they will stay the same.
         // You can also modify these; that is left as an exercise.
         parameters.clrColor = ColorToBgra(value);

         // Call the DwmSetColorizationParameters to make the change take effect.
         DwmSetColorizationParameters(ref parameters, false);
      }
   }
}

После того, как вы добавили этот класс в свой проект, вы взаимодействуете с ним через свойство ColorizationColor. Как говорится в комментариях, структура DWM_COLORIZATION_PARAMS дает вам много дополнительной информации. Вы можете добавить свойства для получения / установки каждого из этих дополнительных параметров, если хотите. Хотя потребуется немного поэкспериментировать, чтобы точно выяснить, что они делают.

Обратите внимание, что вам также необходимо убедиться, что композиция DWM поддерживается и включена операционной системой хоста перед запуском любой из этих функций. (В противном случае атрибут PreserveSig обеспечит создание исключения.) Это довольно очевидно, но в любом случае стоит упомянуть. Для этого вам также понадобится эта функция:

[DllImport("dwmapi.dll")]
private static extern int DwmIsCompositionEnabled(ref bool pfEnabled);
person Cody Gray    schedule 23.07.2013
comment
Ух ты. Спасибо за это. Я проверю это позже, я вернусь к вам. Большое спасибо. - person Trontor; 24.07.2013
comment
Работает безупречно! Я просто не знал, что структура используется в виде: DWM_COLORIZATION_PARAMS dwm = new DWM_COLORIZATION_PARAMS (); - person Trontor; 24.07.2013
comment
@Trontor Конечно. В C # вы создаете новый объект одинаково, будь то класс или структура. Все члены структуры инициализируются значениями по умолчанию, которые для числовых типов, таких как uint, равны 0. Но поскольку вы собираетесь передать ссылку на него функции DwmGetColorizationParameters, чтобы ее члены были заполнены, это на самом деле не имеет значения. :-) - person Cody Gray; 24.07.2013

Возможно, вы могли бы связаться с разработчиком этого небольшого приложения. Спросите, как он это сделал ... я не уверен, что он использовал C# для этого. Но попробовать стоит.

Это мой последний поиск, я не нашел ничего полезного, так что ...

person DeMama    schedule 23.07.2013
comment
Это хороший учебник, но он не совсем полезен для кого-то вроде меня, так как у меня нет опыта работы с C ++, поэтому тег c #. - person Trontor; 23.07.2013
comment
Вы правы, я думала, это для C#, проверьте мою отредактированную ссылку. - person DeMama; 23.07.2013
comment
Новая ссылка объясняет, как включить ‹aero› в приложении, а не изменять цвет окна. - person Trontor; 23.07.2013
comment
Это моя последняя правка, кроме этого я ничего не нашел. Удачи. - person DeMama; 23.07.2013
comment
Спасибо за вашу помощь! - person Trontor; 23.07.2013
comment
Также есть этот маленький драгоценный камень, написанный на C # и с открытым исходным кодом. Я сам не смотрел исходный код, но полагаю, что он содержит необходимый код. - person Cody Gray; 23.07.2013
comment
@CodyGray Я не вижу исходного кода, только некоторые файлы .xaml. - person Trontor; 24.07.2013
comment
Хм, да, я уже сталкивался с этим раньше в проектах CodePlex. Вам необходимо загрузить исходный код в виде ZIP-файла. Я не знаю, почему он недоступен на очевидной вкладке «Исходный код». - person Cody Gray; 24.07.2013
comment
Ничего себе, я тоже наткнулся на AURA, но не нашел того файла zip для загрузки ›.‹ Как глупо! Спасибо! - person Trontor; 24.07.2013