如何在其中的其他控件上绘制时,可以使背景控件可编辑

时间:2016-03-16 09:01:14

标签: c# windows winforms

我们必须为RichTextBox提供选择支持,因此我创建了单独的控件并使用Paint()方法绘制它。问题是我在完成绘图之后无法编辑RichTextBox。请找到下面附带的简单样本并分享您的想法。

注意:由于将选择控制停靠栏样式设置为“填充”,我们怀疑是否存在问题,但如果我删除或更改,则选择未绘制。

enter image description here

partial class Form1
{
    /// <summary>
    /// Required designer variable.
    /// </summary>
    private System.ComponentModel.IContainer components = null;

    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    protected override void Dispose(bool disposing)
    {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
    }

    #region Windows Form Designer generated code

    private GraphicCellControl graphiccell;

    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {

        #region picturebox

        this.BackColor = Color.Aquamarine;

        var selectBtn = new Button();
        selectBtn.Size = new Size(100, 30);
        selectBtn.Location = new Point(10, 10);
        selectBtn.Text = "Click";
        selectBtn.Click += selectBtn_Click;

        //var picturebox = new PictureBox();
        //picturebox.Size = new Size(140, 110);
        //picturebox.Location = new Point(4, 4);
        //picturebox.SizeMode = PictureBoxSizeMode.StretchImage;
        //picturebox.Image = new Bitmap(@"..\..\Data\picture.png");

        var richtextbox = new RichTextBox();
        richtextbox.Size = new Size(140, 110);
        richtextbox.Location = new Point(4, 4);
        richtextbox.Text = "Texting information";

        graphiccell = new GraphicCellControl();
        graphiccell.Location = new Point(50, 200);
        graphiccell.Size = new Size(150, 120);
        graphiccell.Controls.Add(richtextbox);
        this.Controls.Add(graphiccell);
        this.Controls.Add(selectBtn);

        #endregion

    }

    void selectBtn_Click(object sender, EventArgs e)
    {
        graphiccell.IsSelected = !graphiccell.IsSelected;
    }

    #endregion
}

public class GraphicCellControl : Control
{
    private SelectionControl selectionControl;
    public GraphicCellControl()
    {
        selectionControl = new SelectionControl();
    }

    private bool isselected;
    public bool IsSelected
    {
        get { return isselected; }
        set
        {
            isselected = value;
            if (isselected && !this.Controls.Contains(selectionControl))
            {
                this.Controls.Add(selectionControl);
                selectionControl.BringToFront();
            }
            else if (!isselected && this.Controls.Contains(selectionControl))
                this.Controls.Remove(selectionControl);
        }
    }
}

public class SelectionControl : Control
{
    public SelectionControl()
    {
        SetStyle(ControlStyles.AllPaintingInWmPaint |
                 ControlStyles.UserPaint | ControlStyles.Opaque |
                 ControlStyles.SupportsTransparentBackColor, true);
        Dock = DockStyle.Fill;
       // Anchor = AnchorStyles.Left | AnchorStyles.Top;
        BackColor = Color.Transparent;
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.DrawRectangle(new Pen(Color.Gray, 1), 4, 4, this.Size.Width - 10, this.Size.Height - 10);

        e.Graphics.FillEllipse(Brushes.White, 0, 0, 8, 8);
        e.Graphics.FillEllipse(Brushes.White, 0, (this.Size.Height - 10) / 2, 8, 8);
        e.Graphics.FillEllipse(Brushes.White, 0, this.Size.Height - 10, 8, 8);
        e.Graphics.FillEllipse(Brushes.White, (this.Size.Width - 10) / 2, 0, 8, 8);
        e.Graphics.FillEllipse(Brushes.White, (this.Size.Width - 10) / 2, this.Size.Height - 10, 8, 8);
        e.Graphics.FillEllipse(Brushes.White, this.Size.Width - 10, 0, 8, 8);
        e.Graphics.FillEllipse(Brushes.White, this.Size.Width - 10, (this.Size.Height - 10) / 2, 8, 8);
        e.Graphics.FillEllipse(Brushes.White, this.Size.Width - 10, this.Size.Height - 10, 8, 8);

        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), 0, 0, 8, 8);
        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), 0, (this.Size.Height - 10) / 2, 8, 8);
        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), 0, this.Size.Height - 10, 8, 8);
        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), (this.Size.Width - 10) / 2, 0, 8, 8);
        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), (this.Size.Width - 10) / 2, this.Size.Height - 10, 8, 8);
        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), this.Size.Width - 10, 0, 8, 8);
        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), this.Size.Width - 10, (this.Size.Height - 10) / 2, 8, 8);
        e.Graphics.DrawEllipse(new Pen(Color.DarkGray, 2), this.Size.Width - 10, this.Size.Height - 10, 8, 8);
    }
}

2 个答案:

答案 0 :(得分:0)

问题的核心,据我所知,您的叠加控制将拦截所有用户的交互。

这不仅适用于鼠标操作。它还包括键盘操作,设置焦点以及在任何更改后更新显示。

可以通过重定向所有相关的WndProc消息来解决所有这些问题,但它会相当复杂。

这是一个更简单的解决方案:RTB与选择框的重叠,而不是RTB的 。我已经创建了一个修改过的类并且它工作得相当好,虽然可能会调整句柄的大小,使它们动态并使各自的偏移正确,但你可以做到这一点......:

enter image description here

班级与你的基本相同;我刚刚添加了一些属性和Select方法:

Point oldLocation = Point.Empty;
Control oldParent = null;
BorderStyle oldBorder = BorderStyle.None;

public void Select(Control ctl, bool selected)
{
    if (selected)
    {
        Parent = ctl.Parent;
        oldLocation = ctl.Location;
        ctl.Location = new Point(8, 8);
        Location = Point.Subtract(oldLocation, new Size(8, 8));
        Size = new Size(ctl.Width + 16, ctl.Height + 16);
        oldParent = ctl.Parent;
        oldBorder = (ctl as RichTextBox).BorderStyle;        // optional
        (ctl as RichTextBox).BorderStyle = BorderStyle.None; // optional
        ctl.Parent = this;
        this.Show();
    }
    else
    {
        ctl.Location = oldLocation;
        ctl.Parent = oldParent;
        (ctl as RichTextBox).BorderStyle = oldBorder;   // optional
        this.Hide();
    }
}

我最初没有包含BorderStyle逻辑;我认为这是一些切断像素的原因。不难做对.. ..

另请注意,为了使颜色完全正确,您还需要一个FillRectangle以避免让父BackColor流入选择框,具体取决于您拥有的颜色..:

if (Controls.Count > 0)
    using (SolidBrush brush = new SolidBrush(Controls[0].BackColor))
           e.Graphics.FillRectangle(brush, 4, 4, Width - 10, Height - 10);

答案 1 :(得分:0)

通过研究最终我得到了一个解决方案,将此方法放在selectioncontrol中:

protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;
                cp.ExStyle |= 0x20;
                return cp;
            }
        }