C#/WinForm拖拽文件上传
一、首先创建一个上传文件的类,继承Control类,如下:
public class UploadControl : Control{private Image _image;public UploadControl(){this.SetStyle(ControlStyles.UserPaint | //控件自行绘制,而不使用操作系统的绘制ControlStyles.AllPaintingInWmPaint | //忽略背景擦除的Windows消息,减少闪烁,只有UserPaint设为true时才能使用。ControlStyles.OptimizedDoubleBuffer |//在缓冲区上绘制,不直接绘制到屏幕上,减少闪烁。ControlStyles.ResizeRedraw | //控件大小发生变化时,重绘。ControlStyles.SupportsTransparentBackColor, //支持透明背景颜色true);_image =Properties.Resources.upload;this.Cursor = Cursors.Hand;this.AllowDrop = true;}}
准备好上传的图片
二、我们需要绘制圆角矩形,所以先准备一个圆角路径,如下:
private GraphicsPath GetRoundedRectPath(Rectangle rect, uint radius){int r = (int)radius << 1;Rectangle arcRect = new Rectangle(rect.Location, new Size(r, r));GraphicsPath path = new GraphicsPath();path.AddArc(arcRect, 180, 90);// 右上圆弧arcRect.X = rect.Right - r;path.AddArc(arcRect, 270, 90);// 右下圆弧arcRect.Y = rect.Bottom - r;path.AddArc(arcRect, 0, 90);// 左下圆弧arcRect.X = rect.Left;path.AddArc(arcRect, 90, 90);path.CloseFigure();return path;}
三、重写OnPaint事件,绘制填充圆角背景
Rectangle outRect = new Rectangle(0, 0, this.Width, this.Height);
using var outPath = GetRoundedRectPath(outRect, Radius);
this.Region = new Region(path);
using SolidBrush b = new SolidBrush(this.BackColor);
e.Graphics.FillPath(b, outPath);
效果如下:
发现使用Region属性有锯齿,尽管开启高质量绘图也无用,我们去掉Region属性,但是新的问题出现,此控件的背景必须和父级窗体的背景一致,不然圆角效果就没有了。后续我们都是不设置Region属性,保持背景与父级控件背景一致就行。
四、在OnPaint事件,绘制圆角边框
var innerRect = Rectangle.Inflate(outRect, -(int)border, -(int)border);
using GraphicsPath innerPath = GetRoundedRectPath(innerRect, Radius - border);
using Pen pen = new Pen(ColorState switch
{ControlState.Hover => this.BorderHoverColor,ControlState.Pressed => this.BorderPressedColor,ControlState.DragEnter => this.BorderHoverColor,_ => this.BorderNormalColor,
}, border);
pen.DashStyle = BorderStyle;
e.Graphics.DrawPath(pen, innerPath);
效果如下:
四、在OnPaint事件,绘制上传图像以及文字
const int h = 5;
SizeF sizeF = SizeF.Empty;
if (!string.IsNullOrWhiteSpace(Text))sizeF = e.Graphics.MeasureString(Text, this.Font);
if (_image != null)
{int imageH = 0;if (sizeF != SizeF.Empty){imageH = (int)((this.Height - _image.Height - h - sizeF.Height) / 2);TextRenderer.DrawText(e.Graphics, Text, this.Font, new Point((int)((this.Width - sizeF.Width) / 2), imageH + _image.Height + h), this.ForeColor);}elseimageH = this.Height - _image.Height >> 1;e.Graphics.DrawImage(_image, this.Width - _image.Width >> 1, imageH);
}
else
{if (sizeF != SizeF.Empty){TextRenderer.DrawText(e.Graphics, Text, this.Font, new Point((int)((this.Width - sizeF.Width) / 2), (int)((this.Height - sizeF.Height) / 2)), this.ForeColor);}
}
效果如下:
五、我们定义一个枚举,用来实现鼠标移、出移入、点击、文件拖动让边框变色
public enum ControlState { Hover, Normal, Pressed, DragEnter }
然后重写OnMouseEnter、OnMouseLeave、OnMouseDown、OnMouseUp事件,如下:
private ControlState ColorState { get; set; }= ControlState.Normal;
protected override void OnMouseEnter(EventArgs e)//鼠标进入时
{ColorState = ControlState.Hover;//Hoverthis.Invalidate();base.OnMouseEnter(e);
}
protected override void OnMouseLeave(EventArgs e)//鼠标离开
{ColorState = ControlState.Normal;//正常this.Invalidate();base.OnMouseLeave(e);
}
protected override void OnMouseDown(MouseEventArgs e)//鼠标按下
{if (e.Button == MouseButtons.Left && e.Clicks == 1)//鼠标左键且点击次数为1{ColorState = ControlState.Pressed;//按下的状态this.Invalidate();using OpenFileDialog openFileDialog = new OpenFileDialog();openFileDialog.Filter = "所有文件 (*.*)|*.*";if (openFileDialog.ShowDialog() == DialogResult.OK){FilesCallback?.Invoke(new string[] { openFileDialog.FileName });}}base.OnMouseDown(e);
}
protected override void OnMouseUp(MouseEventArgs e)//鼠标弹起
{if (e.Button == MouseButtons.Left && e.Clicks == 1){if (ClientRectangle.Contains(e.Location))//控件区域包含鼠标的位置{ColorState = ControlState.Hover;}else{ColorState = ControlState.Normal;}this.Invalidate();}base.OnMouseUp(e);
}
就是在OnPaint事件中笔的颜色代码:
ColorState switch
{ControlState.Hover => this.BorderHoverColor,ControlState.Pressed => this.BorderPressedColor,ControlState.DragEnter => this.BorderHoverColor,_ => this.BorderNormalColor,
}
当然我们在OnMouseDown事件中还实现了点击选择文件:
using OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "所有文件 (*.*)|*.*";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{FilesCallback?.Invoke(new string[] { openFileDialog.FileName });
}
其中FilesCallback是一个事件:
public event Action<string[]> FilesCallback;
六、实现文件拖动上传
protected override void OnDragEnter(DragEventArgs drgevent)
{base.OnDragEnter(drgevent);if (drgevent.Data.GetDataPresent(DataFormats.FileDrop))drgevent.Effect = DragDropEffects.Copy;elsedrgevent.Effect = DragDropEffects.None;ColorState = ControlState.DragEnter;this.Invalidate();
}
protected override void OnDragLeave(EventArgs e)
{base.OnDragLeave(e);ColorState = ControlState.Normal;this.Invalidate();
}
protected override void OnDragDrop(DragEventArgs drgevent)
{base.OnDragDrop(drgevent);ColorState = ControlState.Normal;this.Invalidate();object? obj = drgevent.Data?.GetData(DataFormats.FileDrop);if (obj == null) return;FilesCallback?.Invoke((string[])obj);
}
同时需要在构造函数中开启AllowDrop:
this.AllowDrop = true;
其它代码未在这里展示详情请见:
https://gitee.com/feng-cai/Seal-Bubbles
相关文章:

C#/WinForm拖拽文件上传
一、首先创建一个上传文件的类,继承Control类,如下: public class UploadControl : Control{private Image _image;public UploadControl(){this.SetStyle(ControlStyles.UserPaint | //控件自行绘制,而不使用操作系统的绘制Cont…...

IT运维的365天--019 用php做一个简单的文件上传工具
前情提要:朋友的工作室,有几个网站分布在不同的服务器上,要经常进行更新,之前是手动复制压缩包到各个服务器去更新(有写了自动更新的Shell脚本)。但还是觉得太麻烦,每次还要手动传输压缩包到各个…...
详细的oracle rac维护命令集合
一、查看命令 所有实例和服务的状态 $srvctl status database -d orcl Instance orcl1 is running on node db1 Instance orcl2 is running on node db2 单个实例的状态 $ srvctl status instance -d orcl -i orcl2 Instance orcl2 is running on node db2 单个节点的应用程序…...

23 种设计模式详解
设计模式的分类 总体来说设计模式分为三大类: 创建型模式,共五种:单例模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式。 结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、 组合模…...

Python毕业设计选题:基于django+vue的二手物品交易系统
开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 管理员登录 管理员功能界面 用户管理 店铺管理 二手物品管理 广告管理 留言反馈 订单…...

VMware 17虚拟Ubuntu 22.04设置共享目录
VMware 17虚拟Ubuntu 22.04设置共享目录 共享文件夹挂载命令!!!<font colorred>配置启动自动挂载Chapter1 VMware 17虚拟Ubuntu 22.04设置共享目录一、卸载老版本二、安装open-vm-tools<font colorred>三、配置启动自动挂载四、添…...
Rust学习(五):泛型、trait
Rust学习(五):泛型、trait 1、泛型: 相信小伙伴们一定还记得,之前我们实现了一个add函数,并指定了参数类型为:i32: fn add(x:i32, y:i32) ->i32 {x y }这里我们就会遇到一个问…...

智能零售柜商品识别
项目源码获取方式见文章末尾! 600多个深度学习项目资料,快来加入社群一起学习吧。 《------往期经典推荐------》 项目名称 1.【基于CNN-RNN的影像报告生成】 2.【卫星图像道路检测DeepLabV3Plus模型】 3.【GAN模型实现二次元头像生成】 4.【CNN模型实现…...

2024智能机器人与自动控制国际学术会议 (IRAC 2024)
主办,承办,支持单位 会议官网 www.icirac.org 大会时间:2024年11月29-12月1日 大会简介 2024智能机器人与自动控制国际学术会议 (IRAC 2024)由华南理工大学主办,会议将于2024年11月29日-12月1日在中国广…...

计算机组成原理:总线与微命令
实验四 总线与微命令实验 一、实验目的 1) 理解总线的概念和作用。 2) 连接运算器与存储器,熟悉计算机的数据通路。 3) 理解微命令与微操作的概念。 二、实验要求 1) 做好实验预习,在实验之前填写好…...

10月回顾 | Apache SeaTunnel社区动态与进展一览
各位热爱 Apache SeaTunnel 的小伙伴们,社区10月份月报来啦,请查收! 这里将记录Apache SeaTunne社区每月动态和进展,欢迎关注。 月度Merge之星 感谢以下小伙伴上个月为 Apache SeaTunnel 所做的精彩贡献(排名不分先…...

网络基础(4)传输层
既然是传输层首先就要明确实在层状结构的哪里,除开物理层之外分成了四层协议: 到这里上层(应用层)的使用已经没有问题,之前使用的套接字都是在应用层的。 再说端口号 到一个主机收到一个报文的时候,这个报文中一定存在这个报文需要到的主机的ip号。如果…...

计算机的错误计算(一百五十六)
摘要 探讨 MATLAB 中双曲反余切函数 acoth(x) 在 附近数的计算精度问题。 Acoth(x)函数的定义为 例1. 已知 计算 与 直接贴图吧: 另外,16位的正确值分别为 0.1110083774360105e2 与 -0.1110083774360105e2(ISRealsoft 提供。通过计算…...

爬虫开发工具与环境搭建——开发工具介绍
第二章:爬虫开发工具与环境搭建 第一节 开发工具介绍 爬虫开发需要一些合适的工具和框架来高效地抓取网页数据。在这节中,我们将介绍常用的开发工具,帮助开发者快速搭建爬虫开发环境。 1. Python与爬虫框架选择 Python因其简洁、易学的语法…...

Oracle 19c PDB克隆后出现Warning: PDB altered with errors受限模式处理
在进行一次19c PDB克隆过程中,发现克隆结束,在打开后出现了报错,PDB变成受限模式,以下是分析处理过程 09:25:48 SQL> alter pluggable database test1113 open instancesall; Warning: PDB altered with errors. Elapsed: 0…...
阿里云ACK容器如何配置pod分散在集群的不同节点上
阿里云ACK容器如何配置pod分散在集群的不同节点上 1.核心原理 是使用pod间反亲和性(podAntiAffinity),pod间反亲和性又分为软约束反亲和和硬约束反亲和。 2.软约束反亲和和硬约束反亲和区别: preferredDuringSchedulingIgnore…...

Qt信号和槽
信号和槽的概念 在Linux中我们也学过信号 Signal,这是进程间通信的一种方式,这里大致分为三个要素: 信号源:谁发送的信号(用户进程,系统内核,终端或者作业控制,) 信号的类…...

Python知识点精汇!字符串:定义、截取(索引)和其内置函数
目录 一、字符串的定义 二、字符串的截取 1.截取干啥的 2.怎么用截取 3.打印多次 4.两个字符串拼接在一起 三、字符串内置函数 1.查询函数: (1)find(str,start,end) (2)index(str,start,end&#…...
【CV】头盔检测区域入侵项目
文章目录 🌕项目和数据下载🌙安全帽佩戴数据集🌕收集数据数据🌕wbem格式视频转avi或者mp4🌕跑通区域入侵🌙多边形标注工具下载🌙使用Python脚本打开视频获取一张用来标注的图片🌙打开labelme标注一个多边行🌙程序可以识别的标注json格式🌙修改代码读取Json…...

大数据应用开发——实时数据处理(一)
前言 大数据应用开发——实时数据采集 大数据应用开发——实时数据处理 Flink完成Kafka中的数据消费,将数据分发至Kafka的dwd层中 并在HBase中进行备份 大数据应用开发——数据可视化 hadoop,zookeeper,kafka,flink要开启 目…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现
目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...