none
フォームのBackColor選択した際のコンボボックスに独自の色を追加したい。 RRS feed

  • 質問

  • Windows 10 x64

    VisualStudio2019

    .Net 4.8

    上記の環境にて、Formが持つBackColorのプロパティにデザイナ上でユーザー独自の色を追加するには

    どうしたらよいでしょうか?

    赤枠の箇所もしくは、他でも良いです。

    恐らくVB.NETも同様とは思いますが、違うようであればVB.NETのSampleも欲しいです。

    追加する色としては、RGB(1,2,3)のように名前のついていない色を、固有色1みたいな感じで設定し

    画面ごとに1,2,3を入力しないようにしたいという感じです。

    よろしくお願いします。

    2020年9月23日 4:48

回答

  • using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : FormBase // Formを継承していないとデザイナ上では反映できない
        {
            public Form1()
            {
                InitializeComponent();
            }
        }
    
    
        public class FormBase : System.Windows.Forms.Form
        {
            //PropertyGridのドロップダウン時のエディタを変更する
            [Editor(typeof(ColorEditorEx), typeof(System.Drawing.Design.UITypeEditor))]
            [ColorEditorColors(0xff010203, 0xffff0000)]
            public override Color BackColor
            {
                get { return base.BackColor; }
                set { base.BackColor = value; }
            }
        }
    
        class ColorEditorColorsAttribute : Attribute
        {
            public ColorEditorColorsAttribute(params uint[] colors)
            {
                List<Color> list = new List<Color>();
                foreach (uint ui in colors)
                {
                    int i = unchecked((int)ui);
                    list.Add(Color.FromArgb(i));
                }
                Colors = new System.Collections.ObjectModel.ReadOnlyCollection<Color>(list);
            }
            public IList<Color> Colors { get; }
        }
    
        public class ColorEditorEx : System.Drawing.Design.ColorEditor //System.Drawing.Design.dll
        {
            public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
            {
                var item=(System.Windows.Forms.GridItem)context;
                var colors=item.PropertyDescriptor.Attributes.OfType<ColorEditorColorsAttribute>().FirstOrDefault()?.Colors;
    
                var editor = (System.Windows.Forms.Design.IWindowsFormsEditorService)provider.GetService(typeof(System.Windows.Forms.Design.IWindowsFormsEditorService));
    
                var threadContext = System.Threading.SynchronizationContext.Current;
                if (threadContext == null)
                {
                    threadContext = new System.Threading.SynchronizationContext();
                    System.Threading.SynchronizationContext.SetSynchronizationContext(threadContext);
    
                }
                TabControl tab = null;
                TabPage page = new TabPage();
                page.Text = "てすと";
                ListBox listBox = new ListBox();
                listBox.SelectedIndexChanged += (s, e) => editor.CloseDropDown();
                if (colors != null)
                {
                    foreach (Color c in colors)
                    {
                        listBox.Items.Add(c);
                    }
                }
                page.Controls.Add(listBox);
    
                threadContext.Post((o) =>
                {
                    var list = Win32API.GetCurrentThreadWindows();
                    foreach (IntPtr hwnd in list)
                    {
                        IntPtr owner = Win32API.GetOwnerWindow(hwnd);
                        if (owner != IntPtr.Zero)
                        {
                            var control = System.Windows.Forms.Control.FromChildHandle(owner);
                            if (control != null)
                            {
                                var children = Win32API.EnumChildWindows(hwnd);
                                var controls = children.Select(h => System.Windows.Forms.Control.FromHandle(h)).OfType<Control>().ToArray();
                                if (controls.Count() > 0)
                                {
                                    tab = controls.OfType<TabControl>().FirstOrDefault();
                                    if (tab != null)
                                    {
                                        tab.TabPages.Add(page);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }, null);
    
                var ret = base.EditValue(context, provider, value);
                if (tab != null && page != null)
                {
                    if (tab.SelectedTab == page)
                    {
                        ret = (Color)listBox.SelectedItem;
    
                    }
                    tab.TabPages.Remove(page);
                }
    
                return ret;
            }
        }
    }
    namespace WindowsFormsApp1
    {
        using System.Runtime.InteropServices;
        class Win32API
        {
            private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    
            [DllImport("kernel32.dll")]
            private static extern uint GetCurrentThreadId();
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
    
            public static IntPtr GetOwnerWindow(IntPtr hwnd)
            {
                return GetWindow(hwnd, 4);
            }
    
            public static List<IntPtr> GetCurrentThreadWindows()
            {
                List<IntPtr> list = new List<IntPtr>();
                var id = GetCurrentThreadId();
                EnumWindows((h, p) =>
                {
                    uint pid;
                    uint tid;
                    tid = GetWindowThreadProcessId(h, out pid);
                    if (tid == id)
                    {
                        list.Add(h);
                    }
                    return true;
                }, IntPtr.Zero);
                return list;
            }
    
            public static List<IntPtr> EnumChildWindows(IntPtr hwnd)
            {
                List<IntPtr> list = new List<IntPtr>();
                EnumChildWindows(hwnd, (h, p) =>
                {
                    list.Add(h);
                    return true;
                }, IntPtr.Zero);
                return list;
            }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク mogja 2020年9月25日 12:38
    2020年9月23日 22:54

すべての返信

  • using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp1
    {
        public partial class Form1 : FormBase // Formを継承していないとデザイナ上では反映できない
        {
            public Form1()
            {
                InitializeComponent();
            }
        }
    
    
        public class FormBase : System.Windows.Forms.Form
        {
            //PropertyGridのドロップダウン時のエディタを変更する
            [Editor(typeof(ColorEditorEx), typeof(System.Drawing.Design.UITypeEditor))]
            [ColorEditorColors(0xff010203, 0xffff0000)]
            public override Color BackColor
            {
                get { return base.BackColor; }
                set { base.BackColor = value; }
            }
        }
    
        class ColorEditorColorsAttribute : Attribute
        {
            public ColorEditorColorsAttribute(params uint[] colors)
            {
                List<Color> list = new List<Color>();
                foreach (uint ui in colors)
                {
                    int i = unchecked((int)ui);
                    list.Add(Color.FromArgb(i));
                }
                Colors = new System.Collections.ObjectModel.ReadOnlyCollection<Color>(list);
            }
            public IList<Color> Colors { get; }
        }
    
        public class ColorEditorEx : System.Drawing.Design.ColorEditor //System.Drawing.Design.dll
        {
            public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
            {
                var item=(System.Windows.Forms.GridItem)context;
                var colors=item.PropertyDescriptor.Attributes.OfType<ColorEditorColorsAttribute>().FirstOrDefault()?.Colors;
    
                var editor = (System.Windows.Forms.Design.IWindowsFormsEditorService)provider.GetService(typeof(System.Windows.Forms.Design.IWindowsFormsEditorService));
    
                var threadContext = System.Threading.SynchronizationContext.Current;
                if (threadContext == null)
                {
                    threadContext = new System.Threading.SynchronizationContext();
                    System.Threading.SynchronizationContext.SetSynchronizationContext(threadContext);
    
                }
                TabControl tab = null;
                TabPage page = new TabPage();
                page.Text = "てすと";
                ListBox listBox = new ListBox();
                listBox.SelectedIndexChanged += (s, e) => editor.CloseDropDown();
                if (colors != null)
                {
                    foreach (Color c in colors)
                    {
                        listBox.Items.Add(c);
                    }
                }
                page.Controls.Add(listBox);
    
                threadContext.Post((o) =>
                {
                    var list = Win32API.GetCurrentThreadWindows();
                    foreach (IntPtr hwnd in list)
                    {
                        IntPtr owner = Win32API.GetOwnerWindow(hwnd);
                        if (owner != IntPtr.Zero)
                        {
                            var control = System.Windows.Forms.Control.FromChildHandle(owner);
                            if (control != null)
                            {
                                var children = Win32API.EnumChildWindows(hwnd);
                                var controls = children.Select(h => System.Windows.Forms.Control.FromHandle(h)).OfType<Control>().ToArray();
                                if (controls.Count() > 0)
                                {
                                    tab = controls.OfType<TabControl>().FirstOrDefault();
                                    if (tab != null)
                                    {
                                        tab.TabPages.Add(page);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }, null);
    
                var ret = base.EditValue(context, provider, value);
                if (tab != null && page != null)
                {
                    if (tab.SelectedTab == page)
                    {
                        ret = (Color)listBox.SelectedItem;
    
                    }
                    tab.TabPages.Remove(page);
                }
    
                return ret;
            }
        }
    }
    namespace WindowsFormsApp1
    {
        using System.Runtime.InteropServices;
        class Win32API
        {
            private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            private static extern bool EnumChildWindows(IntPtr hwndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
    
            [DllImport("kernel32.dll")]
            private static extern uint GetCurrentThreadId();
    
            [DllImport("user32.dll", SetLastError = true)]
            private static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);
    
            public static IntPtr GetOwnerWindow(IntPtr hwnd)
            {
                return GetWindow(hwnd, 4);
            }
    
            public static List<IntPtr> GetCurrentThreadWindows()
            {
                List<IntPtr> list = new List<IntPtr>();
                var id = GetCurrentThreadId();
                EnumWindows((h, p) =>
                {
                    uint pid;
                    uint tid;
                    tid = GetWindowThreadProcessId(h, out pid);
                    if (tid == id)
                    {
                        list.Add(h);
                    }
                    return true;
                }, IntPtr.Zero);
                return list;
            }
    
            public static List<IntPtr> EnumChildWindows(IntPtr hwnd)
            {
                List<IntPtr> list = new List<IntPtr>();
                EnumChildWindows(hwnd, (h, p) =>
                {
                    list.Add(h);
                    return true;
                }, IntPtr.Zero);
                return list;
            }
        }
    }

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    • 回答としてマーク mogja 2020年9月25日 12:38
    2020年9月23日 22:54
  • mogjaさん、こんにちは。フォーラムオペレーターのKumoです。 
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    ご質問いただいた件ですが、その後いかがでしょうか。
    gekkaさんから寄せられた投稿はお役に立ちましたか。

    参考になった投稿には [回答としてマーク] をお願い致します。

    設定いただくことで、
    他のユーザーもお役に立つ回答を見つけやすくなります。

    お手数ですが、ご協力の程どうかよろしくお願いいたします。

    MSDN/ TechNet Community Support Kumo ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、 ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2020年9月25日 7:35
    モデレータ
  • ありがとうございます。忙しくて確認出来ていませんが結構ゴリゴリな実装をする必要があるのですね。

    来週すぎ当たりちょっとサンプル組んでみていい感じにカスタマイズできるか確かめてみます!

    2020年9月25日 12:39