如何更改PropertyGrid控件的边框颜色(或去掉边框)?

7

我有一个标准的WinForms 2.0 PropertyGrid控件,我正在寻找一种方法来改变控件的边框颜色或完全删除边框。

enter image description here

我知道LineColor属性,但它只能改变单元格之间的内部边框。
此外,我使用ILSpy查看了PropertyGrid控件的源代码,但仍然找不到有意义的信息。
我的问题是:
如何移除PropertyGrid控件的外边框或更改外边框的颜色?
更新2012-05-04 - 解决方案(也称为“hack”):
基于Jamie的答案,我组装了一个可行的解决方案(您可以从这里下载)。

enter image description here

这个想法是将属性网格放在一个面板内,并让面板裁剪控件。
采用这种方法,我将裁剪面板置于另一个面板中,该面板具有“1”(或您希望边框为多少)的填充,并给该面板设置了一个作为边框颜色的“BackColor”(例如绿色)。
将属性网格的“Anchor”设置为“左、右、上、下”,将裁剪面板的“Dock”设置为“Full”。

enter image description here

这符合我的需求。尽管它消耗了我本来希望节省下来的两个面板的资源,但我仍然认为这是一种巧妙的方法。
5个回答

2

这里是我项目的代码。

PropertyGrid有两个控件需要处理。
+ doccomment是文档帮助。
+ gridView用于显示属性值。

这些控件使用ControlDark颜色绘制边框矩形。

我们需要重新绘制矩形,使用HelpBackColor和LineColor使视图更清晰。

    namespace Bravo.Bravo7.UI
    {
        public class MyPropertyGrid : PropertyGrid
        {
            public class SnappableControl : NativeWindow
            {
                private Control _parent;
                private MyPropertyGrid _ownerGrid;

                public SnappableControl(Control parent, MyPropertyGrid ownerGrid)
                {
                    _parent = parent;
                    _parent.HandleCreated += _parent_HandleCreated;
                    _parent.HandleDestroyed += _owner_HandleDestroyed;

                    _ownerGrid = ownerGrid;
                }

                protected override void WndProc(ref Message m)
                {
                    base.WndProc(ref m);

                    switch (m.Msg)
                    {
                        case (int)NativeMethods.WM_NCPAINT:
                        case (int)NativeMethods.WM_PAINT:

                            using (var g = _parent.CreateGraphics())
                            {
                                using (var pen = new Pen(_ownerGrid.HelpBackColor))
                                {
                                    var clientRectangle = _parent.ClientRectangle;
                                    clientRectangle.Width--;
                                    clientRectangle.Height--;
                                    g.DrawRectangle(pen, clientRectangle);
                                }
                            }

                            break;
                    }
                }

                void _owner_HandleDestroyed(object sender, EventArgs e)
                {
                    ReleaseHandle();
                }

                void _parent_HandleCreated(object sender, EventArgs e)
                {
                    AssignHandle(_parent.Handle);
                }
            }

            public class PropertyGridView : NativeWindow
            {
                private Control _parent;
                private MyPropertyGrid _ownerGrid;

                public PropertyGridView(Control parent, MyPropertyGrid ownerGrid)
                {
                    _parent = parent;
                    _parent.HandleCreated += _owner_HandleCreated;
                    _parent.HandleDestroyed += _owner_HandleDestroyed;

                    _ownerGrid = ownerGrid;
                }

                protected override void WndProc(ref Message m)
                {
                    base.WndProc(ref m);

                    switch (m.Msg)
                    {
                        case (int)NativeMethods.WM_NCPAINT:
                        case (int)NativeMethods.WM_PAINT:

                            using (var g = _parent.CreateGraphics())
                            {
                                using (var pen = new Pen(_ownerGrid.LineColor))
                                {
                                    g.DrawRectangle(pen, 0, 0, _parent.Width - 1, _parent.Height - 1);
                                }
                            }

                            break;
                    }
                }

                void _owner_HandleDestroyed(object sender, EventArgs e)
                {
                    ReleaseHandle();
                }

                void _owner_HandleCreated(object sender, EventArgs e)
                {
                    AssignHandle(_parent.Handle);
                }
            }

            public class MyToolStripRenderer : ToolStripSystemRenderer
            {
                protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
                {
                    //base.OnRenderToolStripBorder(e);
                }
            }

            public MyPropertyGrid()
            {
                base.LineColor = SystemColors.Control;
                base.ViewBackColor = Color.FromArgb(246, 246, 246);

                base.DrawFlatToolbar = true;
                base.ToolStripRenderer = new MyToolStripRenderer();

                var docDocument = typeof(PropertyGrid)
                    .GetField("doccomment", BindingFlags.NonPublic | BindingFlags.Instance)
                    .GetValue(this) as Control;

                new SnappableControl(docDocument, this);

                var gridView = typeof(PropertyGrid)
                    .GetField("gridView", BindingFlags.NonPublic | BindingFlags.Instance)
                    .GetValue(this) as Control;

                new PropertyGridView(gridView, this);
            }

        }

    }

Screen Shot


1
Explain the context as well - Vinoth Krishnan

2
这是另一种选择,因为我的第一个答案似乎不适用于这个特定的控件。这是一个不太正规的技巧,但应该有效:
在您的窗口或对话框中放置一个Panel控件,大小为100H x 300V。将PropertyGrid控件放置在面板内,位置为-1,-1,大小为102,302。

呵呵,我以前尝试过,但没成功。我会再试一次,以防万一自己做错了什么。 - Uwe Keim
@Jamie,它起作用了,感谢您的建议!我会使用您的答案更新我的问题。 - Uwe Keim
1
小心,由于自动窗体缩放,当窗口大小调整时,此代码可能会出现问题。你真的想在面板的Resize事件处理程序中编写代码,以确保PropertyGrid始终位于正确位置。 - Hans Passant

1
你需要一些互操作性来完成这件事:
[DllImport("User32", CharSet=CharSet.Auto)]
private static extern int SetWindowLong(IntPtr hWnd, int Index, int Value);
[DllImport("User32", CharSet=CharSet.Auto)]
private static extern int GetWindowLong(IntPtr hWnd, int Index);

int GWL_STYLE = -16;
int WS_BORDER = 0x00800000;
IntPtr hWnd = yourPropertyGrid.Handle;

int style = GetWindowLong(hWnd, GWL_STYLE);
style = style & ~WS_BORDER;
SetWindowLong(hWnd, GWL_STYLE, style);

谢谢,@Jamie 我尝试了这个,但不幸的是样式似乎已经省略了,因此删除它并没有改变。您尝试过您的解决方案并且它工作了吗? - Uwe Keim
1
嗨Uwe,不,我还没有尝试过,这只是删除本地Windows控件边框的标准方法。看起来propertygrid没有遵循这个标准,所以我认为你不能用这种方式做到这一点。 - user694833

0

这段代码可以工作。

private void SetHelpBoderColor(bool showBorder)
{
    if (showBorder)
    {
        //Set Default ViewBackColor
        PropertyInfo viewBackColor = this.propertyGrid.GetType().GetProperty("ViewBorderColor");
        if (viewBackColor != null)
            viewBackColor.SetValue(this.propertyGrid, SystemColors.ControlDark, null);

        //Set Default HelpBorderColor
        PropertyInfo helpBorderColor = this.propertyGrid.GetType().GetProperty("HelpBorderColor");
        if (helpBorderColor != null)
            helpBorderColor.SetValue(this.propertyGrid, SystemColors.ControlDark, null);

    }
    else
    {
        //Set ViewBackColor
        PropertyInfo viewBackColor = this.propertyGrid.GetType().GetProperty("ViewBorderColor");
        if (viewBackColor != null)
            viewBackColor.SetValue(this.propertyGrid, SystemColors.Control, null);

        //Set HelpBorderColor
        PropertyInfo helpBorderColor = this.propertyGrid.GetType().GetProperty("HelpBorderColor");
        if (helpBorderColor != null)
            helpBorderColor.SetValue(this.propertyGrid, SystemColors.Control, null);
    }

    if (DesignMode)
    {
        Parent.Refresh();
    }
}

是的,那段代码可以在PropertyGrid中显示或隐藏ViewBoder和HelpBoder。 - TrungNV

0
一个快速而直观的解决方案是创建一个“父面板”和一个“子面板”,如下图所示:

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接