C#winform自定义控件模拟设计时界面鼠标移动和调节大小、选中效果

要想玩转Winform自定义控件需要对GDI+非常熟悉,对常用的控件有一些了解,好选择合适的基类控件来简化。
要点说明及代码
1)定义接口:
using System;
using System.Windows.Forms; namespace GDIPrinterDriver
{
/// <summary>
/// 模板元素接口
/// </summary>
public interface ILabelDesignElement
{
/// <summary>
/// PrintData/codeContext里的字段,{} []
/// </summary>
string 动态内容 { get; set; }
/// <summary>
/// 是否被选中
/// </summary>
bool DesignSelected { get; set; }
/// <summary>
/// 选择状态发生改变
/// </summary>
event Action<object, bool> SelectedStatusChange;
/// <summary>
/// 本控件被选中时键盘方向键被按下
/// </summary>
/// <param name="keyData"></param>
void KeysChangedLocation(Keys keyData);
}
}
2)控件基类实现:
using GDIPrinterDriver;
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Windows.Forms; namespace GDILabelDesigner
{
/// <summary>
/// 设计时控件基类
/// </summary>
public abstract class DesignCellControl : PictureBox, ILabelDesignElement
{
#region 鼠标移动和缩放
private enum EnumMousePointPosition
{
MouseSizeNone = , //'无
MouseSizeRight = , //'拉伸右边框
MouseSizeLeft = , //'拉伸左边框
MouseSizeBottom = , //'拉伸下边框
MouseSizeTop = , //'拉伸上边框
MouseSizeTopLeft = , //'拉伸左上角
MouseSizeTopRight = , //'拉伸右上角
MouseSizeBottomLeft = , //'拉伸左下角
MouseSizeBottomRight = , //'拉伸右下角
MouseDrag = // '鼠标拖动
}
const int Band = ;
const int MinWidth = ;
const int MinHeight = ;
private EnumMousePointPosition m_MousePointPosition;
private Point p, p1;
private EnumMousePointPosition MousePointPosition(Size size, System.Windows.Forms.MouseEventArgs e)
{ if ((e.X >= - * Band) | (e.X <= size.Width) | (e.Y >= - * Band) | (e.Y <= size.Height))
{
if (e.X < Band)
{
if (e.Y < Band) { return EnumMousePointPosition.MouseSizeTopLeft; }
else
{
if (e.Y > - * Band + size.Height)
{ return EnumMousePointPosition.MouseSizeBottomLeft; }
else
{ return EnumMousePointPosition.MouseSizeLeft; }
}
}
else
{
if (e.X > - * Band + size.Width)
{
if (e.Y < Band)
{ return EnumMousePointPosition.MouseSizeTopRight; }
else
{
if (e.Y > - * Band + size.Height)
{ return EnumMousePointPosition.MouseSizeBottomRight; }
else
{ return EnumMousePointPosition.MouseSizeRight; }
}
}
else
{
if (e.Y < Band)
{ return EnumMousePointPosition.MouseSizeTop; }
else
{
if (e.Y > - * Band + size.Height)
{ return EnumMousePointPosition.MouseSizeBottom; }
else
{ return EnumMousePointPosition.MouseDrag; }
}
}
}
}
else
{ return EnumMousePointPosition.MouseSizeNone; }
}
#endregion
public bool DesignSelected
{
get
{
return designSelected;
}
set
{
designSelected = value;
Invalidate();
}
}
private bool designSelected = false;
public DynamicMapProperty DynamicMapProperty { get; set; }
public StaticMapProperty StaticMapProperty { get; set; }
public string 动态内容 { get; set; }
public RoteDescription RoteDescription { get; set; }
/// <summary>
/// 被选中,获取到焦点的事件
/// </summary>
public event Action<object, bool> SelectedStatusChange;
protected override void OnClick(EventArgs e)
{
DesignSelected = true;
SelectedStatusChange?.Invoke(this, DesignSelected);
}
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
double d = 1.068D;
if (e.Delta > && DesignSelected)
{
this.Size = new Size((int)(this.Size.Width * d), (int)(this.Size.Height * d));
}
else
{
this.Size = new Size((int)(this.Size.Width / d), (int)(this.Size.Height / d));
}
}
protected override void OnMouseDown(MouseEventArgs e)
{
p.X = e.X;
p.Y = e.Y;
p1.X = e.X;
p1.Y = e.Y;
}
protected override void OnMouseUp(MouseEventArgs e)
{
m_MousePointPosition = EnumMousePointPosition.MouseSizeNone;
this.Cursor = Cursors.Arrow;
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
switch (m_MousePointPosition)
{
#region 位置计算
case EnumMousePointPosition.MouseDrag:
Left = Left + e.X - p.X;
Top = Top + e.Y - p.Y;
break;
case EnumMousePointPosition.MouseSizeBottom:
Height = Height + e.Y - p1.Y;
p1.X = e.X;
p1.Y = e.Y; //'记录光标拖动的当前点
break;
case EnumMousePointPosition.MouseSizeBottomRight:
Width = Width + e.X - p1.X;
Height = Height + e.Y - p1.Y;
p1.X = e.X;
p1.Y = e.Y; //'记录光标拖动的当前点
break;
case EnumMousePointPosition.MouseSizeRight:
Width = Width + e.X - p1.X;
Height = Height + e.Y - p1.Y;
p1.X = e.X;
p1.Y = e.Y; //'记录光标拖动的当前点
break;
case EnumMousePointPosition.MouseSizeTop:
Top = Top + (e.Y - p.Y);
Height = Height - (e.Y - p.Y);
break;
case EnumMousePointPosition.MouseSizeLeft:
Left = Left + e.X - p.X;
Width = Width - (e.X - p.X);
break;
case EnumMousePointPosition.MouseSizeBottomLeft:
Left = Left + e.X - p.X;
Width = Width - (e.X - p.X);
Height = Height + e.Y - p1.Y;
p1.X = e.X;
p1.Y = e.Y; //'记录光标拖动的当前点
break;
case EnumMousePointPosition.MouseSizeTopRight:
Top = Top + (e.Y - p.Y);
Width = Width + (e.X - p1.X);
Height = Height - (e.Y - p.Y);
p1.X = e.X;
p1.Y = e.Y; //'记录光标拖动的当前点
break;
case EnumMousePointPosition.MouseSizeTopLeft:
Left = Left + e.X - p.X;
Top = Top + (e.Y - p.Y);
Width = Width - (e.X - p.X);
Height = Height - (e.Y - p.Y);
break;
default:
break;
#endregion
}
if (Width < MinWidth) Width = MinWidth;
if (Height < MinHeight) Height = MinHeight;
if (Tag != null)
{
if (Tag is ImageElementNode)
{
var tag = Tag as ImageElementNode;
tag.Location = Location;
}
else if (Tag is BarcodeElementNode)
{
var tag = Tag as BarcodeElementNode;
tag.Location = Location;
}
else if (Tag is TextBoxElementNode)
{
var tag = Tag as TextBoxElementNode;
tag.Location = Location;
}
}
}
else
{
m_MousePointPosition = MousePointPosition(Size, e);
switch (m_MousePointPosition)
{
#region 改变光标
case EnumMousePointPosition.MouseSizeNone:
this.Cursor = Cursors.Arrow; //'箭头
break;
case EnumMousePointPosition.MouseDrag:
this.Cursor = Cursors.SizeAll; //'四方向
break;
case EnumMousePointPosition.MouseSizeBottom:
this.Cursor = Cursors.SizeNS; //'南北
break;
case EnumMousePointPosition.MouseSizeTop:
this.Cursor = Cursors.SizeNS; //'南北
break;
case EnumMousePointPosition.MouseSizeLeft:
this.Cursor = Cursors.SizeWE; //'东西
break;
case EnumMousePointPosition.MouseSizeRight:
this.Cursor = Cursors.SizeWE; //'东西
break;
case EnumMousePointPosition.MouseSizeBottomLeft:
this.Cursor = Cursors.SizeNESW; //'东北到南西
break;
case EnumMousePointPosition.MouseSizeBottomRight:
this.Cursor = Cursors.SizeNWSE; //'东南到西北
break;
case EnumMousePointPosition.MouseSizeTopLeft:
this.Cursor = Cursors.SizeNWSE; //'东南到西北
break;
case EnumMousePointPosition.MouseSizeTopRight:
this.Cursor = Cursors.SizeNESW; //'东北到南西
break;
default:
break;
#endregion
}
}
} /// <summary>
/// 绘制方框
/// </summary>
/// <param name="g"></param>
protected void DrawSelectedStatus(Graphics g)
{
Rectangle rect = ClientRectangle;
rect.Inflate(-, -);
using (Pen p = new Pen(Brushes.Black, ))
{
p.DashStyle = DashStyle.Dot;
p.DashStyle = DashStyle.Solid;
//8个方块
g.FillRectangle(Brushes.White, new Rectangle(rect.Left - , rect.Top - , , ));
g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width / - , rect.Top - , , ));
g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width, rect.Top - , , ));
g.FillRectangle(Brushes.White, new Rectangle(rect.Left - , rect.Top + rect.Height / - , , ));
g.FillRectangle(Brushes.White, new Rectangle(rect.Left - , rect.Top + rect.Height, , ));
g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height / - , , ));
g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width / - , rect.Top + rect.Height, , ));
g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height, , ));
g.DrawRectangle(p, new Rectangle(rect.Left - , rect.Top - , , ));
g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width / - , rect.Top - , , ));
g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width, rect.Top - , , ));
g.DrawRectangle(p, new Rectangle(rect.Left - , rect.Top + rect.Height / - , , ));
g.DrawRectangle(p, new Rectangle(rect.Left - , rect.Top + rect.Height, , ));
g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height / - , , ));
g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width / - , rect.Top + rect.Height, , ));
g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height, , ));
}
}
/// <summary>
/// 旋转图片
/// </summary>
/// <param name="bmp">源图</param>
/// <param name="angle">角度</param>
/// <param name="bkColor">背景色</param>
/// <returns></returns>
protected Bitmap ImageRotate(Bitmap bmp, float angle, Color bkColor)
{
int w = bmp.Width + ;
int h = bmp.Height + ;
PixelFormat pf;
if (bkColor == Color.Transparent)
{
pf = PixelFormat.Format32bppArgb;
}
else
{
pf = bmp.PixelFormat;
}
Bitmap tmp = new Bitmap(w, h, pf);
Graphics g = Graphics.FromImage(tmp);
g.Clear(bkColor);
g.DrawImageUnscaled(bmp, , );
g.Dispose();
GraphicsPath path = new GraphicsPath();
path.AddRectangle(new RectangleF(0f, 0f, w, h));
Matrix mtrx = new Matrix();
mtrx.Rotate(angle);
RectangleF rct = path.GetBounds(mtrx);
Bitmap dst = new Bitmap((int)rct.Width, (int)rct.Height, pf);
g = Graphics.FromImage(dst);
g.Clear(bkColor);
g.TranslateTransform(-rct.X, -rct.Y);
g.RotateTransform(angle);
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImageUnscaled(tmp, , );
g.Dispose();
tmp.Dispose();
return dst;
}
/// <summary>
/// 响应键盘光标键
/// </summary>
/// <param name="keyData"></param>
public virtual void KeysChangedLocation(Keys keyData)
{
if (keyData == Keys.Up)
{
Top -= ;
}
if (keyData == Keys.Down)
{
Top += ;
}
if (keyData == Keys.Left)
{
Left -= ;
}
if (keyData == Keys.Right)
{
Left += ;
}
if (Tag != null)
{
if (Tag is ImageElementNode)
{
var tag = Tag as ImageElementNode;
tag.Location = Location;
}
else if (Tag is BarcodeElementNode)
{
var tag = Tag as BarcodeElementNode;
tag.Location = Location;
}
else if (Tag is TextBoxElementNode)
{
var tag = Tag as TextBoxElementNode;
tag.Location = Location;
}
}
}
}
}
C#winform自定义控件模拟设计时界面鼠标移动和调节大小、选中效果的更多相关文章
- winform窗体运行时的大小和设计时不一致
		
窗体设置的尺寸为1946*850,而电脑分辨率是1920*1280 按说宽度已经超过屏幕大小很多了,应该显示占满屏幕宽度才对,但是运行时宽度只有设计时的一半 高度最多只能是1946像素,再拉大也不管用 ...
 - C# 自定义控件容器,设计时可添加控件
		
本分步指南介绍在将 UserControl 放在 Windows 窗体上之后,如何将 UserControl 对象用作设计时控件容器.可能会有这样的情况:您想将一个控件拖到 UserControl 中 ...
 - Winform自定义控件实例
		
本文转自http://www.cnblogs.com/hahacjh/archive/2010/04/29/1724125.html 写在前面: .Net已经成为许多软件公司的选择,而.Net自定义W ...
 - WPF案例(二)模拟Apple OS 界面前后180度反转
		
原文:WPF案例(二)模拟Apple OS 界面前后180度反转 我们在设计应用程序界面的时候,为了充分利用界面空间,住住需要灵活的界面布局方式,比如可以在界面正面空间上定义一个Chart,背面空间上 ...
 - (三十)c#Winform自定义控件-文本框(三)
		
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. 开源地址:https://gitee.com/kwwwvagaa/net_winform_custom_control ...
 - (六十九)c#Winform自定义控件-垂直滚动条
		
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
 - (七十三)c#Winform自定义控件-资源加载窗体
		
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
 - (七十九)c#Winform自定义控件-导航菜单
		
前提 入行已经7,8年了,一直想做一套漂亮点的自定义控件,于是就有了本系列文章. GitHub:https://github.com/kwwwvagaa/NetWinformControl 码云:ht ...
 - (原创)[C#] 一步一步自定义拖拽(Drag&Drop)时的鼠标效果:(一)基本原理及基本实现
		
一.前言 拖拽(Drag&Drop),属于是极其常用的基础功能. 无论是在系统上.应用上.还是在网页上,拖拽随处可见.同时拖拽时的鼠标效果也很漂亮,像这样: 这样: 还有这样: 等等等等. 这 ...
 
随机推荐
- Solr服务在Linux上的搭建
			
一.系统环境 注:欢迎大家转载,非商业用途请在醒目位置注明本文链接和作者名dijia478即可,商业用途请联系本人dijia478@163.com. CentOS-6.7-i386-bin-DVD1 ...
 - Linux安装Nginx以及简单理解
			
1.Nginx简单介绍 ①.Nginx:一个高性能的HTTP和反向代理服务器,高并发处理很不错. ②.反向代理:在计算机世界里,由于单个服务器的处理客户端(用户)请求能力有一个极限,当用户的接入请求蜂 ...
 - 读《淘宝技术这十年》 总结下web架构的发展
			
关键词就两 分布式 缓存 分布式 数据库,应用服务器等的多节点部署,数据库的读写分离,剥离文件系统 缓存 数据缓存 静态页面缓存 php时代 最初LAMP起步 并将数据库做读写分离,拆分为主库+从库 ...
 - Android开发之监听发出的短信
			
执行效果图: 预备知识: 为了监听指定的ContentProvider的数据的改变,须要通过ContentResolver向指定Uri注冊CotentObserver监听器.ContentResolv ...
 - git for c#,子文件的加入
			
private static void SubDirFile() { string wkDir = @"E:\DotNet2010\单位project\Git.Client\lib2Test ...
 - Java filter中的chain
			
一.Filter Filter:用来拦截请求,处于客户端和被请求资源之间,是为了代码的复用性.Filter链,在web.xml中哪个先配置就先调用哪个 二.FilterChain(过滤链) 服务器会按 ...
 - angular自定义分页组件(实用)
			
功能描述:分页,点击按钮或者下一页获取分页接口,同时active到对应页码. html模块: <page page-count="totalPage" on-click-pa ...
 - 自学WPF之Binding(一)
			
Binding的重要性就不作介绍了,是作为数据交互的支撑,下面来介绍一下为Binding指定源(Source)的几种方法: 把普通CLR类型的单个对象指定为Source:包括.NET Framewor ...
 - idea  安装热部署插件
			
jrebel(http://zeroturnaround.com/)的作用就是当你的代码改变时,你不需要重启服务,节省了时间.代码的改变有很多种,比如增加class.在class中增加方法等等.下面介 ...
 - NodeJs学习笔记(三)
			
最近在用sails框架写移动后台,马上就过年了,打算总结一下. 1.资源 node官方网站: www.nodejs.org sails官方网站:www.sailsjs.org ...