当前位置: 首页 > news >正文

C# wpf 实现截屏框热键截屏功能

wpf截屏系列

第一章 使用GDI+实现截屏
第二章 使用DockPanel制作截屏框
第三章 实现截屏框热键截屏(本章)
第四章 实现截屏框实时截屏
第五章 使用ffmpeg命令行实现录屏


文章目录

  • wpf截屏系列
  • 前言
  • 一、实现步骤
    • 1、响应热键
    • 2、截屏显示
      • (1)获取屏幕区域
      • (2)截取并显示
    • 3、自动捕获窗口
      • (1)获取系统所有窗口
      • (2)根据鼠标位置搜索窗口
      • (3)效果预览
    • 2、点击拖出截屏框
      • (1)移动到点击位置
      • (2)模拟按下事件
      • (3)修正偏移
      • (4)效果预览
    • 3、反向拖动
      • (1)判断边界
      • (2)事件转移
      • (3)修正边界
      • (4)效果预览
    • 4、截取图片
    • 5、设置粘贴板
  • 二、关于dpi
    • 1、适配不同dpi
    • 2、不支持dpi实时修改
      • (1)现象
      • (2)尝试的解决方案
    • 3、建议
  • 三、完整代码
  • 四、效果预览
    • 1、截屏粘贴到qq
    • 2、截屏保存到文件
  • 总结


前言

在《C# wpf 使用DockPanel实现截屏框》中我们实现了一个截屏框,接下来就要实现相应的截屏功能了。获取截屏区域然后使用GDI+截屏,在这里不少的细节需要处理,比如响应热键弹出截屏界面、点击拖出截屏框、截屏区域任意反向拖动、处理不同dpi下的坐标位置等等。


一、实现步骤

1、响应热键

我们直接使用win32 api的RegisterHotKey和UnregisterHotKey即可。在Window的SourceInitialized事件中注册热键,如下是注册alt+d为热键的示例代码

[System.Runtime.InteropServices.DllImport("user32")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, uint controlKey, uint virtualKey);[System.Runtime.InteropServices.DllImport("user32")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

HotKey是对RegisterHotKey、UnregisterHotKey做了封装的对象,网上可以搜到此处略。

 private void Window_SourceInitialized(object sender, EventArgs e){//注册alt+d热键,0x44为d,其他虚拟键值请查看:https://learn.microsoft.com/zh-tw/windows/win32/inputdev/virtual-key-codesHotKey k = new HotKey(this, HotKey.KeyFlags.MOD_ALT, 0x44);k.OnHotKey += K_OnHotKey;Visibility = Visibility.Collapsed;}

2、截屏显示

(1)获取屏幕区域

我们需要使用win32 api获取屏幕区域,采用wpf的方法取得的屏幕分辨率是基于dpi的,就算是用PointToScreen进行转换,在程序运行过程中改了系统dpi后依然会不准确,所以需要直接取得屏幕的实际像素分辨率,用于gdi+截屏。

  const int DESKTOPVERTRES = 117;const int DESKTOPHORZRES = 118;[DllImport("gdi32.dll")]static extern int GetDeviceCaps(IntPtr hdc, // handle to DC  int nIndex // index of capability  );[DllImport("user32.dll")]static extern IntPtr GetDC(IntPtr ptr);[DllImport("user32.dll", EntryPoint = "ReleaseDC")]static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);/// <summary>  /// 获取真实设置的桌面分辨率大小  /// </summary>  static Size DESKTOP{get{IntPtr hdc = GetDC(IntPtr.Zero);Size size = new Size();size.Width = GetDeviceCaps(hdc, DESKTOPHORZRES);size.Height = GetDeviceCaps(hdc, DESKTOPVERTRES);ReleaseDC(IntPtr.Zero, hdc);return size;}}

(2)截取并显示

利用上面步骤获取到的截屏区域,结合《C# wpf 使用GDI+实现截屏》里的简单截屏即完成。取得Bitmap对象后,参考我的另一篇文章《C# wpf Bitmap转换成WriteableBitmap(BitmapSource)的方法》将其转换为转换成wpf对象,然后通过ImageBrush赋值为控件的Background即可以显示在控件上。

//截屏并显示到窗口
void Snapshot()
{//获取桌面实际分辨率,可以解决程序运行后修改dpi,截图区域不正常的问题var leftTop = new Point(0, 0);var rightBottom = new Point(DESKTOP.Width, DESKTOP.Height);var bitmap = Snapshot((int)leftTop.X, (int)leftTop.Y, (int)(rightBottom.X - leftTop.X), (int)(rightBottom.Y - leftTop.Y));var bmp = BitmapToWriteableBitmap(bitmap);bitmap.Dispose();//显示到窗口grdGlobal.Background = new ImageBrush(bmp);
}

3、自动捕获窗口

qq和微信的截屏都有自动捕获窗口功能,我们也可以自己实现这种功能。

(1)获取系统所有窗口

通过win32 api可以枚举系统所有窗口,我们需要将所有窗口的位置大小记录下来,网上可以找到WindowList相关代码此处略。

//获取桌面所有窗口
_windows = WindowList.GetAllWindows();
IntPtr hwnd = new WindowInteropHelper(this).Handle;
//去除不可见窗口以及自己
_windows.RemoveAll((ele) => { return !ele.isVisible || ele.Handle == hwnd; });

(2)根据鼠标位置搜索窗口

//窗口是以z顺序排列的查找到第一个匹配的窗口即可
var screenPoint = grdGlobal.PointToScreen(point);
foreach (var window in _windows)
{if (window.rect.Contains(screenPoint))//获取在鼠标所在区域的窗口{try{if (window.rect.Right > window.rect.Left && window.rect.Bottom > window.rect.Top)//{var topLeft = grdGlobal.PointFromScreen(window.rect.TopLeft);var bottomRight = grdGlobal.PointFromScreen(window.rect.BottomRight);Thickness thickness = new Thickness(topLeft.X, topLeft.Y, grdGlobal.ActualWidth - bottomRight.X, grdGlobal.ActualHeight - bottomRight.Y);//修正边界if (thickness.Left < 0) thickness.Left = 0;if (thickness.Top < 0) thickness.Top = 0;if (thickness.Right < 0) thickness.Right = 0;if (thickness.Bottom < 0) thickness.Bottom = 0;//将截屏框显示在窗口位置leftPanel.Width = thickness.Left;topPanel.Height = thickness.Top;rightPanel.Width = thickness.Right;bottomPanel.Height = thickness.Bottom;break;}}catch { }}
}

(3)效果预览

在这里插入图片描述

2、点击拖出截屏框

出现截屏界面之后,参考qq或微信的实现,第一次点击是可以拖出截屏框框选的。如果是采样绘制的方法很简单,直接绘制矩形就可以了。但是基于控件要实现这个功能需要一定的技巧,在《C# wpf 使用DockPanel实现截屏框》的基础上实现这个功能。

(1)移动到点击位置

在鼠标按下事件或移动实现中

//将截屏框移动到点击位置
leftPanel.Width = p.X;
topPanel.Height = p.Y;
rightPanel.Width = grdGlobal.ActualWidth - p.X;
bottomPanel.Height = grdGlobal.ActualHeight - p.Y;

(2)模拟按下事件

接着上面的代码,thumb为右下角拖动点。

//手动触发截屏框滑块拖动事件
MouseButtonEventArgs downEvent = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left)
{ RoutedEvent = FrameworkElement.MouseLeftButtonDownEvent };
thumb.RaiseEvent(downEvent);

(3)修正偏移

由于是模拟的点击事件,可能会出现鼠标不在Thumb上的情况,此时需要对thumb位置进行修正,在Thumb的DragStarted事件中记录偏移。

//滑块需要的偏移量
Point? _thumbOffset;
var thumb = sender as FrameworkElement;
if (!new Rect(0, 0, thumb.ActualWidth, thumb.ActualHeight).Contains(new Point(e.HorizontalOffset, e.VerticalOffset)))
//鼠标起始位置超出了控件范围,则记录中心点偏移在拖动时修正
{_thumbOffset = new Point(e.HorizontalOffset - thumb.ActualWidth / 2, e.VerticalOffset - thumb.ActualHeight / 2);
}

在Thumb的DragDelta事件中添加修正逻辑

var horizontalChange = e.HorizontalChange;
var verticalChange = e.VerticalChange;
if (_thumbOffset != null)
//修正偏移
{horizontalChange += _thumbOffset.Value.X;verticalChange += _thumbOffset.Value.Y;
}

(4)效果预览

在这里插入图片描述

3、反向拖动

这一步不是必须的,但是有的话操作体验会更好,比如qq和微信的截图就支持反向拖动。如果我们使用gdi或gdi+绘制截屏框则天然支持反向拖动,因为RECT的大小可以为负数。但是基于控件则有一定的难度了,由于控件宽高不能为负数,我们需要实现事件转移机制,依然是在《C# wpf 使用DockPanel实现截屏框》的基础上实现这个功能。

(1)判断边界

原本《C# wpf 使用DockPanel实现截屏框》的逻辑的Thumb到了边界就不进行任何操作了,现在要拓展为到达边界则进行事件转移。
横向的Thumb

if (width >= 0)
{leftPanel.Width = left >= 0 ? left : 0;rightPanel.Width = right >= 0 ? right : 0;
}
else{
//此处将事件转移到反方向的Thumb
}

纵向的Thumb

if (height >= 0)
{topPanel.Height = top >= 0 ? top : 0;bottomPanel.Height = bottom >= 0 ? bottom : 0;
}
else
{
//此处将事件转移到反方向的Thumb
}

(2)事件转移

//当前的Thumb触发鼠标弹起事件,结束拖动
MouseButtonEventArgs upEvent = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left)
{ RoutedEvent = FrameworkElement.MouseLeftButtonUpEvent };
thumb.RaiseEvent(upEvent);
//反方向的Thumb触发鼠标按下事件,开始拖动
MouseButtonEventArgs downEvent = new MouseButtonEventArgs(Mouse.PrimaryDevice, Environment.TickCount, MouseButton.Left)
{ RoutedEvent = FrameworkElement.MouseLeftButtonDownEvent };
t.RaiseEvent(downEvent);

(3)修正边界

完成上述两步之后已经可以做到反向拖动了,但是会有个问题,当多动过快的时截屏框的位置会发生移动,要解决这个问题则需要在事件转移时修正边界位置,即使两条边重合。
横向的Thumb

if (thumb.HorizontalAlignment == HorizontalAlignment.Left)
//从左到右转移的修正
{leftPanel.Width = grdGlobal.ActualWidth - rightPanel.Width;
}
else
//从右到左转移的修正
{rightPanel.Width = grdGlobal.ActualWidth - leftPanel.Width;
}

纵向的Thumb

 if (thumb.VerticalAlignment == VerticalAlignment.Top)//从上到下转移的修正{topPanel.Height = grdGlobal.ActualHeight - bottomPanel.Height;}else//从下到上转移的修正{bottomPanel.Height = grdGlobal.ActualHeight - topPanel.Height;}

(4)效果预览

在这里插入图片描述

4、截取图片

由于前面截取是整个桌面的图像,保存时需要根据截屏框截取画面,我们使用WriteableBitmap对象就可以实现。

//获取截屏框的图片
WriteableBitmap GetClipImage()
{var bursh = grdGlobal.Background as ImageBrush;if (bursh != null){//裁剪//全屏图片var screenWb = bursh.ImageSource as WriteableBitmap;//获取截取区域var leftTop = clipRect.PointToScreen(new Point(0, 0));var rightBottom = clipRect.PointToScreen(new Point(clipRect.ActualWidth, clipRect.ActualHeight));var rect = new Int32Rect((int)leftTop.X, (int)leftTop.Y, (int)(rightBottom.X - leftTop.X), (int)(rightBottom.Y - leftTop.Y));//创建截取图片对象var wb = new WriteableBitmap(rect.Width, rect.Height, 0, 0, screenWb.Format, null);//写入截取区域数据wb.WritePixels(rect, screenWb.BackBuffer, screenWb.PixelHeight * screenWb.BackBufferStride, screenWb.BackBufferStride, 0, 0);return wb;}return null;
}

5、设置粘贴板

直接使用Clipboard.SetImage即可,参数类型为BitmapSource,是WriteableBitmap的基类。

 Clipboard.SetImage(GetClipImage());

二、关于dpi

1、适配不同dpi

有处理dpi不同的情况,在任意dpi下都能正常截图。

2、不支持dpi实时修改

(1)现象

程序启动后实时修改dpi,截屏显示的画面会模糊,主要原因是不同api之间的dpi计算不统一。系统dpi实时修改后wpf界面会响应oloaded自动调整大小,但部分程序内部的dpi(比如getWindowRect)是不会变化的,尤其是渲染图片依然按照程序启动时的dpi去计算,所以会进行缩放,显示的画面必然模糊。
这里举一个具体的例子流程如下:
win11 分辨率1920x1080
1、初始系统dpi为120(1.25倍)
2、程序启动
3、程序dpi为120
5、全屏窗口大小1536x864,通过win32 api获取则是1920x1080,截屏1920x1080显示,截屏画面无损
6、系统dpi设置为96(1倍)
7、此时程序dpi为120
8、全屏窗口大小1920x1080,通过win32 api获取则是2400x1350,截屏1920x1080显示,截屏画面模糊。
按像素点绘制,画面显示在左上角无法充满窗口。

(2)尝试的解决方案

笔者采样了多种方式尝试解决
1、提前缩放图片再显示。
2、参考微软解决dpi问题的方法。
3、使用gdi+的graphics直接通过hdc以像素点为单位绘制。
4、使用gdi的bitblt进行hdc拷贝。
以上方法都没效果画面依然模糊

3、建议

需要支持dpi实时改变,可以将截图功能作为单独的程序,响应热键后再启动。


三、完整代码

https://download.csdn.net/download/u013113678/88308050
说明:截屏的操作方式和qq、微信差不多,目前设置的热键为alt+d。


四、效果预览

1、截屏粘贴到qq

在这里插入图片描述

2、截屏保存到文件

在这里插入图片描述


总结

以上就是今天要讲的内容,本文介绍了wpf截屏框热键截屏的方法。需要实现的功能还是比较多的,而且有些功能难度也不小,几经尝试才找到合适的实现方法,至于实时改变dpi的模糊的问题,这个目前的结论是无法解决,这并不是wpf的局限,用c++ mfc也不行,除非存在一个设置程序全局dpi的win32 api接口笔者没有发现。所以这个问题目前只能通过独立程序启动解决。但是总的来说实现的效果是很不错的,尤其是反向拖动,通过事件转移的方式实现,界面操作还是很流畅。

相关文章:

C# wpf 实现截屏框热键截屏功能

wpf截屏系列 第一章 使用GDI实现截屏 第二章 使用DockPanel制作截屏框 第三章 实现截屏框热键截屏&#xff08;本章&#xff09; 第四章 实现截屏框实时截屏 第五章 使用ffmpeg命令行实现录屏 文章目录 wpf截屏系列前言一、实现步骤1、响应热键2、截屏显示&#xff08;1&#…...

springboot + activiti实现activiti微服务化

概述 本文介绍如何将springbootactiviti进行整合,并配合eureka,zuul和feign实现activiti的微服务化,将流程控制和业务逻辑分离. 并实现了几个比较特殊的功能,比如时间段委托(某人请假或出差,出差时间内,所有待办交给被委托人处理),比如节点的无限级加签功能(流程本身有不确定性…...

c语言练习41:深入理解字符串函数strlen strcpy strcat

深入理解字符串函数strlen strcpy strcat 模拟实现&#xff1a;”strlen strcpy strcat strlen strcat: #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<assert.h> strlen 1.通过指针移动模拟 //int my_strlen(char* str) { // size_t c…...

Vue3+Vue-i18n+I18N ALLY+VSCODE 自动翻译多国语言

ps: 效果图放前面,符合的往下看&#xff0c;不符合的出门右转&#xff0c;希望多多点赞评论支持。 三种语言模式&#xff0c;分别是中文、英文、日文 批量翻译 最后的结果 配置vue-i18n 1、下载安装vue-i18n&#xff0c;9以上的版本。 2、创建对应文件夹 3、对应文件夹中代…...

idea意外退出mac

目录 问题描述 解决过程 问题描述 mac上的idea我很久没用了&#xff0c;之前用的时候还是发布新版的开源项目&#xff0c;这几天再用的时候&#xff0c;就出现了idea意外退出的问题&#xff0c;我上网查找了很久&#xff0c;对于我的问题都没有很好的解决。 解决过程 在寻求…...

百度智能云千帆大模型平台2.0来了!从大模型到生产力落地的怪兽级平台!!

目录 前言 最佳算力效能为企业降低门槛 最多大模型&#xff0c;最多数据集为企业保驾护航 企业级安全对于企业来说是硬性要求 前言 普通人或许感知不明显&#xff0c;但是对于企业而言&#xff0c;身处AI时代&#xff0c;是否选择投资大模型&#xff0c;是否拥抱人工智能…...

k8s nfs-client 添加挂载参数 —— 筑梦之路

背景介绍 为什么要使用noresvport参数挂载NAS&#xff1f;不重新挂载会有什么后果&#xff1f; 如果发生网络切换或者后端服务的HA倒换&#xff0c;小概率会造成NFS文件系统阻塞&#xff0c;那就可能需要几分钟时间连接才会自动恢复&#xff0c;极端情况下甚至需要重启ECS才能恢…...

【算法】堆排序 详解

堆排序 详解 堆排序代码实现 排序&#xff1a; 排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。 稳定性&#xff1a; 假定在待排序的记录序列中&#xff0c;存在多个具有相同的关键字的记录&#xff0c…...

解决Maven依赖下载问题:从阿里云公共仓库入手

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

【Java基础】学习笔记2 - 数组运算符与main方法

目录 多态数组运算符hashCodefinalize 方法 第三阶段类变量类方法main 方法代码块单例模式饥饿式懒汉式 多态数组 顾名思义&#xff0c;就是在一个数组内体现多态 public class PolyArrDemo {public static void main(String[] args) {// 定义多态数组Fruit[] fruits new Fr…...

stable diffusion实践操作-复制-清空-保存提示词

系列文章目录 stable diffusion实践操作 stable diffusion实践操作-webUI教程 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一、右上生成图标附近按钮介绍1. 箭头介绍&#xff08;复现别人的…...

【Spring 事务和事务传播机制】

目录 1 事务概述 1.1 为什么需要事务 1.2 事务的特性 1.3 Spring 中事务的实现 2 Spring 声明式事务 2.1 Transactional 2.2 Transactional 的作用范围 2.3 Transactional 的各种参数 2.3.1 ioslation 2.4 事务发生了异常&#xff0c;也不回滚的情况 异常被捕获时 3 事务的传…...

【爬虫】实验项目二:模拟登录和数据持久化

目录 一、实验目的 二、实验预习提示 三、实验内容 实验要求 基本要求&#xff1a; 改进要求A&#xff1a; 改进要求B&#xff1a; 四、实验过程 基本要求&#xff1a; 源码如下&#xff1a; 改进要求A: 源码如下&#xff1a; 改进要求B&#xff1a; 源码如下&…...

图文版:以太网二层接口类型(含配套习题)

常见的以太网二层接口类型包括以下三种&#xff1a; 一、Access接口 access链路类型端口&#xff0c;一种交换机的主干道模式&#xff0c;2台交换机的2个端口之间是否能够建立干道连接&#xff0c;取决于这2个端口模式的组合。 Access端口在收到以太网帧后打开VLAN标签&#…...

生信豆芽菜-机器学习筛选特征基因

网址&#xff1a;http://www.sxdyc.com/mlscreenfeature 一、使用方法 1、准备数据 第一个文件&#xff1a;特征表达数据 第二个文件&#xff1a;分组信息&#xff0c;第一列为样本名&#xff0c;第二列为患者分组 第三个文件&#xff1a;分析基因名 2、选择机器学习的方…...

v-html富文本里面的图片设置宽高不起作用的原因

把scoped去掉...

pdf文档怎么压缩小一点?文件方法在这里

在日常工作和生活中&#xff0c;我们经常会遇到需要上传或者发送pdf文档的情况。但是&#xff0c;有时候pdf文档的大小超出了限制&#xff0c;需要我们对其进行压缩。那么&#xff0c;如何将pdf文档压缩得更小一点呢&#xff1f;下面&#xff0c;我将介绍三种方法&#xff0c;让…...

CMD关闭占用端口

1. netstat -ano | findstr :xxxx 2. taskkill /pid xxxx 3. 强制关闭taskkill/F /pid xxxx...

复制粘贴是怎么实现的

在上面的代码中&#xff0c;command 和 select 是自定义的函数。它们的作用如下&#xff1a; 实现复制粘贴的思路&#xff1a; 创建一个 textarea 标签将 textarea 移出可视区域给这个 textarea 赋值将这个 textarea 标签添加到页面中调用 textarea 的 select 方法调用 docum…...

mybatisplus多租户原理略解

概述 当前mybatisPlus版本 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.2</version> </dependency>jdk版本&#xff1a;17 springboot版本&#xff1a;…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践

01技术背景与业务挑战 某短视频点播企业深耕国内用户市场&#xff0c;但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大&#xff0c;传统架构已较难满足当前企业发展的需求&#xff0c;企业面临着三重挑战&#xff1a; ① 业务&#xff1a;国内用户访问海外服…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...

SpringSecurity+vue通用权限系统

SpringSecurityvue通用权限系统 采用主流的技术栈实现&#xff0c;Mysql数据库&#xff0c;SpringBoot2Mybatis Plus后端&#xff0c;redis缓存&#xff0c;安全框架 SpringSecurity &#xff0c;Vue3.2Element Plus实现后台管理。基于JWT技术实现前后端分离。项目开发同时采 …...

Python_day48随机函数与广播机制

在继续讲解模块消融前&#xff0c;先补充几个之前没提的基础概念 尤其需要搞懂张量的维度、以及计算后的维度&#xff0c;这对于你未来理解复杂的网络至关重要 一、 随机张量的生成 在深度学习中经常需要随机生成一些张量&#xff0c;比如权重的初始化&#xff0c;或者计算输入…...