WinForm C#: Simple Runtime Control ReSizing and Dragging & Moving Class

/*
C#: Simple Runtime Control Sizing and Dragging Class

首先声明如下代码改自
CodeProject 同名文章(鸣谢原作者 Jim Korovessis: ~!@#$%^&*):
http://www.codeproject.com/cs/miscctrl/CSPickBoxSample1.asp

我做了如下改造:

1.增加一个 ArrayList 存储 WiredControls
2.增加 UnWireAllWiredControls() 方法,用于切换到控件"非设计"状态
3.增加 WireControls() 方法,用于到控件"设计"状态
4.增加支持键盘移动或改大小

我会把我更改的代码高亮显示!
*/


//You Can Save below code to one File named Noname1.cs
//execute "csc noname1.cs" Directly!

//PickBox
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;

//namespace PickBoxTest
//{
 /// <summary>
 /// This class implements sizing and moving functions for
 /// runtime editing of graphic controls
 /// </summary>
public class PickBox
{
 //////////////////////////////////////////////////////////////////
 // PRIVATE CONSTANTS AND VARIABLES
 //////////////////////////////////////////////////////////////////

 private const int BOX_SIZE = 8;
 private Color BOX_COLOR = Color.White;
// private ContainerControl m_container;
 private  Control m_control;
 private Label[] lbl = new Label[8];
 private int startl;
 private int startt;
 private int startw;
 private int starth;
 private int startx;
 private int starty;
 private bool dragging;
 private Cursor[] arrArrow = new Cursor[]
            {
             Cursors.SizeNWSE
             ,Cursors.SizeNS
             ,Cursors.SizeNESW
             ,Cursors.SizeWE
             ,Cursors.SizeNWSE
             ,Cursors.SizeNS
             ,Cursors.SizeNESW
             ,Cursors.SizeWE
            };
 private Cursor oldCursor;

 private const int MIN_SIZE = 20;

 private Form ParentForm;

 //
 // Constructor creates 8 sizing handles & wires mouse events
 // to each that implement sizing functions
 //
 public PickBox()
 {
  for (int i = 0; i < 8; i++)
  {
   lbl[i] = new Label();
   lbl[i].TabIndex = i;
   lbl[i].FlatStyle = 0 ;
   lbl[i].BorderStyle = BorderStyle.FixedSingle;
   lbl[i].BackColor = BOX_COLOR;
   lbl[i].Cursor = arrArrow[i];
   lbl[i].Text = "";
   lbl[i].BringToFront();
   lbl[i].MouseDown += new MouseEventHandler(this.lbl_MouseDown);
   lbl[i].MouseMove += new MouseEventHandler(this.lbl_MouseMove);
   lbl[i].MouseUp += new MouseEventHandler(this.lbl_MouseUp);
  }
 }

 //////////////////////////////////////////////////////////////////
 // PUBLIC METHODS
 //////////////////////////////////////////////////////////////////

 //
 // Wires a Click event handler to the passed Control
 // that attaches a pick box to the control when it is clicked
 //

 //add by playyuer@Microshaoft.com
 // Store Controls for Design (resize or move)
 private ArrayList WiredControls = new ArrayList();

 public void WireControl(Control ctl)
 {
  //add by playyuer@Microshaoft.com
  //Store Wired Controls
  WiredControls.Add(ctl);

  if (ParentForm != ctl.FindForm())
  {
   ParentForm = ctl.FindForm();
   //ParentForm.KeyPreview = true;
  }

  ctl.Click += new EventHandler(this.SelectControl);

  //add by playyuer@Microshaoft.com
  //support resizing or moving control by Keyboard
  ctl.KeyDown += new KeyEventHandler(ctl_KeyDown);
 }

 //add by playyuer@Microshaoft.com
 //for Wire Controls that in WiredControls ArrayList
 public void WireControls()
 {
  if (WiredControls.Count > 0)
  {
   System.Collections.IEnumerator ie = WiredControls.GetEnumerator();
   while ( ie.MoveNext() )
   {
    this.WireControl((Control) ie.Current);
   }
  }
  
 }

 //add by playyuer@Microshaoft.com
 //for UnWire Controls that in WiredControls ArrayList
 public void UnWireAllWiredControls()
 {

  System.Collections.IEnumerator ie = WiredControls.GetEnumerator();
  Control c;
  while ( ie.MoveNext() )
  {
   c = (Control) ie.Current;
   c.Click -= new EventHandler(this.SelectControl);
   c.KeyDown -= new KeyEventHandler(ctl_KeyDown);

   if (m_control is Control)
   {
    m_control.Cursor = oldCursor;
    //Remove event any pre-existing event handlers appended by this class
    m_control.MouseDown -= new MouseEventHandler(this.ctl_MouseDown);
    m_control.MouseMove -= new MouseEventHandler(this.ctl_MouseMove);
    m_control.MouseUp -= new MouseEventHandler(this.ctl_MouseUp);

    m_control.KeyDown -= new KeyEventHandler(ctl_KeyDown);

    m_control = null;
   }
  }
  this.HideHandles();
 }

 /////////////////////////////////////////////////////////////////
 // PRIVATE METHODS
 /////////////////////////////////////////////////////////////////

 //
 // Attaches a pick box to the sender Control
 //
 private void SelectControl(object sender, EventArgs e)
 {

  if (m_control is Control)
  {
   m_control.Cursor = oldCursor;

   //Remove event any pre-existing event handlers appended by this class
   m_control.MouseDown -= new MouseEventHandler(this.ctl_MouseDown);
   m_control.MouseMove -= new MouseEventHandler(this.ctl_MouseMove);
   m_control.MouseUp -= new MouseEventHandler(this.ctl_MouseUp);

 

   m_control = null;
  }

  m_control = (Control) sender;

  //Add event handlers for moving the selected control around
  m_control.MouseDown += new MouseEventHandler(this.ctl_MouseDown);
  m_control.MouseMove += new MouseEventHandler(this.ctl_MouseMove);
  m_control.MouseUp += new MouseEventHandler(this.ctl_MouseUp);


  //Add sizing handles to Control's container (Form or PictureBox)
  for (int i = 0; i < 8; i++)
  {
   m_control.Parent.Controls.Add(lbl[i]);
   lbl[i].BringToFront();
  }

  //Position sizing handles around Control
  MoveHandles();

  //Display sizing handles
  ShowHandles();

  oldCursor = m_control.Cursor;
  m_control.Cursor = Cursors.SizeAll;
 }

 public void Remove()
 {
  HideHandles();
  m_control.Cursor = oldCursor;
 }

 private void ShowHandles()
 {
  if (m_control !=null)
  {
   for (int i = 0; i < 8; i++)
   {
    lbl[i].Visible = true;
   }
  }
 }

 private void HideHandles()
 {
  for (int i = 0; i < 8; i++)
  {
   lbl[i].Visible = false;
  }
 }

 private void MoveHandles()
 {
  int sX = m_control.Left - BOX_SIZE;
  int sY = m_control.Top - BOX_SIZE;
  int sW = m_control.Width + BOX_SIZE;
  int sH = m_control.Height + BOX_SIZE;
  int hB = BOX_SIZE / 2;

  int[] arrPosX = new int[]
         {
          sX+hB, sX + sW / 2
          ,sX + sW-hB
          ,sX + sW-hB
          ,sX + sW-hB
          ,sX + sW / 2
          ,sX+hB, sX+hB
         };
  int[] arrPosY = new int[]
         {
          sY+hB
          ,sY+hB
          ,sY+hB
          ,sY + sH / 2
          , sY + sH-hB
          ,sY + sH-hB
          ,sY + sH-hB
          ,sY + sH / 2
         };
  for (int i = 0; i < 8; i++)
   lbl[i].SetBounds(arrPosX[i], arrPosY[i], BOX_SIZE, BOX_SIZE);
 }

 /////////////////////////////////////////////////////////////////
 // MOUSE EVENTS THAT IMPLEMENT SIZING OF THE PICKED CONTROL
 /////////////////////////////////////////////////////////////////

 //
 // Store control position and size when mouse button pushed over
 // any sizing handle
 //
 private void lbl_MouseDown(object sender, MouseEventArgs e)
 {
  dragging = true;
  startl = m_control.Left;
  startt = m_control.Top;
  startw = m_control.Width;
  starth = m_control.Height;
  HideHandles();
 }

 //
 // Size the picked control in accordance with sizing handle being dragged
 // 0   1   2
 //  7       3
 //  6   5   4
 //
 private void lbl_MouseMove(object sender, MouseEventArgs e)
 {
  int l = m_control.Left;
  int w = m_control.Width;
  int t = m_control.Top;
  int h = m_control.Height;
  if (dragging)
  {
   switch (((Label)sender).TabIndex)
   {
    case 0 : // Dragging top-left sizing box
     l = startl + e.X < startl + startw - MIN_SIZE ? startl + e.X : startl + startw - MIN_SIZE;
     t = startt + e.Y < startt + starth - MIN_SIZE ? startt + e.Y : startt + starth - MIN_SIZE;
     w = startl + startw - m_control.Left;
     h = startt + starth - m_control.Top;
     break;
    case 1 : // Dragging top-center sizing box
     t = startt + e.Y < startt + starth - MIN_SIZE ? startt + e.Y : startt + starth - MIN_SIZE;
     h = startt + starth - m_control.Top;
     break;
    case 2 : // Dragging top-right sizing box
     w = startw + e.X > MIN_SIZE ? startw + e.X : MIN_SIZE;
     t = startt + e.Y < startt + starth - MIN_SIZE ? startt + e.Y : startt + starth - MIN_SIZE;
     h = startt + starth - m_control.Top;
     break;
    case 3 : // Dragging right-middle sizing box
     w = startw + e.X > MIN_SIZE ? startw + e.X : MIN_SIZE;
     break;
    case 4 : // Dragging right-bottom sizing box
     w = startw + e.X > MIN_SIZE ? startw + e.X : MIN_SIZE;
     h = starth + e.Y > MIN_SIZE ? starth + e.Y : MIN_SIZE;
     break;
    case 5 : // Dragging center-bottom sizing box
     h = starth + e.Y > MIN_SIZE ? starth + e.Y : MIN_SIZE;
     break;
    case 6 : // Dragging left-bottom sizing box
     l = startl + e.X < startl + startw - MIN_SIZE ? startl + e.X : startl + startw - MIN_SIZE;
     w = startl + startw - m_control.Left;
     h = starth + e.Y > MIN_SIZE ? starth + e.Y : MIN_SIZE;
     break;
    case 7 : // Dragging left-middle sizing box
     l = startl + e.X < startl + startw - MIN_SIZE ? startl + e.X : startl + startw - MIN_SIZE;
     w = startl + startw - m_control.Left;
     break;
   }
   l = (l < 0)? 0 : l;
   t = (t < 0)? 0 : t;
   m_control.SetBounds(l,t,w,h);
  }
 }

 //
 // Display sizing handles around picked control once sizing has completed
 //
 private void lbl_MouseUp(object sender, MouseEventArgs e)
 {
  dragging = false;
  MoveHandles();
  ShowHandles();
 }

 /////////////////////////////////////////////////////////////////
 // MOUSE EVENTS THAT MOVE THE PICKED CONTROL AROUND THE FORM
 /////////////////////////////////////////////////////////////////

 //
 // Get mouse pointer starting position on mouse down and hide sizing handles
 //
 private void ctl_MouseDown(object sender, MouseEventArgs e)
 {
  dragging = true;
  startx = e.X;
  starty = e.Y;
  HideHandles();
 }

 //
 // Reposition the dragged control
 //
 private void ctl_MouseMove(object sender, MouseEventArgs e)
 {
  if (dragging)
  {
   int l =  m_control.Left + e.X - startx;
   int t = m_control.Top + e.Y - starty;
   int w = m_control.Width;
   int h = m_control.Height;

   l = (l < 0)? 0 : ((l + w > m_control.Parent.ClientRectangle.Width)? m_control.Parent.ClientRectangle.Width - w : l);
   t = (t < 0)? 0 : ((t + h > m_control.Parent.ClientRectangle.Height)? m_control.Parent.ClientRectangle.Height - h : t);
   m_control.Left = l;
   m_control.Top = t;
  }
 }

 //
 // Display sizing handles around picked control once dragging has completed
 //
 private void ctl_MouseUp(object sender, MouseEventArgs e)
 {
  dragging = false;
  MoveHandles();
  ShowHandles();
 }

 private void ctl_KeyDown(object sender, KeyEventArgs e)
 {
  if (e.Modifiers == Keys.Control)
  {
   switch (e.KeyCode)
   {
    case Keys.Right :
     m_control.Left += 10;
     break;
    case Keys.Left :
     m_control.Left -= 10;
     break;
    case Keys.Up :
     m_control.Top -= 10;
     break;
    case Keys.Down :
     m_control.Top += 10;
     break;
   }
   MoveHandles();
  }
  else if (e.Modifiers == Keys.Shift)
  {
   switch (e.KeyCode)
   {
    case Keys.Right :
     m_control.Width += 10;
     break;
    case Keys.Left :
     m_control.Width -= 10;
     break;
    case Keys.Up :
     m_control.Height -= 10;
     break;
    case Keys.Down :
     m_control.Height += 10;
     break;
   }
   MoveHandles();
  }
  //((Control)sender).Select();
 }
}
//}

//==================================================

//WinForm Test
//Form1
//using System;
//using System.Drawing;
//using System.Collections;
//using System.ComponentModel;
//using System.Windows.Forms;
//using System.Data;

//namespace WindowsApplication1
//{
 /// <summary>
 /// Form1 的摘要说明。
 /// </summary>
public class Form1 : System.Windows.Forms.Form
{
 private System.Windows.Forms.Button button1;
 private System.Windows.Forms.TextBox textBox1;
 private System.Windows.Forms.DataGrid dataGrid1;
 /// <summary>
 /// 必需的设计器变量。
 /// </summary>
 private System.ComponentModel.Container components = null;
 private System.Windows.Forms.DataGrid dataGrid2;
 private System.Windows.Forms.Button button2;

 //add by playyuer@Microshaoft.com
 private PickBox pb = new PickBox();
 public Form1()
 {
  //
  // Windows 窗体设计器支持所必需的
  //
  InitializeComponent();

  //
  // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
  //
 }

 /// <summary>
 /// 清理所有正在使用的资源。
 /// </summary>
 protected override void Dispose( bool disposing )
 {
  if( disposing )
  {
   if (components != null)
   {
    components.Dispose();
   }
  }
  base.Dispose( disposing );
 }

 #region Windows 窗体设计器生成的代码
 /// <summary>
 /// 设计器支持所需的方法 - 不要使用代码编辑器修改
 /// 此方法的内容。
 /// </summary>
 private void InitializeComponent()
 {
  this.button1 = new System.Windows.Forms.Button();
  this.textBox1 = new System.Windows.Forms.TextBox();
  this.dataGrid1 = new System.Windows.Forms.DataGrid();
  this.dataGrid2 = new System.Windows.Forms.DataGrid();
  this.button2 = new System.Windows.Forms.Button();
  ((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).BeginInit();
  ((System.ComponentModel.ISupportInitialize)(this.dataGrid2)).BeginInit();
  this.SuspendLayout();
  //
  // button1
  //
  this.button1.Location = new System.Drawing.Point(24, 16);
  this.button1.Name = "button1";
  this.button1.Size = new System.Drawing.Size(104, 40);
  this.button1.TabIndex = 0;
  this.button1.Text = "切换";
  this.button1.Click += new System.EventHandler(this.button1_Click);
  //
  // textBox1
  //
  this.textBox1.Location = new System.Drawing.Point(144, 32);
  this.textBox1.Name = "textBox1";
  this.textBox1.Size = new System.Drawing.Size(128, 21);
  this.textBox1.TabIndex = 1;
  this.textBox1.Text = "textBox1";
  //
  // dataGrid1
  //
  this.dataGrid1.DataMember = "";
  this.dataGrid1.HeaderForeColor = System.Drawing.SystemColors.ControlText;
  this.dataGrid1.Location = new System.Drawing.Point(32, 80);
  this.dataGrid1.Name = "dataGrid1";
  this.dataGrid1.Size = new System.Drawing.Size(160, 72);
  this.dataGrid1.TabIndex = 2;
  //
  // dataGrid2
  //
  this.dataGrid2.DataMember = "";
  this.dataGrid2.HeaderForeColor = System.Drawing.SystemColors.ControlText;
  this.dataGrid2.Location = new System.Drawing.Point(64, 208);
  this.dataGrid2.Name = "dataGrid2";
  this.dataGrid2.Size = new System.Drawing.Size(168, 64);
  this.dataGrid2.TabIndex = 3;
  //
  // button2
  //
  this.button2.Location = new System.Drawing.Point(280, 144);
  this.button2.Name = "button2";
  this.button2.Size = new System.Drawing.Size(152, 56);
  this.button2.TabIndex = 4;
  this.button2.Text = "button2";
  //
  // Form1
  //
  this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
  this.ClientSize = new System.Drawing.Size(608, 381);
  this.Controls.Add(this.button2);
  this.Controls.Add(this.dataGrid2);
  this.Controls.Add(this.dataGrid1);
  this.Controls.Add(this.textBox1);
  this.Controls.Add(this.button1);
  this.Name = "Form1";
  this.Text = "Form1";
  this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
  this.Load += new System.EventHandler(this.Form1_Load);
  ((System.ComponentModel.ISupportInitialize)(this.dataGrid1)).EndInit();
  ((System.ComponentModel.ISupportInitialize)(this.dataGrid2)).EndInit();
  this.ResumeLayout(false);

 }
 #endregion

 /// <summary>
 /// 应用程序的主入口点。
 /// </summary>
 [STAThread]
 static void Main()
 {
  Application.Run(new Form1());
 }

 private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
 {

 }

 bool b = false;
 
 private void button1_Click(object sender, System.EventArgs e)
 {
  if (!b) 
  {
   this.Text = "Design Time";

   pb.WireControl(dataGrid1);
   pb.WireControl(textBox1);
   pb.WireControl(button2);
   pb.WireControl(dataGrid2);

  }
  else
  {
   this.Text = "Run Time";
   pb.UnWireAllWiredControls();
  }
  b = !b;
 }

 private void Form1_Load(object sender, System.EventArgs e)
 {

 }
}
//}

posted @ 2004-10-26 22:14  于斯人也  阅读(306)  评论(0编辑  收藏  举报