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

MFC界面美化第三篇----自绘按钮(重绘按钮)

1.前言

最近发现读者对我的mfc美化的专栏比较感兴趣,因此在这里进行续写,这里我会计划写几个连续的篇章,包括对MFC按钮的美化,菜单栏的美化,标题栏的美化,list列表的美化,直到最后形成一个完整的成品效果。

2.最终效果展示

点击启动按钮之后,能响应功能。

博主不会UI设计图片显示的效果比较差,用更好的图片贴上去,就能显示更好的效果的

3.思路分析

1.使用我们设计好的图片,来美化按钮。把图片贴到按钮上

2.创建一个按钮类,继承CButton,来重绘按钮

3.核心还是重写了 DrawItem,函数来实现重绘的效果

4.实现过程

1.在MFC的界面那里,创建两个按钮,启动和停止按钮。

2.找到按钮的属性那里,把所有者描述改成true,不然重绘是不能成功的,这一步是一定要做的

3.核心代码

头文件里面声明按钮变量

public:CMyButton m_button_start;CMyButton m_button_stop;afx_msg void OnBnClickedButton2();afx_msg void OnBnClickedButton1();

OnInitDialog()函数

BOOL CMFCDrawnTitleDlg::OnInitDialog()
{CDialogEx::OnInitDialog();// 将“关于...”菜单项添加到系统菜单中。// IDM_ABOUTBOX 必须在系统命令范围内。ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);ASSERT(IDM_ABOUTBOX < 0xF000);CMenu* pSysMenu = GetSystemMenu(FALSE);if (pSysMenu != nullptr){BOOL bNameValid;CString strAboutMenu;bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);ASSERT(bNameValid);if (!strAboutMenu.IsEmpty()){pSysMenu->AppendMenu(MF_SEPARATOR);pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);}}// 设置此对话框的图标。  当应用程序主窗口不是对话框时,框架将自动//  执行此操作SetIcon(m_hIcon, TRUE);			// 设置大图标SetIcon(m_hIcon, FALSE);		// 设置小图标// TODO: 在此添加额外的初始化代码//退出按钮绘制CRect rtBtnClo;GetClientRect(&rtBtnClo);rtBtnClo.left = rtBtnClo.right - 20;m_btnExit.SetImagePath(_T(".\\res\\icon_popup_off.png"), _T(".\\res\\icon_popup_off.png"), _T(".\\res\\icon_popup_off.png"));m_btnExit.InitMyButton(rtBtnClo.left, 5, 16, 16, true);//最大化按钮绘制GetClientRect(&rtBtnClo);rtBtnClo.left = rtBtnClo.right - 50;m_btnMax.SetImagePath(_T(".\\res\\icon_square.png"), _T(".\\res\\icon_square.png"), _T(".\\res\\icon_square.png"));m_btnMax.InitMyButton(rtBtnClo.left, 5, 16, 16, true);//最小化按钮// GetClientRect(&rtBtnClo);rtBtnClo.left = rtBtnClo.right - 80;m_btnMin.SetImagePath(_T(".\\res\\icon_minimiz.png"), _T(".\\res\\icon_minimiz.png"), _T(".\\res\\icon_minimiz.png"));m_btnMin.InitMyButton(rtBtnClo.left, 5, 16, 16, true);return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE
}

5.button重绘的头文件和cpp文件

mybutton.h

pch.h, 和framework.h这两个文件的路径,可以改的。根据你的项目文件实际放置情况

#pragma once#include <afxwin.h>
#include "../pch.h"
#include "../framework.h"
// CMyButtonclass CMyButton : public CButton
{DECLARE_DYNAMIC(CMyButton)public:CMyButton();virtual ~CMyButton();protected://正常状态图像路径CString m_strNormalImgPath;//按下状态图像路径CString m_strPressImgPath;//悬浮状态图像路径CString m_strFloatImgPath;//正常状态图像CImage m_imgNormal;//按下状态图像CImage m_imgPress;//悬浮状态图像CImage m_imgFloat;//窗口背景图片CImage m_BkImg;public://设置按钮图片路径void SetImagePath(CString strNoramlImgPath, CString strPressImgPath, CString strFloatImgPath);//初始化按钮,主要是调整按钮的位置,处理透明色  bool InitMyButton(int nX/*左上角X坐标*/, int nY/*左上角Y坐标*/, int nW/*图像宽*/, int nH/*图像高*/, bool bIsPng/*是否是PNG图片*/);//自绘制函数  void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);//初始化窗口背景void SetBkImg(CString strBkImg);//释放图片资源,方便最大化 void ReleaseImg();
protected://光标是否在窗口内BOOL m_bIsInWnd;DECLARE_MESSAGE_MAP()
public:afx_msg void OnMouseMove(UINT nFlags, CPoint point);afx_msg void OnMouseHover(UINT nFlags, CPoint point);afx_msg void OnMouseLeave();};

mybutton.cpp

// MyButton.cpp : 实现文件
//#include "pch.h"
#include "MyButton.h"// CMyButtonIMPLEMENT_DYNAMIC(CMyButton, CButton)CMyButton::CMyButton()
{m_bIsInWnd = FALSE;
}CMyButton::~CMyButton()
{
}BEGIN_MESSAGE_MAP(CMyButton, CButton)ON_WM_MOUSEMOVE()ON_WM_MOUSEHOVER()ON_WM_MOUSELEAVE()
END_MESSAGE_MAP()// CMyButton 消息处理程序//设置按钮图片路径
void CMyButton::SetImagePath(CString strNoramlImgPath, CString strPressImgPath, CString strFloatImgPath)
{m_strNormalImgPath = strNoramlImgPath;m_strPressImgPath = strPressImgPath;m_strFloatImgPath = strFloatImgPath;
}void CMyButton::SetBkImg(CString strBkImg)
{if (strBkImg.IsEmpty())return;m_BkImg.Load(strBkImg);
}//初始化按钮,主要是调整按钮的位置,处理透明色 
void CMyButton::ReleaseImg()
{if (m_imgNormal){m_imgNormal.Destroy();}if (m_imgPress){m_imgPress.Destroy();}if (m_imgFloat){m_imgFloat.Destroy();}
}
bool CMyButton::InitMyButton(int nX/*左上角X坐标*/, int nY/*左上角Y坐标*/, int nW/*图像宽*/, int nH/*图像高*/, bool bIsPng/*是否是PNG图片*/)
{HRESULT hr = 0;if (m_strNormalImgPath.IsEmpty())return false;if (m_strPressImgPath.IsEmpty())return false;if (m_strFloatImgPath.IsEmpty())return false;hr = m_imgNormal.Load(m_strNormalImgPath);int a = GetLastError();if (FAILED(hr))return false;hr = m_imgPress.Load(m_strPressImgPath);if (FAILED(hr))return false;hr = m_imgFloat.Load(m_strFloatImgPath);if (FAILED(hr))return false;if (bIsPng){if (m_imgNormal.GetBPP() == 32){int i = 0;int j = 0;for (i = 0; i < m_imgNormal.GetWidth(); i++){for (j = 0; j < m_imgNormal.GetHeight(); j++){byte * pbyte = (byte *)m_imgNormal.GetPixelAddress(i, j);pbyte[0] = pbyte[0] * pbyte[3] / 255;pbyte[1] = pbyte[1] * pbyte[3] / 255;pbyte[2] = pbyte[2] * pbyte[3] / 255;}}}if (m_imgPress.GetBPP() == 32){int i = 0;int j = 0;for (i = 0; i < m_imgPress.GetWidth(); i++){for (j = 0; j < m_imgPress.GetHeight(); j++){byte * pbyte = (byte *)m_imgPress.GetPixelAddress(i, j);pbyte[0] = pbyte[0] * pbyte[3] / 255;pbyte[1] = pbyte[1] * pbyte[3] / 255;pbyte[2] = pbyte[2] * pbyte[3] / 255;}}}if (m_imgFloat.GetBPP() == 32){int i = 0;int j = 0;for (i = 0; i < m_imgFloat.GetWidth(); i++){for (j = 0; j < m_imgFloat.GetHeight(); j++){byte * pbyte = (byte *)m_imgFloat.GetPixelAddress(i, j);pbyte[0] = pbyte[0] * pbyte[3] / 255;pbyte[1] = pbyte[1] * pbyte[3] / 255;pbyte[2] = pbyte[2] * pbyte[3] / 255;}}}}MoveWindow(nX, nY, nW, nH);return true;}
//自绘制函数  
void CMyButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{if (!lpDrawItemStruct)return;HDC hMemDC;HBITMAP bmpMem;HGDIOBJ hOldObj;bmpMem = CreateCompatibleBitmap(lpDrawItemStruct->hDC, lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left, lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top);if (!bmpMem)return;hMemDC = CreateCompatibleDC(lpDrawItemStruct->hDC);if (!hMemDC){if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}return;}hOldObj = ::SelectObject(hMemDC, bmpMem);int nW = lpDrawItemStruct->rcItem.right - lpDrawItemStruct->rcItem.left;int nH = lpDrawItemStruct->rcItem.bottom - lpDrawItemStruct->rcItem.top;RECT rectTmp = { 0 };rectTmp = lpDrawItemStruct->rcItem;MapWindowPoints(GetParent(), &rectTmp);if (m_BkImg.IsNull() == false)m_BkImg.Draw(hMemDC, 0, 0, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top, rectTmp.left, rectTmp.top, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top);if (lpDrawItemStruct->itemState & ODS_SELECTED){//按钮被选择  m_imgPress.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);}else{//默认状态  m_imgNormal.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0, nW, nH);}::BitBlt(lpDrawItemStruct->hDC, 0, 0, nW, nH, hMemDC,0,0,SRCCOPY);SelectObject(hMemDC, hOldObj);if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}if (hMemDC){::DeleteDC(hMemDC);hMemDC = NULL;}return;
}void CMyButton::OnMouseMove(UINT nFlags, CPoint point)
{// TODO:  在此添加消息处理程序代码和/或调用默认值CButton::OnMouseMove(nFlags, point);if (!m_bIsInWnd){TRACKMOUSEEVENT       tme;tme.cbSize = sizeof(TRACKMOUSEEVENT);tme.dwFlags = TME_HOVER | TME_LEAVE;tme.dwHoverTime = 10;tme.hwndTrack = m_hWnd;_TrackMouseEvent(&tme);m_bIsInWnd = TRUE;}
}void CMyButton::OnMouseHover(UINT nFlags, CPoint point)
{// TODO:  在此添加消息处理程序代码和/或调用默认值HDC hMemDC;HBITMAP bmpMem;HGDIOBJ hOldObj;HDC hDC = ::GetDC(GetSafeHwnd());CRect rcItem;GetClientRect(&rcItem);if (hDC){bmpMem = CreateCompatibleBitmap(hDC, rcItem.Width(), rcItem.Height());if (!bmpMem){::ReleaseDC(GetSafeHwnd(), hDC);return;}hMemDC = CreateCompatibleDC(hDC);if (!hMemDC){if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}::ReleaseDC(GetSafeHwnd(), hDC);return;}hOldObj = ::SelectObject(hMemDC, bmpMem);RECT rectTmp = { 0 };rectTmp = rcItem;MapWindowPoints(GetParent(), &rectTmp);if (m_BkImg.IsNull() == false)m_BkImg.Draw(hMemDC, 0, 0, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top, rectTmp.left, rectTmp.top, rectTmp.right - rectTmp.left, rectTmp.bottom - rectTmp.top);int nW = rcItem.right - rcItem.left;int nH = rcItem.bottom - rcItem.top;m_imgFloat.AlphaBlend(hMemDC, 0, 0, nW, nH, 0, 0,nW,nH);::BitBlt(hDC, 0, 0, nW, nH, hMemDC, 0, 0, SRCCOPY);SelectObject(hMemDC, hOldObj);if (bmpMem){::DeleteObject(bmpMem);bmpMem = NULL;}if (hMemDC){::DeleteDC(hMemDC);hMemDC = NULL;}::ReleaseDC(GetSafeHwnd(), hDC);}CButton::OnMouseHover(nFlags, point);
}void CMyButton::OnMouseLeave()
{// TODO:  在此添加消息处理程序代码和/或调用默认值CButton::OnMouseLeave();InvalidateRect(NULL);m_bIsInWnd = FALSE;
}

相关文章:

MFC界面美化第三篇----自绘按钮(重绘按钮)

1.前言 最近发现读者对我的mfc美化的专栏比较感兴趣&#xff0c;因此在这里进行续写&#xff0c;这里我会计划写几个连续的篇章&#xff0c;包括对MFC按钮的美化&#xff0c;菜单栏的美化&#xff0c;标题栏的美化&#xff0c;list列表的美化&#xff0c;直到最后形成一个完整…...

设计模式|工厂模式

文章目录 1. 工厂模式的三种实现2. 简单工厂模式和工厂方法模式示例3. 抽象工厂模式示例4. 工厂模式与多态的关系5. 工程模式与策略模式的关系6. 面试中可能遇到的问题6.1 **工厂模式的概念是什么&#xff1f;**6.2 **工厂模式解决了什么问题&#xff1f;**6.3 **工厂模式的优点…...

CHAT~(持续更新)

CHAT&#xff08;持续更新&#xff09; 实现一个ChatGPT创建API设计页面布局业务操作技术架构 实现安装工具 其他 实现一个ChatGPT 创建API 最简单也最需要信息的一步 继续往下做的前提 此处省略&#xff0c;想要获取接口创建方式联系 设计 页面布局 按照官网布局 业务操作…...

linux系统------------Mysql数据库介绍、编译安装

目录 一、数据库基本概念 1.1数据(Data) 1.2表 1.3数据库 1.4数据库管理系统(DBMS) 数据库管理系统DBMS原理 1.5数据库系统&#xff08;DBS) 二、数据库发展史 1、第一代数据库 2、第二代数据库 3、第三代数据库 三、关系型数据库 3.1关系型数据库应用 3.2主流的…...

文件操作3

随机读写数据文件 一、随机读写原理 在我们写数据时&#xff0c;有一个光标不断的在随着新写入的数据往后移动&#xff1b; 而读数据时&#xff0c;也有一个看不见光标&#xff0c;随着已经读完的数据&#xff0c;往后移动 这里的文件读写位置标记——可以想象成图形界面里的…...

算法D57 | 动态规划17 | 647. 回文子串 516.最长回文子序列 动态规划总结篇

647. 回文子串 动态规划解决的经典题目&#xff0c;如果没接触过的话&#xff0c;别硬想 直接看题解。 代码随想录 Python: class Solution:def countSubstrings(self, s: str) -> int:n len(s)dp [[0]*n for _ in range(n)]dp[0] [1]*nresult nfor i in range(1, n)…...

go的限流

背景 服务请求下游&#xff0c;oom&#xff0c;排查下来发现是一个下游组件qps陡增导致 但是司内网络框架比较挫&#xff0c;竟然不负责框架内存问题&#xff08;有内存管理模块&#xff0c;但逻辑又是无限制使用内存&#xff09; 每个请求一个r、w buffer&#xff0c;请求无限…...

补充--广义表学习

第一章 逻辑结构 &#xff08;1&#xff09;A()&#xff0c;A是一个空表&#xff0c;长度为0&#xff0c;深度为1。 &#xff08;2&#xff09;B(d,e)&#xff0c;B的元素全是原子&#xff0c;d和e&#xff0c;长度为2&#xff0c;深度为1。 &#xff08;3&#xff09;C(b,(c,…...

【笔记】KaiOS SPN显示逻辑

更新流程code 1、gonk/dom/system/gonk/radio/RadioInterfaceLayer.jsm handleNetworkStateChanged -> requestNetworkInfo() -> handleRilResponse的getOperator -> handleOperator handleNetworkStateChanged:网络状态变化请求网络信息 this.requestNetworkInfo…...

Visual Basic6.0零基础教学(4)—编码基础,数据类型与变量

编码基础,数据类型与变量 文章目录 编码基础,数据类型与变量前言一、VB中的编程基础二、VB的基本字符集和词汇集1、字符集2、词汇集 VB中的数据类型VB中的变量与常量一.变量和常量的命名规则二.变量声明1.用Dim语句显式声明变量三. 常量 运算符和表达式一. 运算符 1. 算术运算符…...

VPCFormer:一个基于transformer的多视角指静脉识别模型和一个新基准

文章目录 VPCFormer:一个基于transformer的多视角指静脉识别模型和一个新基准总结摘要介绍相关工作单视角指静脉识别多视角指静脉识别Transformer 数据库基本信息 方法总体结构静脉掩膜生成VPC编码器视角内相关性的提取视角间相关关系提取输出融合IFFN近邻感知模块(NPM) patch嵌…...

Android 图形渲染和显示系统关系

SurfaceFlinger&#xff1a;作为 Android 系统中的一个系统服务&#xff0c;SurfaceFlinger 负责管理整个屏幕的渲染和合成工作。它管理和合成多个 Surface&#xff0c;并与硬件加速器以及 Hardware Composer (HWC) 进行交互&#xff0c;最终将图像数据发送给显示硬件进行显示。…...

3.C++:类与对象(下)

一、再谈构造函数 1.1构造函数体赋值 在创建对象时&#xff0c;编译器通过调用构造函数&#xff0c;给对象中各个成员变量一个合适的初始值。 class Date { public:Date(int year, int month, int day){_year year;_month month;_day day;}private:int _year;int _month;i…...

iOS开发之SwiftUI

iOS开发之SwiftUI 在iOS开发中SwiftUI与Objective-C和Swift不同&#xff0c;它采用了声明式语法&#xff0c;相对而言SwiftUI声明式语法简化了界面开发过程&#xff0c;减少了代码量。 由于SwiftUI是Apple推出的界面开发框架&#xff0c;从iOS13开始引入&#xff0c;Apple使用…...

2024-简单点-pandas

pandas pandas to numpy 尽量不用.values提取数据 numexpr 和 bottleneck加速 布尔操作 describe 自定义describe .pipe df.apply 行或者列级别函数级别应用...

面试笔记——Redis(双写一致、持久化)

双写一致 双写一致性&#xff1a; 当修改了数据库中的数据&#xff0c;也要更新缓存的数据&#xff0c;使缓存和数据库中的数据保持一致。 相关问题&#xff1a;使用Redis作为缓存&#xff0c;mysql的数据如何与Redis进行同步&#xff1f;——双写一致性问题 回答时&#xff0…...

【漏洞复现】科立讯通信指挥调度平台editemedia.php sql注入漏洞

漏洞描述 在20240318之前的福建科立讯通信指挥调度平台中发现了一个漏洞。该漏洞被归类为关键级别,影响文件/api/client/editemedia.php的未知部分。通过操纵参数number/enterprise_uuid可导致SQL注入。攻击可能会远程发起。 免责声明 技术文章仅供参考,任何个人和组织使…...

css的active事件在手机端不生效的解决方法

需求&#xff1a;需求就是实现点击图中的 “抽奖” 按钮&#xff0c;实现一个按钮Q弹的放大缩小动画 上面是实现的效果&#xff0c;pc端&#xff0c;点击触发 :active 问题&#xff1a;但是这种方式在模拟器上可以&#xff0c;真机H5一调试就没生效了&#xff0c;下面是简单…...

00. 认识 Java 语言与安装教程

认识 Java Java 在 20 多年发展过程中&#xff0c;与时俱进&#xff0c;为了适应时代的需要&#xff0c;经历过两次重大的版本升级&#xff0c;一个是 Java 5&#xff0c;它提供了泛型等重要的功能。另一个是提供了 Lambda 表达式等重要的功能的 Java 8。 一些重要的 Java 的…...

数据结构-栈-004

1链栈 1.1栈结点结构体定义 /*定义一个数据结构*/ typedef struct student {char name[32];char sex;int age; }DATA_TYPE;/*定义一个栈结点*/ typedef struct stack_node {DATA_TYPE data;//数据域struct stack_node *pnext;//指针域 }STACK_NODE;1.2栈顶结点结构体定义 /*…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

电脑插入多块移动硬盘后经常出现卡顿和蓝屏

当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时&#xff0c;可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案&#xff1a; 1. 检查电源供电问题 问题原因&#xff1a;多块移动硬盘同时运行可能导致USB接口供电不足&#x…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

Java 加密常用的各种算法及其选择

在数字化时代&#xff0c;数据安全至关重要&#xff0c;Java 作为广泛应用的编程语言&#xff0c;提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景&#xff0c;有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序

一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...