C#winform自定义控件模拟设计时界面鼠标移动和调节大小、选中效果
1.贡献个Winform自定义控件,信用卡、银行卡输入控件;每4个字符分隔显示。其他UI框架可以参考。2.印章WinForm自定义控件封装,提供源码下载3.Windows高速定时器,多媒体定时器winmm.dll库的使用4.理解SynchronizationContext,如何在Winform里面跨线程访问UI控件5.C#winform程序关闭计算机的正确姿势6.WinForm触摸屏程序功能界面长时间不操作自动关闭回到主界面7.分享Winform datagridview 动态生成中文HeaderText8.Winform让扫描枪听话,防止在有焦点的地方就扫码输入的尴尬9.WinForm调用钉钉获取考勤结果10.C# Winform 实现Ajax效果自定义按钮11.C#Winform 自定义透明按钮和单窗体模块化实现12.C#Winform设计的通用标签设计器13.C#Winform使用mysql作为本地数据库
14.C#winform自定义控件模拟设计时界面鼠标移动和调节大小、选中效果
15.我在winform项目里使用“Windows I/O完成端口”的经验分享16.一次人脸识别ViewFaceCore使用的经验分享,看我把门店淘汰下来的POS机改成了人脸考勤机要想玩转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 = 0, //'无 MouseSizeRight = 1, //'拉伸右边框 MouseSizeLeft = 2, //'拉伸左边框 MouseSizeBottom = 3, //'拉伸下边框 MouseSizeTop = 4, //'拉伸上边框 MouseSizeTopLeft = 5, //'拉伸左上角 MouseSizeTopRight = 6, //'拉伸右上角 MouseSizeBottomLeft = 7, //'拉伸左下角 MouseSizeBottomRight = 8, //'拉伸右下角 MouseDrag = 9 // '鼠标拖动 } const int Band = 5; const int MinWidth = 10; const int MinHeight = 10; private EnumMousePointPosition m_MousePointPosition; private Point p, p1; private EnumMousePointPosition MousePointPosition(Size size, System.Windows.Forms.MouseEventArgs e) { if ((e.X >= -1 * Band) | (e.X <= size.Width) | (e.Y >= -1 * Band) | (e.Y <= size.Height)) { if (e.X < Band) { if (e.Y < Band) { return EnumMousePointPosition.MouseSizeTopLeft; } else { if (e.Y > -1 * Band + size.Height) { return EnumMousePointPosition.MouseSizeBottomLeft; } else { return EnumMousePointPosition.MouseSizeLeft; } } } else { if (e.X > -1 * Band + size.Width) { if (e.Y < Band) { return EnumMousePointPosition.MouseSizeTopRight; } else { if (e.Y > -1 * Band + size.Height) { return EnumMousePointPosition.MouseSizeBottomRight; } else { return EnumMousePointPosition.MouseSizeRight; } } } else { if (e.Y < Band) { return EnumMousePointPosition.MouseSizeTop; } else { if (e.Y > -1 * 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 > 0 && 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(-6, -6); using (Pen p = new Pen(Brushes.Black, 1)) { p.DashStyle = DashStyle.Dot; p.DashStyle = DashStyle.Solid; //8个方块 g.FillRectangle(Brushes.White, new Rectangle(rect.Left - 4, rect.Top - 4, 4, 4)); g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width / 2 - 3, rect.Top - 4, 4, 4)); g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width, rect.Top - 4, 4, 4)); g.FillRectangle(Brushes.White, new Rectangle(rect.Left - 4, rect.Top + rect.Height / 2 - 3, 4, 4)); g.FillRectangle(Brushes.White, new Rectangle(rect.Left - 4, rect.Top + rect.Height, 4, 4)); g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height / 2 - 3, 4, 4)); g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width / 2 - 3, rect.Top + rect.Height, 4, 4)); g.FillRectangle(Brushes.White, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left - 4, rect.Top - 4, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width / 2 - 3, rect.Top - 4, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width, rect.Top - 4, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left - 4, rect.Top + rect.Height / 2 - 3, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left - 4, rect.Top + rect.Height, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height / 2 - 3, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width / 2 - 3, rect.Top + rect.Height, 4, 4)); g.DrawRectangle(p, new Rectangle(rect.Left + rect.Width, rect.Top + rect.Height, 4, 4)); } } /// <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 + 2; int h = bmp.Height + 2; 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, 1, 1); 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, 0, 0); g.Dispose(); tmp.Dispose(); return dst; } /// <summary> /// 响应键盘光标键 /// </summary> /// <param name="keyData"></param> public virtual void KeysChangedLocation(Keys keyData) { if (keyData == Keys.Up) { Top -= 1; } if (keyData == Keys.Down) { Top += 1; } if (keyData == Keys.Left) { Left -= 1; } if (keyData == Keys.Right) { Left += 1; } 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; } } } } }
作者:数据酷软件
出处:https://www.cnblogs.com/datacool/p/datacool_2017_gdi.html
关于作者:20年编程从业经验,持续关注MES/ERP/POS/WMS/工业自动化
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明。
联系方式: qq:71008973;wx:6857740733
基于人脸识别的考勤系统 地址: https://gitee.com/afeng124/viewface_attendance_ext
自己开发安卓应用框架 地址: https://gitee.com/afeng124/android-app-frame
WPOS(warehouse+pos) 后台演示地址: http://47.239.106.75:8080/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2015-10-11 也许每个农村出来的码农都有个田园梦