Custom Color Palette in Visual Studio Color Property Editor
Asked Answered
N

2

9

Within the Visual Studio Designer, under the properties window you are able to select the ForeColor, BackColor etc using color picker. When you want to pick a color, a color picker comes up with the tabs 'Custom, Web, System'. If you select custom, then you are able to add a new color to the picker, but only the bottom 2 rows are changeable, and the changes don't persist across controls. So if you add a color to the palette, when you select another control and want to change for example BackColor your previous added color is not there.

Is there a way to create and import a custom set of colors into the designer's color-picker control?

Note: This question isn't asking about VS themes, or if colors can be implemented as a class in the code-behind. I'm after a way to tailor the designer.

Nobody answered 7/3, 2016 at 9:33 Comment(0)
D
14

The editor that helps you to pick color in visual studio is ColorEditor which doesn't persists custom colors across different controls. To solve the problem, you should:

  • Create a custom UITypeEditor based on ColorEditor
  • Register the editor for type Color at visual studio startup

Here is a detailed answer including codes which I used to solve the problem.

Create CustomColorEditor

ColorEditor uses a private ColorUI class to show a private ColorPalette control. The palette uses an array of colors to show custom colors.

To create CustomColorEditor I derived from ColorEditor and using reflection, found those members and filled the array using a static array of some colors to show at first load. Then after closing the editor, I get custom colors from the editor and put them in the static array and initialize the color editor using this static array at next load. This way custom colors are shared between all instances of my CustomColorEditor.

Show CustomColorEditor instead of default ColorEditor

To show an ui type editor for all properties of a specific type, you should add an Editor attribute to the type. But since Color is not my type, how could I add Editor attribute to it?

TypeDescriptor.AddAttributes helped me to register the editor for Color type.

Where should I run the code to register the attribute? Surely at visual studio run-time!

To do so, I created a Visual Studio Package project and put the registration code at Initialize method of package. I also added ProvideAutoLoad attribute to the package class to make it auto load when I open a solution.

Then I installed the package.

Then I put the dll in GAC using gacutil.exe /i "path to dll". Instead of GAC also can put the dll in Visual Studio near devenv.exe because the visual stusio run-time will use it to show my custom color editor for all color properties.

Conclusion

After performing above tasks, I opened a new visual studio instance and in my Windows Forms project, I see my custom color editor shown for colors. The initial colors which I set displayed. Also the color editor persisted custom colors even between different forms!

I shared the codes here. You can use the idea and codes to enhance the editor. You can provide your custom colors to show in editor at start. You even can add another tab to the editor. Here is my codes:

Code for Color Editor

class CustomColorEditor : ColorEditor
{
    private static Color[] Colors;
    static CustomColorEditor()
    {
        Colors = new Color[]{
            Color.Red, Color.Green, Color.Blue, Color.White, 
            Color.White, Color.White, Color.White, Color.White, 
            Color.White, Color.White, Color.White, Color.White, 
            Color.White, Color.White, Color.White, Color.White, 
        };
    }
    public override object EditValue(ITypeDescriptorContext context, System.IServiceProvider provider, object value)
    {
        var colorEditorObject = this;
        Type colorUiType = typeof(ColorEditor).GetNestedType("ColorUI", BindingFlags.NonPublic);
        var colorUiConstructor = colorUiType.GetConstructors()[0];
        var colorUiField = typeof(ColorEditor).GetField("colorUI", BindingFlags.Instance | BindingFlags.NonPublic);
        var colorUiObject = colorUiConstructor.Invoke(new[] { colorEditorObject });
        colorUiField.SetValue(colorEditorObject, colorUiObject);
        var palField = colorUiObject.GetType().GetField("pal", BindingFlags.Instance | BindingFlags.NonPublic);
        var palObject = palField.GetValue(colorUiObject);
        var palCustomColorsField = palObject.GetType().GetField("customColors", BindingFlags.Instance | BindingFlags.NonPublic);
        palCustomColorsField.SetValue(palObject, Colors);
        var selectedValue = base.EditValue(context, provider, value);
        Colors = palCustomColorsField.GetValue(palObject) as Color[];
        return selectedValue;
    }
}

Code for Package

[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)]
[Guid(GuidList.guidVSPackage1PkgString)]
[ProvideAutoLoad(Microsoft.VisualStudio.Shell.Interop.UIContextGuids80.SolutionExists)]
public sealed class VSPackage1Package : Package
{
    public VSPackage1Package() { }
    protected override void Initialize()
    {
        base.Initialize();
        TypeDescriptor.AddAttributes(typeof(Color), new EditorAttribute(typeof(CustomColorEditor), typeof(UITypeEditor)));
    }
}

Result

This would be the result in Visual Studio property window. Look at those Red, Green, Blue at the bottom of dialog which we added:

enter image description here

Dextro answered 19/3, 2016 at 1:59 Comment(3)
I know, my question comes six years later... Βut how can we add a new tab with custom colors? You wrote we can! I have searched "all over" the internet to find a solution but with no luck. I have also make a question about it ( https://mcmap.net/q/1314149/-how-can-i-override-colorui-class-of-coloreditor-class-and-add-a-new-tab-with-custom-colors/6336312 ).Rump
@SimosSigma I posted an answer for the linked question.Dextro
@Reze Aghaei Thank you so much!!! I just had a quick glance to your answer and it looks exactly like what I want to do. I'll study it later, with clearer mind, because right now every cell in my brain is burned :)) and I'll mark it as correct answer. Thank you for your time!!!Rump
D
0

I know it's been quite some time...

You can use MergedDictionaries and reference a Resource Dictionary in your App.xml file.

That will put the colors you define in the palette but you would have to include the same Resource Dictionary and reference it in every App.xaml for every application you use, which, in my opinion, is good because sometimes you have to use custom colors for different applications.Custom Color Palette

Something like that

Durham answered 22/9, 2017 at 21:35 Comment(1)
The question is tagged Windows Forms.Pich

© 2022 - 2024 — McMap. All rights reserved.