C#基础系列:开发自己的窗体设计器(在容器上拖动鼠标增加控件)
本文我们实现一个简单的通过拖动鼠标来增加控件的方法。在我们使用vs2005来开发WinForm应用程序的时候,我们通过选择左边“工具箱”中的某个控件,然后在我们自己的窗体上通过拖动鼠标,一个我们需要的控件就出现了,觉得很爽!其实vs2005中已经有这方面的组件,我们通过简单的代码就可以直接使用,这个你可以用“窗体设计器”Google一下,已经有人做了这方面的介绍。所以我要说的是,难
本文我们实现一个简单的通过拖动鼠标来增加控件的方法。
在我们使用vs2005来开发WinForm应用程序的时候,我们通过选择左边“工具箱”中的某个控件,然后在我们自己的窗体上通过拖动鼠标,一个我们需要的控件就出现了,觉得很爽!其实vs2005中已经有这方面的组件,我们通过简单的代码就可以直接使用,这个你可以用“窗体设计器”Google一下,已经有人做了这方面的介绍。
所以我要说的是,难道除了使用vs2005中提供的这个标准组件,就不能自己弄出一个来?即使不够强大,但是最终都是自己折腾出来的,所以也会很爽。下面我就这个功能点做一个介绍,实现效果图如下:
实现关键点:
1、动态加载控件:
在vs2005中,在某个容器控件上增加新的子控件相当的简单,语法如下,如,增加一个TextBox:
Control.Controls.Add(new TextBox());
2、选择要添加的控件:
通过一个全局的单件类来实现。
3、捕获窗体(或者容器控件,比如Panel,GroupBox等)上鼠标的移动区域,并绘制选择框,如上图中黑色的框。
对于1,是很容易实现的,所以不是我们讨论的重点,我主要讨论2和3点。
第2点:选择需要添加的控件,为了尽量的使Winform中的代码简洁,以及和其它的部分解耦,我们尽量不要考虑在WinForm中使用全局变量或者与其它模块通信的接口。所以我们使用一个单件类SettingService来作为Winform和其它部分通信的中介。
- public class SettingService
- {
- private static SettingService _Instance;
- private System.Windows.Forms.Control _SelectedToolBoxControl;
- /// <summary>
- /// 在Form中,选择了某个要添加的控件后,这里保存这个控件的一个新实例
- /// </summary>
- public System.Windows.Forms.Control SelectedToolBoxControl
- {
- get { return this._SelectedToolBoxControl; }
- set { this._SelectedToolBoxControl = value; }
- }
- private SettingService()
- { }
- /// <summary>
- /// 这里使用单件
- /// </summary>
- public static SettingService Instance
- {
- get
- {
- if (_Instance == null)
- {
- _Instance = new SettingService();
- }
- return _Instance;
- }
- }
- }
第3点:因为这里涉及到捕获鼠标的选择区域,并且在按照这个区域的起始以及大小绘制控件。要捕获鼠标,我们需要实现容器控件(Winform也是一个Control,所以这里称的容器控件包括WinForm)的Control_ MouseDown,Control_ MouseMove,Control_ MouseUp,Control_ MouseEnter这几个事件。
代码如下:
- public class MouseHook
- {
- Control _Owner;
- private int _CLickAtX;
- private int _ClickAtY;
- private int _MoveAtX;
- private int _MoveAtY;
- private bool _BeginDrag;
- private bool _BeginDrawControl;
- /// <summary>
- /// 这里Owner使用的是Control类型,是因为我们不仅仅需要在Winform上增加控件,
- /// 也需要在其它容器,比如Panel,GroupBox等上面增加容器
- /// </summary>
- /// <param name="Owner"></param>
- public MouseHook(System.Windows.Forms.Control Owner)
- {
- this._Owner = Owner;
- this._Owner.MouseDown += new MouseEventHandler(this.Control_MouseDown);
- this._Owner.MouseMove += new MouseEventHandler(this.Control_MouseMove);
- this._Owner.MouseUp += new MouseEventHandler(this.Control_MouseUp);
- this._Owner.MouseEnter += new EventHandler(this.Control_MouseEnter);
- this._BeginDrawControl = false;
- }
- #region Control上的鼠标事件
- void Control_MouseDown(object sender, MouseEventArgs e)
- {
- //如果没有选择控件,那么退出
- if (SettingService.Instance.SelectedToolBoxControl == null)
- {
- return;
- }
- this._CLickAtX = e.X;
- this._ClickAtY = e.Y;
- this._MoveAtX = e.X;
- this._MoveAtY = e.Y;
- this._BeginDrag = true;
- if (SettingService.Instance.SelectedToolBoxControl != null)
- {
- this._BeginDrawControl = true;
- }
- else
- {
- this._BeginDrawControl = false;
- }
- }
- void Control_MouseMove(object sender, MouseEventArgs e)
- {
- if (SettingService.Instance.SelectedToolBoxControl == null)
- {
- return;
- }
- if (this._BeginDrag)
- {
- //取消上次绘制的选择框
- int iLeft, iTop, iWidth, iHeight;
- Pen pen;
- Rectangle rect;
- pen = new Pen(this._Owner.BackColor);
- if (this._BeginDrawControl == true)
- {
- pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
- pen.Width = 2;
- }
- else
- {
- pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
- }
- iLeft = this._CLickAtX < this._MoveAtX ? this._CLickAtX : this._MoveAtX;
- iTop = this._ClickAtY < this._MoveAtY ? this._ClickAtY : this._MoveAtY;
- iWidth = Math.Abs(this._MoveAtX - this._CLickAtX);
- iHeight = Math.Abs(this._MoveAtY - this._ClickAtY);
- rect = new Rectangle(iLeft, iTop, iWidth, iHeight);
- this._Owner.CreateGraphics().DrawRectangle(pen, rect);
- //重新绘制选择框
- this._MoveAtX = e.X;
- this._MoveAtY = e.Y;
- pen = new Pen(Color.Black);
- if (this._BeginDrawControl == true)
- {
- pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Solid;
- pen.Width = 2;
- }
- else
- {
- pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
- }
- iLeft = this._CLickAtX < this._MoveAtX ? this._CLickAtX : this._MoveAtX;
- iTop = this._ClickAtY < this._MoveAtY ? this._ClickAtY : this._MoveAtY;
- iWidth = Math.Abs(this._MoveAtX - this._CLickAtX);
- iHeight = Math.Abs(this._MoveAtY - this._ClickAtY);
- rect = new Rectangle(iLeft, iTop, iWidth, iHeight);
- this._Owner.CreateGraphics().DrawRectangle(pen, rect);
- }
- }
- void Control_MouseUp(object sender, MouseEventArgs e)
- {
- this._BeginDrag = false;
- this._Owner.SuspendLayout();
- if (SettingService.Instance.SelectedToolBoxControl == null)
- {
- return;
- }
- //取消上次绘制的选择框
- int iLeft, iTop, iWidth, iHeight;
- Pen pen;
- Rectangle rect;
- pen = new Pen(this._Owner.BackColor);
- pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot;
- iLeft = this._CLickAtX < this._MoveAtX ? this._CLickAtX : this._MoveAtX;
- iTop = this._ClickAtY < this._MoveAtY ? this._ClickAtY : this._MoveAtY;
- iWidth = Math.Abs(this._MoveAtX - this._CLickAtX);
- iHeight = Math.Abs(this._MoveAtY - this._ClickAtY);
- rect = new Rectangle(iLeft, iTop, iWidth, iHeight);
- this._Owner.CreateGraphics().DrawRectangle(pen, rect);
- if (SettingService.Instance.SelectedToolBoxControl != null)
- {
- AddControl(SettingService.Instance.SelectedToolBoxControl, rect);
- }
- else
- {
- //这里是拖动鼠标,选择控件,这里将会在后续的介绍中给出
- }
- this._Owner.Refresh();
- this._Owner.ResumeLayout();
- }
- void Control_MouseEnter(object sender, EventArgs e)
- {
- if (SettingService.Instance.SelectedToolBoxControl != null)
- {
- this._Owner.Cursor = Cursors.Cross;
- }
- else
- {
- this._Owner.Cursor = Cursors.Default;
- }
- }
- private void AddControl(System.Windows.Forms.Control control, Rectangle rect)
- {
- try
- {
- control.Location = rect.Location;
- control.Size = rect.Size;
- control.Name = GetControlName(control);
- //因为对于DataTimePiker控件来说不能设置.Text为非日期型,所以忽略错误
- try
- {
- control.Text = GetControlType(control);
- }
- catch { }
- this._Owner.Controls.Add(control);
- control.Visible = true;
- this._Owner.Cursor = Cursors.Default;
- SettingService.Instance.SelectedToolBoxControl = null;
- }
- catch (Exception e)
- {
- this._Owner.Cursor = Cursors.Default;
- SettingService.Instance.SelectedToolBoxControl = null;
- }
- }
- private string GetControlType(System.Windows.Forms.Control ctrl)
- {
- string strType = ctrl.GetType().ToString();
- string strControlType;
- string[] strArr = strType.Split(".".ToCharArray());
- strControlType = strArr[strArr.Length - 1].Trim();
- return strControlType;
- }
- private string GetControlName(System.Windows.Forms.Control control)
- {
- //这里简单返回控件名,如果需要,可以通过修改这个函数做特殊处理
- return control.GetType().Name;
- }
- #endregion
- }
另外Form代码如下,这里为了方便,我直接先使用几个Button来替代实际中的ToolBox:
- //在Form中增加几个Button,分别命名为cmdArrow,cmdLabel,cmdTextBox,cmdComboBox,cmdGroupBox
- public partial class Form1 : Form
- {
- private MouseHook _MouseHook;
- public Form1()
- {
- InitializeComponent();
- this._MouseHook = new MouseHook(this);
- }
- private void cmdArrow_Click(object sender, EventArgs e)
- {
- SettingService.Instance.SelectedToolBoxControl = null;
- }
- private void cmdLabel_Click(object sender, EventArgs e)
- {
- SettingService.Instance.SelectedToolBoxControl = new Label();
- }
- private void cmdTextBox_Click(object sender, EventArgs e)
- {
- SettingService.Instance.SelectedToolBoxControl = new TextBox();
- }
- private void cmdComboBox_Click(object sender, EventArgs e)
- {
- SettingService.Instance.SelectedToolBoxControl = new ComboBox();
- }
- private void cmdGroupBox_Click(object sender, EventArgs e)
- {
- SettingService.Instance.SelectedToolBoxControl = new GroupBox();
- }
- }
上面就是简单实现拖动增加控件的方法,如果要在GroupBox中增加控件的话,只需要再new 一个MouseHook,如:new MouseHook(GroupBoxControl)这样就可以了的。
更多推荐
所有评论(0)