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),属于是极其常用的基础功能. 无论是在系统上.应用上.还是在网页上,拖拽随处可见.同时拖拽时的鼠标效果也很漂亮,像这样: 这样: 还有这样: 等等等等. 这 ...
随机推荐
- 关于我之前写的修改Windows系统Dos下显示用用户名的名字再测试
最近看到蛮多网友反映,自己修改Dos下用户名后出现了很多的问题--今天抽了时间,再次修改测试... ================= Win10下C:\Users\John以账户名称命名的系统文件夹 ...
- 某pdf转word v6.3.0.2算法分析
某pdf转word v6.3.0.2算法分析 [文章标题]某pdf转word v6.3.0.2算法分析 [文章作者]jieliuhouzi[原版下载]www.pdfcword.cn [保护方式]序列号 ...
- (hdu step 8.1.6)士兵队列训练问题(数据结构,简单模拟——第一次每2个去掉1个,第二次每3个去掉1个.知道队伍中的人数<=3,输出剩下的人 )
题目: 士兵队列训练问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...
- UVA 10465 Homer Simpson(全然背包: 二维目标条件)
UVA 10465 Homer Simpson(全然背包: 二维目标条件) http://uva.onlinejudge.org/index.php? option=com_onlinejudge&a ...
- IT(计算机/软件/互联网)专业词汇宝典(持续更新中)
1.Stack Overflow:http://stackoverflow.com/ .一个著名的IT技术的问答站点.全然免费.程序猿必知. 2.programmer:程序猿 3.enthu ...
- ado 字符串变量
这次变量主要针对 Mfc 的 Cstring 类型的变量(前面VC 链接Access 数据库 插入变量到表) 思路; 1 把cstring 类型 转为 string 2 string 转 char 数 ...
- AVL树 & 重平衡概念
AVL树是有平衡条件的二叉搜索树.这个平衡条件必须容易保持,而且需要保证树的深度是O(logN). AVL=BBST 作为二叉搜索树的最后一部分,我们来介绍最为经典的一种平衡二叉搜索树:AVL树.回顾 ...
- 观未见,行不止 —— Power BI 两周年技术和方案交流圆桌会议纪实
作者:陈希章 发表于 2017年8月13日 2017年8月11日下午两点,Power BI 两周年技术和方案交流圆桌会议如期举行.线上和线下约有100位朋友参加了由我组织和主持的本次活动,在两个小时的 ...
- 一.windows环境下rabbitMQ的的安装和配置
rabbitMQ是AMQP 0-9-1(高级消息队列协议)的一个实现,使用Erlang语言编写,利用了Erlang的分布式特性.用它来实现分布式消息队列. 1.因为是用Erlang编写的,所以首先要安 ...
- python爬虫入门学习
近期写的一个爬虫的Demo,只是简单的用了几个函数.实现了简单的爬取网页的功能(以途牛为例). import urllib2 import re import urlparse import robo ...