您的位置:首页 > 编程语言 > C#

C#基础系列:开发自己的窗体设计器(在容器上拖动鼠标增加控件)

2013-01-11 17:19 846 查看
【转 /article/1778186.html

本文我们实现一个简单的通过拖动鼠标来增加控件的方法。

在我们使用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)这样就可以了的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐