.net شرح - الرسم فوق عناصر التحكم داخل لوحة(C#WinForms)




windows application (9)

أعلم أن هذا السؤال قد تم طرحه أكثر من عدة مرات ، لكني لم أتمكن حتى الآن من إيجاد حل جيد له.

لدي لوحة تحكم أخرى عليها.
أرغب في رسم خط عليه وعلى رأس جميع عناصر التحكم في اللوحة

جئت عبر ثلاثة أنواع من الحلول (لم يعملوا بالطريقة التي أردتها):

  1. الحصول على سطح المكتب DC ورسم على الشاشة.
    سيعتمد ذلك على التطبيقات الأخرى إذا تداخلت في النموذج.

  2. تجاوز لوحة "CreateParams":

=

protected override CreateParams CreateParams {  
  get {  
    CreateParams cp;  
    cp = base.CreateParams;  
    cp.Style &= ~0x04000000; //WS_CLIPSIBLINGS
    cp.Style &= ~0x02000000; //WS_CLIPCHILDREN
    return cp;  
  }  
}           

// ملاحظة لقد حاولت أيضًا تعطيل WS_CLIPSIBLINGS

ثم رسم الخط OnPaint (). ولكن ... بما أن OnPaint الخاص باللوحة يتم استدعاؤه قبل OnPaint من عناصر التحكم فيه ، فإن رسم عناصر التحكم داخل ببساطة يرسم فوق الخط.
لقد رأيت أحدهم يقترح استخدام عامل تصفية رسائل للاستماع إلى marsages WM_PAINT ، واستخدام جهاز توقيت ، ولكن لا أعتقد أن هذا الحل هو "ممارسة جيدة" أو فعالة.
ماذا كنت ستفعل ؟ تقرر أن عناصر التحكم في الداخل قد انتهى الرسم بعد X MS ، وتعيين الموقت إلى X مللي ثانية؟

تعرض لقطة الشاشة هذه اللوحة مع WS_CLIPSIBLINGS و WS_CLIPCHILDREN متوقفة.
تم رسم الخط الأزرق في OnPaint للوحة ، وببساطة يتم رسمه بواسطة مربعات النص والتسمية.
يرسم الخط الأحمر على القمة فقط لأنه لا يتم رسمه من OnPaint الخاص باللوحة (تم رسمه في الواقع نتيجة النقر على زر)

ثالثًا: إنشاء طبقة شفافة والاعتماد على تلك الطبقة.
لقد قمت بإنشاء عنصر تحكم شفاف باستخدام:

protected override CreateParams CreateParams {  
  get {  
    CreateParams cp = base.CreateParams;  
    cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT  
    return cp;  
  }  
}

لا تزال المشكلة تكمن في وضع السيطرة الشفافة على رأس الفريق وجميع ضوابطه.
لقد حاولت جلبها إلى الأمام باستخدام: "BringToFront ()" ، ولكن لا يبدو أنها تساعد.
لقد وضعته في معالج OnPaint () عنصر تحكم الخط.
يجب أن أحاول وضعه في مكان آخر؟
- هذا أيضًا يخلق مشكلة مع وجود عنصر تحكم آخر أعلى اللوحة. (اصطياد الفأرة نقرات الخ ..)

أي مساعدة سيكون موضع تقدير كبير!

** EDIT: الخط الأسود هو عينة مما كنت أحاول القيام به. (تستخدم ويندوز الطلاء لرسمه)


Answers

جعل LineControl جديد: التحكم مثل هذا:

ثم استدعاء BringToFront () بعد InitializeComponent

public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
            this.simpleLine1.BringToFront();
        }
    }



using System;
using System.Windows.Forms;
using System.Drawing;
using System.Collections.Generic;

public class SimpleLine : Control
{
    private Control parentHooked;   
    private List<Control> controlsHooked;

    public enum LineType
    {
        Horizontal,
        Vertical,
        ForwardsDiagonal,
        BackwardsDiagonal
    }

    public event EventHandler AppearanceChanged;
    private LineType appearance;
    public virtual LineType Appearance
    {
        get
        {
            return appearance;
        }
        set
        {
            if (appearance != value)
            {
                this.SuspendLayout();
                switch (appearance)
                {
                    case LineType.Horizontal:
                        if (value == LineType.Vertical)
                        {
                            this.Height = this.Width;
                        }

                        break;
                    case LineType.Vertical:
                        if (value == LineType.Horizontal)
                        {
                            this.Width = this.Height;
                        }
                        break;
                }
                this.ResumeLayout(false);

                appearance = value;
                this.PerformLayout();
                this.Invalidate();
            }
        }
    }
    protected virtual void OnAppearanceChanged(EventArgs e)
    {
        if (AppearanceChanged != null) AppearanceChanged(this, e);
    }

    public event EventHandler LineColorChanged;
    private Color lineColor;
    public virtual Color LineColor
    {
        get
        {
            return lineColor;
        }
        set
        {
            if (lineColor != value)
            {
                lineColor = value;
                this.Invalidate();
            }
        }
    }
    protected virtual void OnLineColorChanged(EventArgs e)
    {
        if (LineColorChanged != null) LineColorChanged(this, e);
    }

    public event EventHandler LineWidthChanged;
    private float lineWidth;
    public virtual float LineWidth
    {
        get
        {
            return lineWidth;
        }
        set
        {
            if (lineWidth != value)
            {
                if (0 >= value)
                {
                    lineWidth = 1;
                }
                lineWidth = value;
                this.PerformLayout();
            }
        }
    }
    protected virtual void OnLineWidthChanged(EventArgs e)
    {
        if (LineWidthChanged != null) LineWidthChanged(this, e);
    }

    public SimpleLine()
    {
        base.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Selectable, false);
        base.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        base.BackColor = Color.Transparent;

        InitializeComponent();

        appearance = LineType.Vertical;
        LineColor = Color.Black;
        LineWidth = 1;
        controlsHooked = new List<Control>();

        this.ParentChanged += new EventHandler(OnSimpleLineParentChanged);
    }

    private void RemoveControl(Control control)
    {
        if (controlsHooked.Contains(control))
        {
            control.Paint -= new PaintEventHandler(OnControlPaint);
            if (control is TextboxX)
            {
                TextboxX text = (TextboxX)control;
                text.DoingAPaint -= new EventHandler(text_DoingAPaint);
            }
            controlsHooked.Remove(control);
        }
    }

    void text_DoingAPaint(object sender, EventArgs e)
    {
        this.Invalidate();
    }

    private void AddControl(Control control)
    {
        if (!controlsHooked.Contains(control))
        {
            control.Paint += new PaintEventHandler(OnControlPaint);
            if (control is TextboxX)
            {
                TextboxX text = (TextboxX)control;
                text.DoingAPaint += new EventHandler(text_DoingAPaint);
            }
            controlsHooked.Add(control);
        }
    }

    private void OnSimpleLineParentChanged(object sender, EventArgs e)
    {
        UnhookParent();

        if (Parent != null)
        {

            foreach (Control c in Parent.Controls)
            {
                AddControl(c);
            }
            Parent.ControlAdded += new ControlEventHandler(OnParentControlAdded);
            Parent.ControlRemoved += new ControlEventHandler(OnParentControlRemoved);
            parentHooked = this.Parent;
        }
    }

    private void UnhookParent()
    {
            if (parentHooked != null)
            {
                foreach (Control c in parentHooked.Controls)
                {
                    RemoveControl(c);
                }
                parentHooked.ControlAdded -= new ControlEventHandler(OnParentControlAdded);
                parentHooked.ControlRemoved -= new ControlEventHandler(OnParentControlRemoved);
                parentHooked = null;
            }
    }

    private void OnParentControlRemoved(object sender, ControlEventArgs e)
    {
        RemoveControl(e.Control);
    }   

    private void OnControlPaint(object sender, PaintEventArgs e)
    {
        int indexa =Parent.Controls.IndexOf(this) , indexb = Parent.Controls.IndexOf((Control)sender);
        //if above invalidate on paint
        if(indexa < indexb)
        {
            Invalidate();
        }
    }

    private void OnParentControlAdded(object sender, ControlEventArgs e)
    {
        AddControl(e.Control);
    }

    private System.ComponentModel.IContainer components = null;
    private void InitializeComponent()
    {
        components = new System.ComponentModel.Container();
    }
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;  // Turn on WS_EX_TRANSPARENT
            return cp;
        }
    }

    protected override void OnLayout(LayoutEventArgs levent)
    {
        switch (this.Appearance)
        {
            case LineType.Horizontal:
                this.Height = (int)LineWidth;
                this.Invalidate();
                break;
            case LineType.Vertical:
                this.Width = (int)LineWidth;
                this.Invalidate();
                break;
        }

        base.OnLayout(levent);
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
        //disable background paint
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        switch (Appearance)
        {
            case LineType.Horizontal:
                DrawHorizontalLine(pe);
                break;
            case LineType.Vertical:
                DrawVerticalLine(pe);
                break;
            case LineType.ForwardsDiagonal:
                DrawFDiagonalLine(pe);
                break;
            case LineType.BackwardsDiagonal:
                DrawBDiagonalLine(pe);
                break;
        }
    }

    private void DrawFDiagonalLine(PaintEventArgs pe)
    {
        using (Pen p = new Pen(this.LineColor, this.LineWidth))
        {
            pe.Graphics.DrawLine(p, this.ClientRectangle.X, this.ClientRectangle.Bottom,
                                    this.ClientRectangle.Right, this.ClientRectangle.Y);
        }
    }

    private void DrawBDiagonalLine(PaintEventArgs pe)
    {
        using (Pen p = new Pen(this.LineColor, this.LineWidth))
        {
            pe.Graphics.DrawLine(p, this.ClientRectangle.X, this.ClientRectangle.Y,
                                    this.ClientRectangle.Right, this.ClientRectangle.Bottom);
        }
    }

    private void DrawHorizontalLine(PaintEventArgs pe)
    {
        int  y = this.ClientRectangle.Height / 2;
        using (Pen p = new Pen(this.LineColor, this.LineWidth))
        {
            pe.Graphics.DrawLine(p, this.ClientRectangle.X, y,
                                    this.ClientRectangle.Width, y);
        }
    }

    private void DrawVerticalLine(PaintEventArgs pe)
    {
        int x = this.ClientRectangle.Width / 2;
        using (Pen p = new Pen(this.LineColor, this.LineWidth))
        {
            pe.Graphics.DrawLine(p,x, this.ClientRectangle.Y,
                                   x, this.ClientRectangle.Height);
        }
    }
}

تحرير: أضيفت دعم قطري

لقد أضفت بعض الدعم لعناصر التحكم التي تعيد الرسم عند الحصول على التركيز.

لن تعمل مربعات النص و comboboxs كما هو بحاجة إلى جعل بنفسك وربط هناك ترسم أوامر مثل:

public class TextboxX : TextBox
{
    public event EventHandler DoingAPaint;
    protected override void WndProc(ref Message m)
    {
        switch ((int)m.Msg)
        {
            case (int)NativeMethods.WindowMessages.WM_PAINT:
            case (int)NativeMethods.WindowMessages.WM_ERASEBKGND:
            case (int)NativeMethods.WindowMessages.WM_NCPAINT:
            case 8465: //not sure what this is WM_COMMAND?
                if(DoingAPaint!=null)DoingAPaint(this,EventArgs.Empty);
                break;
        }           
        base.WndProc(ref m);
    }
}

لم يتم اختباره وأنا متأكد من أنه يمكنك تحسين ذلك


يجب أن يكون الكود الأصلي:

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp;
            cp = base.CreateParams;
            cp.Style &= 0x7DFFFFFF; //WS_CLIPCHILDREN
            return cp;
        }
    }

هذا يعمل !!


إذا كنت تريد أن يكون الخط مجرد خط أفقي أو رأسي ، ضع لوحة أخرى (تم تعطيلها بحيث لا تلتقط أي أحداث ماوس) على اللوحة الرئيسية ، قم بتعيين ارتفاعها (أو عرضها) إلى 3 أو 4 بكسل (أو كل ما تريد) ، وإحضاره إلى الأمام. إذا كنت بحاجة إلى تغيير مكان الخط أثناء وقت التشغيل ، فيمكنك فقط تحريك اللوحة وجعلها مرئية وغير مرئية. هنا هو كيف يبدو:

نص بديل http://www.freeimagehosting.net/uploads/832018002a.jpg

يمكنك حتى النقر في أي مكان تريد ، والخطوط لا تتدخل على الإطلاق. يتم رسم الخط على أي نوع من التحكم على الإطلاق (على الرغم من أن الجزء المنسدل من ComboBox أو DatePicker لا يزال يظهر أعلى الخط ، وهو أمر جيد على أي حال). الخط الأزرق هو نفس الشيء ولكن يتم إرساله إلى الخلف.


ماذا عن هذا الأمر على الحل رقم 1 (احصل على سطح المكتب DC وارسم على الشاشة):

  1. الحصول على سطح المكتب DC وكائن الرسومات لذلك DC [Graphics.fromHDC (...)]
  2. قم بتعيين الخاصية Clip للكائن الرسومات الناتجة لتكون المنطقة المرئية حالياً من النموذج الخاص بك. (لم أبحث حتى الآن عن كيفية العثور على المنطقة المرئية للنموذج)
  3. هل تقديم الرسومات الخاصة بك.

تبين أن هذا أسهل بكثير مما كنت أعتقد. شكرا لعدم قبول أي من إجاباتي الأخرى. فيما يلي عملية من خطوتين لإنشاء Fline ( خط loating - آسف ، إنه متأخر):

نص بديل http://www.freeimagehosting.net/uploads/1fd1206890.jpg

الخطوة 1 : إضافة UserControl إلى المشروع الخاص بك ثم اسم "Fline". أضف ما يلي إلى عبارات الاستخدام:

using System.Drawing.Drawing2D;

الخطوة 2 : أضف التالي إلى حدث تغيير حجم Fline:

int wfactor = 4; // half the line width, kinda
// create 6 points for path
Point[] pts = {
    new Point(0, 0), 
    new Point(wfactor, 0), 
    new Point(Width, Height - wfactor),
    new Point(Width, Height) ,
    new Point(Width - wfactor, Height),
    new Point(0, wfactor) };
// magic numbers! 
byte[] types = {
    0, // start point
    1, // line
    1, // line
    1, // line
    1, // line
    1 }; // line 
GraphicsPath path = new GraphicsPath(pts, types);
this.Region = new Region(path);

ترجمة ، ثم اسحب Fline إلى النموذج أو اللوحة. هام: BackColor الافتراضي هو نفس النموذج ، لذا قم بتغيير BackColor الخاص بـ Fline إلى اللون الأحمر أو شيء واضح (في المصمم). واحد غريب الغرابة حول هذا هو أنه عندما تقوم بسحبه في المصمم فإنه يظهر ككتلة صلبة حتى تقوم بإطلاق سراحه - ليس صفقة كبيرة.

يمكن أن يظهر عنصر التحكم هذا أمام أي عنصر تحكم آخر أو خلفه. إذا قمت بتعيين تمكين إلى false ، فسيظل مرئيًا ولكن لن يتداخل مع أحداث الماوس على عناصر التحكم الموجودة أسفله.

ستحتاج إلى تحسين ذلك لأغراضك ، بالطبع ، لكن هذا يُظهر المبدأ الأساسي. يمكنك استخدام نفس الأسلوب لإنشاء تحكم في أي شكل تريده (اختباري الأولي لهذا جعل مثلثًا).

تحديث : هذا يجعل بطانة واحدة كثيفة لطيفة ، أيضا. فقط ضع هذا في حدث تغيير حجم UserControl الخاص بك:

this.Region=new Region(new System.Drawing.Drawing2D.GraphicsPath(new Point[]{new Point(0,0),new Point(4,0),new Point(Width,Height-4),new Point(Width,Height),new Point(Width-4,Height),new Point(0,4)},new byte[]{0,1,1,1,1,1}));

أعتقد أن أفضل طريقة هي أن ترث التحكم الذي تريد رسم خط عليه. تجاوز أسلوب OnPaint ، base base.Paint () من الداخل ، بعد ذلك رسم الخط باستخدام نفس نسخة الرسومات. في الوقت نفسه ، يمكنك أيضًا الحصول على معلمة محددة عند هذه النقطة يجب رسم الخط ، بحيث يمكنك التحكم في الخط مباشرةً من النموذج الرئيسي.


الحل الوحيد البسيط الذي يمكنني التفكير فيه هو إنشاء معالجات أحداث Paint لكل عنصر تحكم تريد أن ترسمه فوق. ثم تنسيق خط الرسم بين هذه معالجات. هذا ليس الحل الأكثر ملاءمة ، ولكن هذا سوف يعطيك القدرة على الطلاء فوق عناصر التحكم.

زر افتراض هو التحكم في لوحة الطفل:

panel.Paint += new PaintEventHandler(panel_Paint);
button.Paint += new PaintEventHandler(button_Paint);

protected void panel_Paint(object sender, PaintEventArgs e)
{
    //draw the full line which will then be partially obscured by child controls
}

protected void button_Paint(object sender, PaintEventArgs e)
{
    //draw the obscured line portions on the button
}

تحرير وجدت طريقة للتخلص من قضية اللوحة عودية كان لي. والآن ، بالنسبة لي ، يبدو هذا قريبًا جدًا جدًا مما تريد تحقيقه.

إليك ما يمكن أن أضعه. ويستخدم النهج # 3 المبينة في السؤال الأصلي. الرمز طويل نوعًا ما نظرًا لثلاثة فئات:

  1. فئة خاصة تسمى DecorationCanvas. هذا مستمد من لوحة ويستخدم WS_EX_TRANSPARENT لتوفير قماش شفاف لرسم الأشياء الخاصة بنا
  2. فئة اللوحة نفسها ، أنا أطلق عليها اسم DecoratedPanel ، وهي مستمدة من لوحة
  3. فئة المصمم تسمى DecoratedPanelDesigner للوحة ، للتأكد من أنه يمكن الحفاظ على ZOrder خلال وقت التصميم.

النهج الأساسي هو:

  • في منشئ DecoratedPanel ، قم بإنشاء مثيل من DecorationCanvas وإضافته إلى مجموعة عناصر التحكم DecoratedPanel.
  • تجاوز OnControlAdded و OnControlRemoved ، تلقائياً ربط / إلغاء أحداث الرسام للتحكمات التابعة ، والتأكد من يبقى DecorationCanvas على رأس ZOrder.
  • عندما يرسم عنصر تحكم متحكم ، إبطال مستطيل decorationCanvas المناظر.
  • تجاوز OnResize و OnSizeChanged للتأكد من أن DecorationCanvas له نفس الحجم مثل DecoratedPanel. (حاولت إنجاز ذلك باستخدام خاصية الارتساء ، لكنها فشلت بطريقة أو بأخرى).
  • قم بتوفير طريقة داخلية لإعادة ضبط الزخرفة من Zincar داخل من DecoratedPanelDesigner.

يعمل بشكل جيد على النظام الخاص بي (VS2010 / .net4 / Windows XP SP3). هنا الرمز:

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace WindowsFormsApplication3
{
  [Designer("WindowsFormsApplication3.DecoratedPanelDesigner")]
  public class DecoratedPanel : Panel
  {
    #region decorationcanvas

    // this is an internal transparent panel.
    // This is our canvas we'll draw the lines on ...
    private class DecorationCanvas : Panel
    {
      public DecorationCanvas()
      {
        // don't paint the background
        SetStyle(ControlStyles.Opaque, true);
      }

      protected override CreateParams CreateParams
      {
        get
        {
          // use transparency
          CreateParams cp = base.CreateParams;
          cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
          return cp;
        }
      }
    }

    #endregion

    private DecorationCanvas _decorationCanvas;

    public DecoratedPanel()
    {
      // add our DecorationCanvas to our panel control
      _decorationCanvas = new DecorationCanvas();
      _decorationCanvas.Name = "myInternalOverlayPanel";
      _decorationCanvas.Size = ClientSize;
      _decorationCanvas.Location = new Point(0, 0);
      // this prevents the DecorationCanvas to catch clicks and the like
      _decorationCanvas.Enabled = false;
      _decorationCanvas.Paint += new PaintEventHandler(decoration_Paint);
      Controls.Add(_decorationCanvas);
    }

    protected override void Dispose(bool disposing)
    {
      if (disposing && _decorationCanvas != null)
      {
        // be a good citizen and clean up after yourself

        _decorationCanvas.Paint -= new PaintEventHandler(decoration_Paint);
        Controls.Remove(_decorationCanvas);
        _decorationCanvas = null;
      }

      base.Dispose(disposing);
    }

    void decoration_Paint(object sender, PaintEventArgs e)
    {
      // --- PAINT HERE ---
      e.Graphics.DrawLine(Pens.Red, 0, 0, ClientSize.Width, ClientSize.Height);
    }

    protected override void OnControlAdded(ControlEventArgs e)
    {
      base.OnControlAdded(e);

      if (IsInDesignMode)
        return;

      // Hook paint event and make sure we stay on top
      if (!_decorationCanvas.Equals(e.Control))
        e.Control.Paint += new PaintEventHandler(containedControl_Paint);

      ResetDecorationZOrder();
    }

    protected override void OnControlRemoved(ControlEventArgs e)
    {
      base.OnControlRemoved(e);

      if (IsInDesignMode)
        return;

      // Unhook paint event
      if (!_decorationCanvas.Equals(e.Control))
        e.Control.Paint -= new PaintEventHandler(containedControl_Paint);
    }

    /// <summary>
    /// If contained controls are updated, invalidate the corresponding DecorationCanvas area
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void containedControl_Paint(object sender, PaintEventArgs e)
    {
      Control c = sender as Control;

      if (c == null)
        return;

      _decorationCanvas.Invalidate(new Rectangle(c.Left, c.Top, c.Width, c.Height));
    }

    protected override void OnResize(EventArgs eventargs)
    {
      base.OnResize(eventargs);
      // make sure we're covering the panel control
      _decorationCanvas.Size = ClientSize;
    }

    protected override void OnSizeChanged(EventArgs e)
    {
      base.OnSizeChanged(e);
      // make sure we're covering the panel control
      _decorationCanvas.Size = ClientSize;
    }

    /// <summary>
    /// This is marked internal because it gets called from the designer
    /// to make sure our DecorationCanvas stays on top of the ZOrder.
    /// </summary>
    internal void ResetDecorationZOrder()
    {
      if (Controls.GetChildIndex(_decorationCanvas) != 0)
        Controls.SetChildIndex(_decorationCanvas, 0);
    }

    private bool IsInDesignMode
    {
      get
      {
        return DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime;
      }
    }
  }

  /// <summary>
  /// Unfortunately, the default designer of the standard panel is not a public class
  /// So we'll have to build a new designer out of another one. Since Panel inherits from
  /// ScrollableControl, let's try a ScrollableControlDesigner ...
  /// </summary>
  public class DecoratedPanelDesigner : ScrollableControlDesigner
  {
    private IComponentChangeService _changeService;

    public override void Initialize(IComponent component)
    {
      base.Initialize(component);

      // Acquire a reference to IComponentChangeService.
      this._changeService = GetService(typeof(IComponentChangeService)) as IComponentChangeService;

      // Hook the IComponentChangeService event
      if (this._changeService != null)
        this._changeService.ComponentChanged += new ComponentChangedEventHandler(_changeService_ComponentChanged);
    }

    /// <summary>
    /// Try and handle ZOrder changes at design time
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void _changeService_ComponentChanged(object sender, ComponentChangedEventArgs e)
    {
      Control changedControl = e.Component as Control;
      if (changedControl == null)
        return;

      DecoratedPanel panelPaint = Control as DecoratedPanel;

      if (panelPaint == null)
        return;

      // if the ZOrder of controls contained within our panel changes, the
      // changed control is our control
      if (Control.Equals(panelPaint))
        panelPaint.ResetDecorationZOrder();
    }

    protected override void Dispose(bool disposing)
    {
      if (disposing)
      {
        if (this._changeService != null)
        {
          // Unhook the event handler
          this._changeService.ComponentChanged -= new ComponentChangedEventHandler(_changeService_ComponentChanged);
          this._changeService = null;
        }
      }

      base.Dispose(disposing);
    }

    /// <summary>
    /// If the panel has BorderStyle.None, a dashed border needs to be drawn around it
    /// </summary>
    /// <param name="pe"></param>
    protected override void OnPaintAdornments(PaintEventArgs pe)
    {
      base.OnPaintAdornments(pe);

      Panel panel = Control as Panel;
      if (panel == null)
        return;

      if (panel.BorderStyle == BorderStyle.None)
      {
        using (Pen p = new Pen(SystemColors.ControlDark))
        {
          p.DashStyle = System.Drawing.Drawing2D.DashStyle.Dash;
          pe.Graphics.DrawRectangle(p, 0, 0, Control.Width - 1, Control.Height - 1);
        }
      }
    }
  }
}

اسمحوا لي أن أعرف ما هو رأيك ...


للحصول على كافة الخصائص (public + private / protected / internal، static + instance) من Type someType معين Type someType (ربما باستخدام GetType() للحصول على بعض someType ):

PropertyInfo[] props = someType.BaseType.GetProperties(
        BindingFlags.NonPublic | BindingFlags.Public
        | BindingFlags.Instance | BindingFlags.Static)




c# .net winforms