[C#] الرسم على أعلى من الضوابط داخل لوحة (C # وينفورمز)


Answers

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

ألت تكست http://www.freeimagehosting.net/uploads/832018002a.jpg

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

Question

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

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

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

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

  2. تجاوز لوحة "كريتيبارامز" في اللوحة:

=

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

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

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

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

ثالثا: إنشاء طبقة شفافة والاستفادة من تلك الطبقة.
لقد أنشأت رقابة شفافة باستخدام:

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

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

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

** إديت: الخط الأسود هو عينة من ما كنت أحاول القيام به. (تستخدم النوافذ الطلاء لطلائه)




إنشاء لينكونترول جديدة: التحكم مثل هذا:

ثم استدعاء برينتوفرونت () بعد إنيتياليزكومبوننت

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

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

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

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

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

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




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




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

لحسن الحظ، يمكنك إنشاء نماذج النوافذ الضوابط التي لها حدود غير مستطيلة. انظر إلى هذه التقنية: http://msdn.microsoft.com/en-us/library/aa289517(VS.71).aspx

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

في ما يلي نموذج شفرة:

private void label1_Paint(object sender, PaintEventArgs e)
{
    System.Drawing.Drawing2D.GraphicsPath myGraphicsPath = new  System.Drawing.Drawing2D.GraphicsPath();
    myGraphicsPath.AddEllipse(new Rectangle(0, 0, 125, 125));
    myGraphicsPath.AddEllipse(new Rectangle(75, 75, 20, 20));
    myGraphicsPath.AddEllipse(new Rectangle(120, 0, 125, 125));
    myGraphicsPath.AddEllipse(new Rectangle(145, 75, 20, 20));
    //Change the button's background color so that it is easy
    //to see.
    label1.BackColor = Color.ForestGreen;
    label1.Size = new System.Drawing.Size(256, 256);
    label1.Region = new Region(myGraphicsPath);
}



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

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