一、整体布局构思
采用 Panel 和 一些其他控件bt(例如:button、lable或者一些自定义的控件)做出的一个平面图。主要功能包含:1> Panel 上 bt 的自动加载,bt的事件绑定;
2> Panel 与 bt 的同步缩放,滚动条事件的处理;
3> Panel 上 bt 的拖拽,以及对齐线的自动保存处理;
二、Panel的基本配置。
//窗体加载事件
private void Frm_Load(object sender, EventArgs e)
{
//如果面板内的内容超出了面板的可见范围,将自动滚动面板
this.PanShow.AutoScroll = true;
}
三、Bt的自动加载。
private void BuildCrib()
{
// 清除PanShow画布上所有控件
this.PanShow.Controls.Clear();
//假如咱们从后台数据库中拿到的建筑信息是DataTable
for (int i = 0; i < dt.Rows.Count; i++)
{
// 自定义后面使用,咱们现在使用Winfrm源生控件Button
Button cfb = new Button();
// 设置其Size(宽、高)
cfb.Size = new Size(Width,Height);
// 设置其Location(x,y)
cfb.Location = new Point(x,y);
// 设置其Name(唯一值)
cfb.Name="";
// 设置其显示文本
cfs.text="";
// 设置其背景颜色
cfb.BackColor= Color.LightBlue;
// 设置其可以拖拽
cfb.AllowDrop = true;
// 设置其字体、颜色、阴影面积.....
//...
// 设置其点击或者其他事件
cfb.MouseDown += new MouseEventHandler(Control_MouseDown);
cfb.MouseMove += new MouseEventHandler(Control_MouseMove);
cfb.Click += new MouseEventHandler(Control_Click);
// 将其添加到画布
PanShow.Controls.Add(cfb);
}
}
四、Bt的拖拽。
[DllImport("user32.dll", EntryPoint = "ReleaseCapture")]
public static extern void ReleaseCapture();
[DllImport("user32.dll", EntryPoint = "SendMessage")]
public static extern void SendMessage(int hwnd, int wMsg, int wParam, int lParam);
private const int WM_SYSCOMMAND = 0x0112;//点击窗口左上角那个图标时的系统信息
private const int WM_MOVING = 0x216;//鼠标移动消息
private const int SC_MOVE = 0xF010;//移动信息
private const int HTCAPTION = 0x0002;//表示鼠标在窗口标题栏时的系统信息
private const int WM_NCHITTEST = 0x84;//鼠标在窗体客户区(除了标题栏和边框以外的部分)时发送的消息
private const int HTCLIENT = 0x1;//表示鼠标在窗口客户区的系统消息
private const int SC_MAXIMIZE = 0xF030;//最大化信息
private const int SC_MINIMIZE = 0xF020;//最小化信息
private void Control_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Control control = (Control)sender;
control.BringToFront(); //将控件置于顶层
ReleaseCapture();
SendMessage((int)control.Handle, 0xA1, 2, 0);
control.BackColor = Color.Plum;
}
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_MOVING: //如果鼠标移
base.WndProc(ref m);//调用基类的窗口过程——WndProc方法处理这个消息
if (m.Result == (IntPtr)HTCLIENT)//如果返回的是HTCLIENT
{
m.Result = (IntPtr)HTCAPTION;//把它改为HTCAPTION
return;//直接返回退出方法
}
break;
}
base.WndProc(ref m);//如果不是鼠标移动或单击消息就调用基类的窗口过程进行处理
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
ReleaseCapture();
Control control = Control.FromHandle(this.PanShow.Handle);
SendMessage(control.Left, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
}
base.OnMouseMove(e);
}
private void Control_Click(object sender, EventArgs e)
{
Button bt = sender as Button;
bt.BackColor = Color.Plum;
}
五、Panle滚动条事件。
Point scrollPosition=new Point(0,0);//滚动条初始值
private void PanShow_Scroll(object sender, ScrollEventArgs e)
{
// 获取Panel控件的滚动位置
scrollPosition.Y = PanShow.VerticalScroll.Value;
scrollPosition.X = PanShow.HorizontalScroll.Value;
}
六、Bt的保存。
private void btnSave_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
{
//获取PanShow中所有的控件
Control.ControlCollection controls = this.PanShow.Controls;
foreach (Control control in controls)
{
//只要Button类型的控件
if (control is Button)
{
Button btn = (Button)control;
if().......//根据实际情况写
当前坐标x= control.Location.X + scrollPosition.X;
}
}
}
七、拖拽对齐网格线绘制。
private void PanShow_Paint(object sender, PaintEventArgs e)
{
// 清除多余线
e.Graphics.Clear(PanShow.BackColor);
}
public void Grid_Line(Button bt)
{
//可以容忍最大值
int tolerance = 1;
// 获取Panel的Graphics对象
Graphics g = this.PanShow.CreateGraphics();
// 清除绘图区域
g.Clear(this.PanShow.BackColor);
//获取目的控件坐标位置
Point location = bt.Location;
// 检查周围Button的坐标,如果相差5px,在其左下角绘制十字线
foreach (Control neighbor in this.PanShow.Controls)
{
if (neighbor is Button && neighbor != bt)
{
Button neighborButton = (Button)neighbor;
Point neighborLocation = neighborButton.Location;
#region 纵向
if (Math.Abs(location.X - neighborLocation.X) <= tolerance)
{
// 使用Graphics类绘制十字线 --左上角
using (Pen pen = new Pen(Color.Red, 2))
{
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
pen.DashPattern = new float[] { 4.0F, 2.0F, 1.0F, 3.0F }; // 设置虚线的模式
PanShow.CreateGraphics().DrawLine(pen, location.X - 0, location.Y - bt.Height, location.X - 0, location.Y + 2*bt.Height);
}
// 使用Graphics类绘制十字线 --右上角
using (Pen pen = new Pen(Color.Red, 2))
{
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
pen.DashPattern = new float[] { 4.0F, 2.0F, 1.0F, 3.0F }; // 设置虚线的模式
PanShow.CreateGraphics().DrawLine(pen, location.X + bt.Width + 0, location.Y - bt.Height, location.X + bt.Width + 0, location.Y + 2*bt.Height);
}
}
#endregion
#region 横向
if (Math.Abs(location.Y - neighborLocation.Y) <= tolerance)
{
// 使用Graphics类绘制十字线
using (Pen pen = new Pen(Color.Red, 2))
{
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
pen.DashPattern = new float[] { 4.0F, 2.0F, 1.0F, 3.0F }; // 设置虚线的模式
PanShow.CreateGraphics().DrawLine(pen, location.X - bt.Width, location.Y - 0, location.X + 2*bt.Width, location.Y - 0);
}
// 使用Graphics类绘制十字线
using (Pen pen = new Pen(Color.Red, 2))
{
pen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
pen.DashPattern = new float[] { 4.0F, 2.0F, 1.0F, 3.0F }; // 设置虚线的模式
PanShow.CreateGraphics().DrawLine(pen, location.X - bt.Width, location.Y +bt.Height+ 0, location.X + 2 * bt.Width, location.Y +bt.Height+ 0);
}
}
#endregion
}
}
}
八、自定义控件的制作
后续咱们来日方长.......