6

I am thinking of making a program that would change the Windows 7 aero color according to the battery level. I am fairly new to c# and I would like to know how to change the Windows 7 Aero programmatically

I have this code

[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;
}

Although, I do not know how to use it and set a custom color.

Trontor
  • 417
  • 1
  • 7
  • 20

2 Answers2

10

There is no documented API for this. That's entirely by design: this setting is intended to be changed by the user, not by applications. And there's a built-in applet for the user to use to do this: the Personalize control panel.

But like the code that you've got hints at, there is an undocumented API that you can use—DwmSetColorizationParameters. You just need to carefully test that your code works on all targeted operating systems and be aware that it is subject to break with any new versions of Windows and/or any updates to the current version of Windows.

I know that it used to work in Windows 7, but I haven't tested it with all of the latest service packs and other updates, nor do I have any idea if it works in Windows 8. That's all up to you to test. Using undocumented APIs is a lot of work.

You're lucky, though. Someone else has already done the reverse engineering for you. (And probably other people, too, like the person who wrote the code you show in your question. It would be nice to give them credit. Maybe it was this guy?)

Here's how you use it:

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);
      }
   }
}

Once you've got that class added to your project, you interact with it through the ColorizationColor property. Like the comments say, the DWM_COLORIZATION_PARAMS structure gives you a lot more information. You could add properties to get/set each of these additional parameters, if you like. Although it'll take some experimentation to figure out exactly what they do.

Note that you also need to check that DWM composition is supported and enabled by the host operating system before running any of these functions. (Otherwise, the PreserveSig attribute will ensure that an exception is thrown.) This is fairly obvious, but worth mentioning anyway. To do that, you will also need this function:

[DllImport("dwmapi.dll")]
private static extern int DwmIsCompositionEnabled(ref bool pfEnabled);
Community
  • 1
  • 1
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • Wow. Thanks for this. I will check this out later, ill get back to you. Thanks so much. – Trontor Jul 24 '13 at 02:30
  • Works flawlessly! I just didn't know that a struct is used in the form of : DWM_COLORIZATION_PARAMS dwm = new DWM_COLORIZATION_PARAMS(); – Trontor Jul 24 '13 at 11:04
  • 1
    @Trontor Sure. In C#, you create a new object the same way, whether it's a class or a struct. All of the struct members get initialized to their default values, which for numeric types like `uint` is `0`. But since you're about to pass a reference to it to the `DwmGetColorizationParameters` function to have its members filled in, that doesn't really matter. :-) – Cody Gray - on strike Jul 24 '13 at 11:05
1

Maybe you could contact the developer of this small application. Ask how he did it.. i'm not sure he used C# to accomplish this. But it's worth a shot.

This is my final search, I couldn't find anything else usefull so...

DeMama
  • 1,134
  • 3
  • 13
  • 32
  • It is a good tutorial, but not exactly helpful to someone like me, as I have no C++ experience hence the tag c#. – Trontor Jul 23 '13 at 06:26
  • You are right, I thought it was for `C#`, check my edited link. – DeMama Jul 23 '13 at 06:36
  • The new link explains how to enable itself on an application , not change the color of the window. – Trontor Jul 23 '13 at 06:38
  • This is my last edit, i couldn't find anything else than this. Good luck. – DeMama Jul 23 '13 at 07:01
  • There's also [this little gem](http://aura.codeplex.com/), written in C# and open source. I haven't looked at the source code myself, but I imagine it contains the necessary code. – Cody Gray - on strike Jul 23 '13 at 11:25
  • @CodyGray I don't see the source, just some .xaml files. – Trontor Jul 24 '13 at 02:26
  • Hmm yeah, I've ran into that before on CodePlex projects. You have to [*download*](http://aura.codeplex.com/releases/view/64311) the source in a ZIP file. I don't know why it isn't available on the obvious "Source Code" tab. – Cody Gray - on strike Jul 24 '13 at 04:00
  • Wow, I came across AURA aswell, but didn't find that download zip thing >.< Feel so stupid ! Thanks! – Trontor Jul 24 '13 at 11:01