所谓控件的选择,就是在设计器上某个控件被选中或者控件获得焦点(通过Tab调整控件焦点)的时候,在控件的四周显示出调整手柄。
如下图:
如上,通过控件的调整手柄,我们可以调整控件的宽度和高度。而实现这个调整手柄的关键点其实得益于vs2005控件的灵活性。因为这8个正方形的调整手柄其实就是8个控件。
所以我们本文的重点如下:
1、开发自定义的调整手柄控件,也就是这正方形控件;
2、组合这8个调整手柄控件,目标是使设计器上的控件与调整手柄完全解耦,调整手柄能够不做任何的修改就可以应用于所有的控件;
3、设计器上的控件与调整手柄的对应方法,也就是选择控件的时候,能够在控件周围显示调整手柄。
下面我们针对这3个重点,在前一篇《在容器上拖动鼠标增加控件》的基础上,实现控件的选择功能。
1、开发自定义的调整手柄控件:
这其实属于自定义控件开发的问题,你首先增加“用户控件”,把控件名命名为UISizeDot,把下面的代码直接拷贝进去就可以了,所以我不做过多的描述,这里直接把代码贴出来好了。
- [ToolboxItem(false)]
- public partial class UISizeDot : Control
- {
- private bool _movable;
- private Pen pen = new Pen(Color.Black);
- public UISizeDot()
- {
- InitializeComponent();
- SetStyle(ControlStyles.UserPaint, true);
- SetStyle(ControlStyles.AllPaintingInWmPaint, true);
- SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
- this.TabStop = false;
- this._movable = true;
- }
- /// <summary>
- /// UISizeDot的边框颜色
- /// </summary>
- public Color BorderColor
- {
- get { return pen.Color; }
- set
- {
- this.pen = new Pen(value);
- this.Refresh();
- }
- }
- protected override void OnPaint(PaintEventArgs pe)
- {
- // TODO: 在此处添加自定义绘制代码
- //this.BackColor = Color.White;
- pe.Graphics.DrawRectangle(pen, 0, 0, this.Width - 1, this.Height - 1);
- // 调用基类 OnPaint
- base.OnPaint(pe);
- }
- public bool Movable
- {
- get { return this._movable; }
- set { this._movable = value; }
- }
- }
2、组合这8个自定义调整手柄控件:
这个功能的目的就是,就是将这8个调整手柄控件组合起来,为了描述以及开发上的方便,我们使用一个控件数组UISizeDot[]_UISizeDot = new UISizeDot(8),我们约定从左上角按照顺时针方向到又下角分别_UISizeDot[0]~ _UISizeDot[7],其它的不用说了,看代码吧:
- public enum ENUM_UISizeMode
- {
- FixNone = 0, //不固定
- FixLocation = 1, //固定左上角,这时只能改变两边
- FixHeight = 2, //固定高
- FixWidth = 3, //固定宽
- FixBoth = 4 //长宽都固定
- }
- public class UISizeKnob
- {
- private const int DOT_WIDTH = 7; //UISizeDot宽度
- private const int DOT_HEIGHT = 7; //UISizeDot高度
- private const int DOT_SPACE = 0; //UISizeDot与_Owner的距离
- private const int DOT_COUNT = 8; //要显示的UISizeDot数
- private System.Windows.Forms.Control _Owner;
- private UISizeDot[] _UISizeDot;
- private int _OldTop;
- private int _OldLeft;
- private int _NewTop;
- private int _NewLeft;
- private int _OldWidth;
- private int _OldHeight;
- private int _ClickAtX;
- private int _ClickAtY;
- private ENUM_UISizeMode _UISizeMode;
- private bool _BeginDrag;
- private Rectangle _OldRect;
- private Color _DotColor = Color.White; //UISizeDot默认颜色为白色
- private Color _DotBorderColor = Color.Black; //UISizeDot默认边框颜色为黑色
- public event System.Windows.Forms.MouseEventHandler MouseDown = null;
- public event System.Windows.Forms.MouseEventHandler MouseMove = null;
- public event System.Windows.Forms.MouseEventHandler MouseUp = null;
- private int j=0;
- private bool _IsShow = false;
- public UISizeKnob(System.Windows.Forms.Control owner)
- {
- this._Owner = owner;
- this._NewTop = owner.Top;
- this._NewLeft = owner.Left;
- this._OldWidth = owner.Width;
- this._OldHeight = owner.Height;
- InitUISizeDots();
- }
- public bool IsShow
- {
- get { return this._IsShow; }
- }
- public Color DotColor
- {
- get { return this._DotColor; }
- set
- {
- this._DotColor = value;
- this._DotBorderColor = Color.FromArgb(Math.Abs(Convert.ToInt32(value.R) - 255), Math.Abs(Convert.ToInt32(value.G) - 255), Math.Abs(Convert.ToInt32(value.B) - 255));
- }
- }
- /// <summary>
- /// 注销
- /// </summary>
- public void Dispose()
- {
- for (int i = 0; i < this._UISizeDot.Length; i++)
- {
- this._UISizeDot[i].Dispose();
- }
- }
- /// <summary>
- /// this._Owner的大小改变模式
- /// </summary>
- public ENUM_UISizeMode UISizeMode
- {
- get { return this._UISizeMode; }
- set { this._UISizeMode = value; }
- }
- private void InitUISizeDots()
- {
- this._UISizeDot = new UISizeDot[DOT_COUNT];
- for (int i = 0; i < DOT_COUNT; i++)
- {
- this._UISizeDot[i] = new UISizeDot();
- this._UISizeDot[i].Width = DOT_WIDTH;
- this._UISizeDot[i].Height = DOT_HEIGHT;
- this._UISizeDot[i].Visible = false;
- this._Owner.Parent.Controls.Add(this._UISizeDot[i]);
- this._UISizeDot[i].MouseDown += new System.Windows.Forms.MouseEventHandler(this.UISizeDot_MouseDown);
- this._UISizeDot[i].MouseMove += new System.Windows.Forms.MouseEventHandler(this.UISizeDot_MouseMove);
- this._UISizeDot[i].MouseUp += new System.Windows.Forms.MouseEventHandler(this.UISizeDot_MouseUp);
- }
- this._UISizeDot[0].Cursor = System.Windows.Forms.Cursors.SizeNWSE;
- this._UISizeDot[1].Cursor = System.Windows.Forms.Cursors.SizeNS;
- this._UISizeDot[2].Cursor = System.Windows.Forms.Cursors.SizeNESW;
- this._UISizeDot[3].Cursor = System.Windows.Forms.Cursors.SizeWE;
- this._UISizeDot[4].Cursor = System.Windows.Forms.Cursors.SizeNWSE;
- this._UISizeDot[5].Cursor = System.Windows.Forms.Cursors.SizeNS;
- this._UISizeDot[6].Cursor = System.Windows.Forms.Cursors.SizeNESW;
- this._UISizeDot[7].Cursor = System.Windows.Forms.Cursors.SizeWE;
- SetUISizeDotsPosition();
- }
- public void ShowUISizeDots(bool show)
- {
- this._IsShow = show;
- //2006-10-05:将此函数中所有的this._UISizeDot.Length全部替换成8
- if (show)
- {
- SetUISizeDotsPositionByMove(false);
- }
- else
- {
- this._Owner.Parent.SuspendLayout();
- for (int i = 0; i < DOT_COUNT; i++)
- {
- this._UISizeDot[i].Visible = show;
- }
- this._Owner.Parent.ResumeLayout();
- return;
- }
- if (this._UISizeMode == ENUM_UISizeMode.FixNone)
- {
- for (int i = 0; i < DOT_COUNT; i++)
- {
- this._UISizeDot[i].BorderColor = this._DotBorderColor;
- this._UISizeDot[i].BackColor = this._DotColor;
- this._UISizeDot[i].Visible = show;
- }
- }
- else if (this._UISizeMode == ENUM_UISizeMode.FixLocation)
- {
- for (int i = 0; i < DOT_COUNT; i++)
- {
- this._UISizeDot[i].BorderColor = this._DotBorderColor;
- this._UISizeDot[i].BackColor = this._DotColor;
- this._UISizeDot[i].Visible = show;
- }
- this._UISizeDot[0].BackColor = System.Drawing.Color.FromArgb(9, 55, 119);
- this._UISizeDot[0].Movable = false;
- this._UISizeDot[1].BackColor = System.Drawing.Color.FromArgb(9, 55, 119);
- this._UISizeDot[1].Movable = false;
- this._UISizeDot[2].BackColor = System.Drawing.Color.FromArgb(9, 55, 119);
- this._UISizeDot[2].Movable = false;
- this._UISizeDot[6].BackColor = System.Drawing.Color.FromArgb(9, 55, 119);
- this._UISizeDot[6].Movable = false;
- this._UISizeDot[7].BackColor = System.Drawing.Color.FromArgb(9, 55, 119);
- this._UISizeDot[7].Movable = false;
- }
- else if (this._UISizeMode == ENUM_UISizeMode.FixHeight)
- {
- this._UISizeDot[0].Visible = false;
- this._UISizeDot[1].Visible = false;
- this._UISizeDot[2].Visible = false;
- this._UISizeDot[3].BorderColor = this._DotBorderColor;
- this._UISizeDot[3].BackColor = this._DotColor;
- this._UISizeDot[3].Refresh();
- this._UISizeDot[3].Visible = show;
- this._UISizeDot[4].Visible = false;
- this._UISizeDot[5].Visible = false;
- this._UISizeDot[6].Visible = false;
- this._UISizeDot[7].BorderColor = this._DotBorderColor;
- this._UISizeDot[7].BackColor = this._DotColor;
- this._UISizeDot[7].Refresh();
- this._UISizeDot[7].Visible = show;
- }
- else if (this._UISizeMode == ENUM_UISizeMode.FixWidth)
- {
- this._UISizeDot[0].Visible = false;
- this._UISizeDot[1].BorderColor = this._DotBorderColor;
- this._UISizeDot[1].BackColor = this._DotColor;
- this._UISizeDot[1].Visible = show;
- this._UISizeDot[1].Refresh();
- this._UISizeDot[2].Visible = false;
- this._UISizeDot[3].Visible = false;
- this._UISizeDot[4].Visible = false;
- this._UISizeDot[5].BorderColor = this._DotBorderColor;
- this._UISizeDot[5].BackColor = this._DotColor;
- this._UISizeDot[5].Visible = show;
- this._UISizeDot[5].Refresh();
- this._UISizeDot[6].Visible = false;
- this._UISizeDot[7].Visible = false;
- }
- else if (this._UISizeMode == ENUM_UISizeMode.FixBoth)
- {
- for (int i = 0; i < DOT_COUNT; i++)
- {
- this._UISizeDot[i].BorderColor = this._DotBorderColor;
- this._UISizeDot[i].BackColor = System.Drawing.Color.FromArgb(9, 55, 119);
- this._UISizeDot[i].Movable = false;
- this._UISizeDot[i].Visible = show;
- }
- }
- }
- private void SetUISizeDotsPosition()
- {
- int left, width, height, top;
- left = this._Owner.Left;
- top = this._Owner.Top;
- width = this._Owner.Width;
- height = this._Owner.Height;
- this._UISizeDot[0].Location = new Point(left - DOT_WIDTH - DOT_SPACE, top - DOT_HEIGHT - DOT_SPACE);
- this._UISizeDot[1].Location = new Point(left + width / 2 - DOT_WIDTH / 2, top - DOT_HEIGHT - DOT_SPACE);
- this._UISizeDot[2].Location = new Point(left + width + DOT_SPACE, top - DOT_HEIGHT - DOT_SPACE);
- this._UISizeDot[3].Location = new Point(left + width + DOT_SPACE, top + height / 2 - DOT_HEIGHT / 2);
- this._UISizeDot[4].Location = new Point(left + width + DOT_SPACE, top + height + DOT_SPACE);
- this._UISizeDot[5].Location = new Point(left + width / 2 - DOT_WIDTH / 2, top + height + DOT_SPACE);
- this._UISizeDot[6].Location = new Point(left - DOT_WIDTH - DOT_SPACE, top + height + DOT_SPACE);
- this._UISizeDot[7].Location = new Point(left - DOT_WIDTH - DOT_SPACE, top + height / 2 - DOT_HEIGHT / 2);
- }
- private void SetUISizeDotsPositionByMove(bool Show)
- {
- int left, width, height, top;
- left = this._Owner.Left;
- top = this._Owner.Top;
- width = this._Owner.Width;
- height = this._Owner.Height;
- this._UISizeDot[0].Visible = Show;
- this._UISizeDot[1].Visible = Show;
- this._UISizeDot[2].Visible = Show;
- this._UISizeDot[3].Visible = Show;
- this._UISizeDot[4].Visible = Show;
- this._UISizeDot[5].Visible = Show;
- this._UISizeDot[6].Visible = Show;
- this._UISizeDot[7].Visible = Show;
- this._UISizeDot[0].BringToFront();
- this._UISizeDot[1].BringToFront();
- this._UISizeDot[2].BringToFront();
- this._UISizeDot[3].BringToFront();
- this._UISizeDot[4].BringToFront();
- this._UISizeDot[5].BringToFront();
- this._UISizeDot[6].BringToFront();
- this._UISizeDot[7].BringToFront();
- this._UISizeDot[0].Location = new Point(left - DOT_WIDTH - DOT_SPACE, top - DOT_HEIGHT - DOT_SPACE);
- this._UISizeDot[1].Location = new Point(left + width / 2 - DOT_WIDTH / 2, top - DOT_HEIGHT - DOT_SPACE);
- this._UISizeDot[2].Location = new Point(left + width + DOT_SPACE, top - DOT_HEIGHT - DOT_SPACE);
- this._UISizeDot[3].Location = new Point(left + width + DOT_SPACE, top + height / 2 - DOT_HEIGHT / 2);
- this._UISizeDot[4].Location = new Point(left + width + DOT_SPACE, top + height + DOT_SPACE);
- this._UISizeDot[5].Location = new Point(left + width / 2 - DOT_WIDTH / 2, top + height + DOT_SPACE);
- this._UISizeDot[6].Location = new Point(left - DOT_WIDTH - DOT_SPACE, top + height + DOT_SPACE);
- this._UISizeDot[7].Location = new Point(left - DOT_WIDTH - DOT_SPACE, top + height / 2 - DOT_HEIGHT / 2);
- }
- private void UISizeDot_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
- {
- if (!((UISizeDot)sender).Movable)
- {
- return;
- }
- j++;
- this.ShowUISizeDots(false);
- this._BeginDrag = true;
- this._ClickAtX = e.X;
- this._ClickAtY = e.Y;
- this._OldTop = this._Owner.Top;
- this._OldLeft = this._Owner.Left;
- this._NewTop = this._Owner.Top;
- this._NewLeft = this._Owner.Left;
- this._OldHeight = this._Owner.Height;
- this._OldWidth = this._Owner.Width;
- Rectangle rect = new Rectangle(this._NewLeft - 1, this._NewTop - 1, this._OldWidth + 2, this._OldHeight + 2);
- //this._Owner.Parent.CreateGraphics().DrawRectangle(new Pen(Color.Black,2),rect);
- this._OldRect = rect;
- if (this.MouseDown != null)
- this.MouseDown(sender, e);
- }
- private void UISizeDot_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
- {
- if (!((UISizeDot)sender).Movable)
- {
- return;
- }
- if (this._BeginDrag)
- {
- int eX = e.X - this._ClickAtX;
- int eY = e.Y - this._ClickAtY;
- if (this._UISizeDot[0] == sender)
- {
- this._Owner.Location = new System.Drawing.Point(this._NewLeft + eX, this._NewTop + eY);
- this._Owner.Size = new System.Drawing.Size(this._Owner.Width - eX, this._Owner.Height - eY);
- }
- else if (this._UISizeDot[1] == sender)
- {
- this._Owner.Location = new System.Drawing.Point(this._NewLeft, this._NewTop + eY);
- this._Owner.Size = new System.Drawing.Size(this._Owner.Width, this._Owner.Height - eY);
- }
- else if (this._UISizeDot[2] == sender)
- {
- this._Owner.Location = new System.Drawing.Point(this._NewLeft, this._NewTop + eY);
- this._Owner.Size = new System.Drawing.Size(this._Owner.Width + eX, this._Owner.Height - eY);
- }
- else if (this._UISizeDot[3] == sender)
- {
- this._Owner.Size = new System.Drawing.Size(this._Owner.Width + eX, this._Owner.Height);
- }
- else if (this._UISizeDot[4] == sender)
- {
- this._Owner.Size = new System.Drawing.Size(this._Owner.Width + eX, this._Owner.Height + eY);
- }
- else if (this._UISizeDot[5] == sender)
- {
- this._Owner.Size = new System.Drawing.Size(this._Owner.Width, this._Owner.Height + eY);
- }
- else if (this._UISizeDot[6] == sender)
- {
- this._Owner.Location = new System.Drawing.Point(this._NewLeft + eX, this._NewTop);
- this._Owner.Size = new System.Drawing.Size(this._Owner.Size.Width - eX, this._Owner.Height + eY);
- }
- else if (this._UISizeDot[7] == sender)
- {
- this._Owner.Location = new System.Drawing.Point(this._NewLeft + eX, this._NewTop);
- this._Owner.Size = new System.Drawing.Size(_Owner.Width - eX, this._Owner.Height);
- }
- this._NewTop = this._Owner.Top;
- this._NewLeft = this._Owner.Left;
- //this._OldHeight = this._Owner.Height;
- //this._OldWidth = this._Owner.Width;
- SetUISizeDotsPosition();
- this._Owner.Refresh();
- this._Owner.Parent.Refresh();
- //this._Owner.Parent.CreateGraphics().DrawRectangle(new Pen(this._Owner.BackColor,2), this._OldRect);
- Rectangle rect = new Rectangle(this._NewLeft - 1, this._NewTop - 1, this._Owner.Width + 2, this._Owner.Height + 2);
- //this._Owner.Parent.CreateGraphics().DrawRectangle(new Pen(Color.Black,2), rect);
- this._OldRect = rect;
- }
- if (this.MouseMove != null)
- this.MouseMove(sender, e);
- }
- private void UISizeDot_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
- {
- if (!((UISizeDot)sender).Movable)
- {
- return;
- }
- Hashtable OldWidth;
- Hashtable OldHeight;
- Hashtable NewWidth;
- Hashtable NewHeight;
- //Test.UIResizeCommand ResizeCommand;
- //this._Owner.Parent.CreateGraphics().DrawRectangle(new Pen(this._Owner.BackColor,2),this._OldRect);
- this.ShowUISizeDots(true);
- //使用UIResizeCommand,这里主要是保存现场,这样可以方便实现Undo和Redo
- if (this._OldHeight != this._Owner.Height || this._OldWidth != this._Owner.Width)
- {
- OldWidth = new Hashtable();
- OldHeight = new Hashtable();
- NewWidth = new Hashtable();
- NewHeight = new Hashtable();
- OldWidth.Add(this._Owner, this._OldWidth);
- OldHeight.Add(this._Owner, this._OldHeight);
- NewWidth.Add(this._Owner, this._Owner.Width);
- NewHeight.Add(this._Owner, this._Owner.Height);
- }
- this._BeginDrag = false;
- if (this.MouseUp != null)
- this.MouseUp(sender, e);
- }
- }
3、设计器上控件与调整手柄的对应方法:
在我们的UISizeKnob中,有一个函数ShowUISizeDots(bool show)。这里的show参数就是表示,显示或者隐藏控件的调整手柄。
所以为了方便,我在前面的Form中增加这样的变量和函数:
变量private Hashtable _HashUISizeKnob负责缓存每个新增加的控件对应的UISizeKnob对象,因为一个Control只能对应一个UISizeKnob对象。
另外,我们怎么知道新增了控件呢,这里需要实现事件Control.ControlAdded,在这里是实现Form的ControlAdded事件。
Form的代码修改后如下:
- //在Form中增加几个Button,分别命名为cmdArrow,cmdLabel,cmdTextBox,cmdComboBox,cmdGroupBox
- public partial class Form1 : Form
- {
- private MouseHook _MouseHook;
- //我们将所有的已经与具体控件关联了的UISizeKnob缓存在这个HashTable中
- private Hashtable _HashUISizeKnob;
- public Form1()
- {
- InitializeComponent();
- this._MouseHook = new MouseHook(this);
- this._HashUISizeKnob = new Hashtable();
- //为了简洁明了,我们在ControlAdded中来设置具体控件和UISizeKnob的关联
- this.ControlAdded += new ControlEventHandler(Form1_ControlAdded);
- }
- void Form1_ControlAdded(object sender, ControlEventArgs e)
- {
- if (!(e.Control is UISizeDot))
- {
- this._HashUISizeKnob.Add(e.Control, new UISizeKnob(e.Control));
- //点击控件的时候,显示控件的选择
- e.Control.Click += new EventHandler(Control_Click);
- }
- }
- void Control_Click(object sender, EventArgs e)
- {
- //寿险清除已经选择的控件
- foreach (UISizeKnob knob in this._HashUISizeKnob.Values)
- {
- knob.ShowUISizeDots(false);
- }
- try
- {
- ((UISizeKnob)this._HashUISizeKnob[sender]).ShowUISizeDots(true);
- }
- catch { }
- }
- 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();
- }
- }
以上就是实现控件选择的关键部分,各位结合上面一篇,应该是很容易理解的,代码都是可运行的,自己拷贝过去就可以了。
相关文章:
C#基础系列:开发自己的窗体设计器(在容器上拖动鼠标增加控件)