【问题标题】:Adding controls to a custom form将控件添加到自定义表单
【发布时间】:2013-05-19 04:50:59
【问题描述】:

我创建了一个自定义表单 (FormBorderStyle = FormBorderStyle.None)。

我使用自己的自定义标题按钮(关闭、最大化...)在顶部绘制自己的标题栏。

现在我唯一的问题是向该表单添加普通用户控件。如果我给这些控件一个位置,这些位置是相对于窗体顶部的(包括标题栏)。

我使用“new”关键字覆盖了默认的 ClientSize 和 ClientRectangle,这使我可以对其进行调整(从而从中删除标题栏)。

这似乎不起作用,我无法弄清楚如何在不“破解” ControlAdded 事件的情况下正确执行此操作(这仍然是错误的)。

    protected override void OnControlAdded(ControlEventArgs e)
    {
        base.OnControlAdded(e);
        if (e.Control.GetType() != typeof(VlufiCaptionButton /* Caption buttons: close, minimize & maximize, should not be included */))
        {
            e.Control.Location = new Point(e.Control.Location.X + ClientRectangle.X, e.Control.Location.Y + ClientRectangle.Y);
            e.Control.LocationChanged += Control_LocationChanged;
        }
    }
    private void Control_LocationChanged(object sender, EventArgs e)
    {
        if (!childControlLocationChangedHandled)
        {
            System.Diagnostics.Debug.WriteLine("changing");
            Control cControl = (Control)sender;
            childControlLocationChangedHandled = true;
            cControl.Location = new Point(cControl.Location.X + ClientRectangle.X, cControl.Location.Y + ClientRectangle.Y);
        }
        else
            childControlLocationChangedHandled = false;
    }

这是我目前使用的代码,但它超级笨拙,而且我的自定义绘制边框仍然存在其他问题。

有人知道我应该如何正确处理吗?

我找到了一个不错的解决方案:我在表单中添加了一个 ContainerControl,并根据表单对其进行定位和调整大小,然后每当向表单添加控件时,都应该将其添加到 ContainerControl .仍然不是一个合适的解决方案,但它是迄今为止最好的解决方案。

如果有人提出其他解决方案,我仍然会很感激。

【问题讨论】:

    标签: c# winforms custom-controls


    【解决方案1】:

    详细阅读cmets:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    
    namespace WindowsApplication1
    {
        public partial class Form1 : Form
        {
            int dy = 0;
            public Form1()
            {
                InitializeComponent();
                //i add a panel to top form
                //( for simulating your caption bar) and get its height
                dy = panel1.Height; //for yours its your caption bar height
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                //adding button control between form top and panel end area
                //( simulate in your caption bar )
                Button btn = new Button();
                btn.Location = new Point(panel1.Location.X+40,panel1.Location.Y+10);
                btn.Text = "Salam";
                this.Controls.Add(btn);
            }
            //in control added event i add dy ( height of ignored area) to control Location
            private void Form1_ControlAdded(object sender, ControlEventArgs e)
            {
                e.Control.Location = new Point(e.Control.Location.X, e.Control.Location.Y + dy);
            }
    
            private void button2_Click(object sender, EventArgs e)
            {
                this.Close();
            }
        }
    }
    

    【讨论】:

    • 正如您在代码中看到的那样,这就是我正在做的事情。在运行时更改位置和调整表单大小时会带来很多错误
    • 对不起,我一个字都听不懂你在说什么,你的解决方案到底是什么?
    • 这就是我在示例代码中所做的事情?此外,这种方法不支持对接等。我找到的最后一个解决方案确实如此,除非有人能提供另一个更好的解决方案,否则我会坚持使用它。谢谢
    【解决方案2】:

    好吧,我终于找到了一个可行且相当不错的解决方案。

    我所做的是使用我自己的自定义 ControlCollection 覆盖自定义表单的 Controls 属性。

    这就是我在自定义表单中得到的:

    public Control.ControlCollection RealControls
    {
        get
        {
            return base.Controls;
        }
    }
    public new CustomControlCollection Controls { get; private set; }
    
    public ContainerControl ControlContainer { get; set; }
    

    这是自定义的 ControlCollection:

    public class CustomControlCollection 
    {
        public VlufiForm Owner { get; private set; }
        public CustomControlCollection (VlufiForm pOwner)
        {
            Owner = pOwner;
        }
        public void Add(Control c)
        {
            Add(c, false);
        }
        public int Count
        {
            get
            {
                return Owner.ControlContainer.Controls.Count;
            }
        }
        public Control this[int index]
        {
            get
            {
                return Owner.ControlContainer.Controls[index];
            }
        }
        public void Add(Control c, bool isUsable)
        {
            if (isUsable)
                Owner.RealControls.Add(c);
            else
                Owner.ControlContainer.Controls.Add(c);
        }
        public void SetChildIndex(Control c, int nIndex)
        {
            Owner.ControlContainer.Controls.SetChildIndex(c, nIndex);
        }
    }
    

    这只是一个示例自定义控件集合,您可以在其中添加更多方法(从而更多地继承 ControlCollection)。 我还没有在这个系统中发现任何错误,目前它运行良好。

    编辑:发现一个错误,如果你在 Visual Studio 的设计器模式中停靠一个控件,它将停靠在整个窗体中,但运行时不会出现。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-14
      • 1970-01-01
      • 2010-11-12
      • 1970-01-01
      • 2011-11-10
      • 1970-01-01
      • 2017-08-21
      相关资源
      最近更新 更多