VS2019+MFC+MySQL登录界面实战:从环境配置到代码实现

1. 项目缘起与整体设计思路

1.1 为什么还在用 MFC 做登录界面

先把话说在前头:MFC 不是什么新东西,但它在某些场景下依然有不可替代的位置。我接触过不少做工业控制、医疗设备上位机、实验室仪器配套软件的团队,他们的技术栈就是 VS2019 + MFC + MySQL 这套组合。原因很实在——存量代码多、界面响应快、部署简单、不依赖运行时环境,一个 exe 拷过去就能跑。

登录界面是所有管理系统的第一道门。别看它简单,麻雀虽小五脏俱全:要有输入框、要有密码掩码、要有登录按钮的响应逻辑、要连接数据库做校验、还要处理各种异常情况。很多新手觉得“不就是个登录嘛”,结果一上手就卡在环境配置、字符集乱码、连接失败这些问题上,折腾一整天都跑不起来。

这篇内容就是把我自己踩过的坑和验证过的流程完整梳理一遍。适合两类人看:一类是刚接触 MFC 的学生或者转岗开发者,需要快速跑通一个能用的登录 Demo;另一类是有一定基础但每次配 MySQL 连接都要重新查资料的老手,可以当作一份速查手册。核心关键词就三个:VS2019、MFC、MySQL 连接,围绕这三个词把登录界面从零到一讲透。

1.2 整体架构与技术选型考量

这个项目的架构非常简单,三层结构:界面层(MFC 对话框)→ 业务逻辑层(登录校验函数)→ 数据层(MySQL 数据库)。没有复杂的框架,没有 ORM 映射,就是最朴素的 C++ 调用 MySQL C API。

为什么不用 ODBC?因为 ODBC 需要额外配置数据源,换一台机器就要重新配一遍,部署起来麻烦。而 MySQL C API 是直接链接库文件,把 libmysql.dll 和 libmysql.lib 一起打包就行,对单机部署的桌面程序来说更省心。

为什么不用 MySQL Connector/C++?那个是基于 JDBC 风格的接口,用起来确实更“现代”,但它依赖的运行时库更多,而且不同版本之间的 ABI 兼容性经常出问题。对于 MFC 这种偏传统的技术栈,用最原始的 C API 反而最稳。

数据库表的设计也很简单,一张用户表就够了:

CREATE TABLE user_info ( id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

注意:密码字段这里先存明文,是为了让 Demo 跑通。实际项目里必须做哈希加盐处理,后面我会专门讲这块怎么改。

2. 环境准备与依赖配置

2.1 VS2019 安装时的关键选项

VS2019 的安装器里,工作负载要勾选“使用 C++ 的桌面开发”。这个大类下面有几个组件必须确认勾上:

  • MSVC v142 - VS 2019 C++ x64/x86 生成工具:这是编译器核心,不勾什么都干不了。
  • Windows 10 SDK:选最新版本就行,MFC 的头文件依赖它。
  • C++ MFC 最新 v142 生成工具:这个默认是不勾的,必须手动勾上,否则新建项目时找不到 MFC 模板。
  • C++ ATL 最新 v142 生成工具:MFC 内部依赖 ATL 的部分组件,建议一起勾上。

安装完之后,打开 VS2019 新建项目,在搜索框输入“MFC”,应该能看到“MFC 应用”模板。如果看不到,说明 MFC 组件没装好,回到安装器里补勾。

2.2 MySQL 服务端与开发库的版本匹配

MySQL 的版本选择有个坑:服务端版本和开发库版本必须匹配。我见过有人服务端装的是 MySQL 8.0,开发库却下载了 5.7 的,结果编译能过,运行时报“找不到指定模块”或者直接崩溃。

推荐的做法是:服务端装什么版本,开发库就下什么版本。MySQL 官网提供两个东西:

  1. MySQL Installer:用来装服务端和 Workbench 管理工具。
  2. MySQL Connector/C:这是纯 C 语言的连接库,包含头文件和 lib 文件。

下载 Connector/C 的时候注意选对平台。VS2019 默认编译的是 32 位程序(除非你手动改成 x64),所以要下 32 位的库。如果你打算编译 64 位程序,那就下 64 位的。两者不能混用。

安装完 Connector/C 之后,目录结构大概是这样:

C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\ ├── include\ │ ├── mysql.h │ ├── mysql_com.h │ └── ... ├── lib\ │ ├── libmysql.lib │ ├── libmysql.dll │ └── ...

记住这个路径,后面配置项目属性要用。

2.3 项目属性配置的四个关键位置

新建 MFC 项目之后,右键项目 → 属性,需要改四个地方。这里以 32 位 Debug 配置为例:

第一处:C/C++ → 常规 → 附加包含目录

添加 Connector/C 的 include 路径:

C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\include

第二处:链接器 → 常规 → 附加库目录

添加 lib 路径:

C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib

第三处:链接器 → 输入 → 附加依赖项

添加:

libmysql.lib

第四处:把 libmysql.dll 拷贝到输出目录

这一步最容易忘。libmysql.lib 只是导入库,运行时真正加载的是 libmysql.dll。你需要把 Connector/C 的 lib 目录下的 libmysql.dll 拷贝到你的项目输出目录(通常是项目名\Debug\或项目名\x64\Debug\)。

实操心得:我习惯在项目根目录建一个libs文件夹,把 include、lib、dll 都放进去,然后用相对路径配置。这样整个项目拷到别的机器上也能直接编译,不用重新配路径。

3. 登录界面设计与核心代码实现

3.1 对话框布局与控件命名

在资源视图里打开主对话框,把默认的“TODO: 在此放置对话框控件”删掉,然后拖入以下控件:

控件类型ID用途
Static TextIDC_STATIC_USER显示“用户名:”
Edit ControlIDC_EDIT_USER输入用户名
Static TextIDC_STATIC_PWD显示“密码:”
Edit ControlIDC_EDIT_PWD输入密码
ButtonIDC_BTN_LOGIN登录按钮
ButtonIDC_BTN_EXIT退出按钮

密码输入框要设置一个属性:在属性面板里找到Password,设为True。这样输入的内容会显示为圆点,不会明文暴露。

另外建议把对话框的System Menu设为 False,去掉标题栏的关闭按钮,防止用户直接点 X 绕过登录逻辑(虽然 Demo 里无所谓,但养成习惯是好的)。

3.2 数据库连接类的封装

直接在对话框类里写 MySQL 连接代码不是不行,但复用性差。我习惯封装一个简单的数据库工具类,叫CDbHelper。核心代码如下:

// DbHelper.h #pragma once #include <mysql.h> #include <string> class CDbHelper { public: CDbHelper(); ~CDbHelper(); bool Connect(const std::string& host, const std::string& user, const std::string& password, const std::string& dbName, unsigned int port = 3306); void Disconnect(); bool CheckLogin(const std::string& username, const std::string& password); std::string GetLastError(); private: MYSQL* m_pConn; std::string m_lastError; };

实现文件:

// DbHelper.cpp #include "pch.h" #include "DbHelper.h" CDbHelper::CDbHelper() : m_pConn(nullptr) { m_pConn = mysql_init(nullptr); if (m_pConn) { // 设置字符集为 utf8mb4,防止中文乱码 mysql_options(m_pConn, MYSQL_SET_CHARSET_NAME, "utf8mb4"); } } CDbHelper::~CDbHelper() { Disconnect(); } bool CDbHelper::Connect(const std::string& host, const std::string& user, const std::string& password, const std::string& dbName, unsigned int port) { if (!m_pConn) { m_lastError = "mysql_init failed"; return false; } if (!mysql_real_connect(m_pConn, host.c_str(), user.c_str(), password.c_str(), dbName.c_str(), port, nullptr, 0)) { m_lastError = mysql_error(m_pConn); return false; } return true; } void CDbHelper::Disconnect() { if (m_pConn) { mysql_close(m_pConn); m_pConn = nullptr; } } bool CDbHelper::CheckLogin(const std::string& username, const std::string& password) { if (!m_pConn) return false; // 使用 mysql_real_escape_string 防止 SQL 注入 char escapedUser[256] = { 0 }; char escapedPwd[256] = { 0 }; mysql_real_escape_string(m_pConn, escapedUser, username.c_str(), username.length()); mysql_real_escape_string(m_pConn, escapedPwd, password.c_str(), password.length()); std::string sql = "SELECT id FROM user_info WHERE username='"; sql += escapedUser; sql += "' AND password='"; sql += escapedPwd; sql += "' LIMIT 1"; if (mysql_query(m_pConn, sql.c_str()) != 0) { m_lastError = mysql_error(m_pConn); return false; } MYSQL_RES* res = mysql_store_result(m_pConn); if (!res) { m_lastError = mysql_error(m_pConn); return false; } bool found = (mysql_num_rows(res) > 0); mysql_free_result(res); return found; } std::string CDbHelper::GetLastError() { return m_lastError; }

这段代码有几个关键点值得展开说。

第一,mysql_options 设置字符集。很多人连接数据库之后发现中文用户名查不到,就是因为字符集没设对。MySQL 8.0 默认是 utf8mb4,但 C API 默认可能是 latin1,两边不一致就会出问题。在 mysql_init 之后、mysql_real_connect 之前调用 mysql_options 设置字符集,是最稳妥的做法。

第二,mysql_real_escape_string 防注入。登录框是 SQL 注入的重灾区。如果用户输入' OR '1'='1,拼接出来的 SQL 就变成了SELECT id FROM user_info WHERE username='' OR '1'='1' AND password='...',直接绕过校验。用 escape 函数把特殊字符转义掉,能挡住绝大部分注入攻击。

第三,mysql_store_result 和 mysql_free_result 必须配对。每次查询完都要把结果集释放掉,否则内存会持续泄漏。在长时间运行的程序里,这个泄漏会累积到程序崩溃。

3.3 登录按钮的响应逻辑

在对话框类里添加一个成员变量CDbHelper m_db;,然后在 OnInitDialog 里初始化连接:

BOOL CLoginDlg::OnInitDialog() { CDialogEx::OnInitDialog(); // 尝试连接数据库 if (!m_db.Connect("127.0.0.1", "root", "your_password", "test_db")) { CString errMsg; errMsg.Format(_T("数据库连接失败:%s"), CString(m_db.GetLastError().c_str())); AfxMessageBox(errMsg); } return TRUE; }

登录按钮的响应函数:

void CLoginDlg::OnBnClickedBtnLogin() { CString strUser, strPwd; GetDlgItemText(IDC_EDIT_USER, strUser); GetDlgItemText(IDC_EDIT_PWD, strPwd); // 空值校验 if (strUser.IsEmpty() || strPwd.IsEmpty()) { AfxMessageBox(_T("用户名和密码不能为空")); return; } // 长度校验 if (strUser.GetLength() > 50 || strPwd.GetLength() > 100) { AfxMessageBox(_T("输入长度超出限制")); return; } // 转换为 std::string(注意宽字符转窄字符) CT2A userA(strUser); CT2A pwdA(strPwd); if (m_db.CheckLogin(std::string(userA), std::string(pwdA))) { AfxMessageBox(_T("登录成功")); // 这里可以跳转到主界面 // CDialogEx::OnOK(); } else { AfxMessageBox(_T("用户名或密码错误")); // 清空密码框,方便重新输入 SetDlgItemText(IDC_EDIT_PWD, _T("")); GetDlgItem(IDC_EDIT_PWD)->SetFocus(); } }

这里有个字符转换的细节:MFC 默认使用 Unicode 字符集,CString 是宽字符(wchar_t),而 MySQL C API 用的是窄字符(char)。所以需要转换。CT2A是 ATL 提供的转换宏,会自动处理编码转换。如果项目用的是多字节字符集,那就不需要转换,直接用strUser.GetBuffer()就行。

注意:CT2A 转换后的字符串生命周期只在当前作用域内有效,不要把它保存到全局变量里。

4. 常见问题排查与避坑指南

4.1 连接失败的五种典型情况

数据库连接失败是新手遇到最多的问题,没有之一。我把常见的失败原因整理成一张速查表:

错误信息关键词可能原因解决方法
Can't connect to MySQL serverMySQL 服务没启动在服务管理器里启动 MySQL 服务
Access denied for user用户名或密码错误检查连接参数,确认 root 密码
Unknown database数据库名写错或不存在在 Workbench 里确认数据库已创建
Can't connect to MySQL server on '127.0.0.1'端口不对或被防火墙拦截确认端口是 3306,检查防火墙规则
找不到 libmysql.dlldll 没拷贝到输出目录把 dll 拷到 exe 同级目录

还有一种情况是编译时报“无法打开 libmysql.lib”,这说明附加库目录配错了,或者 lib 文件和当前编译平台不匹配(32 位项目用了 64 位的 lib)。

4.2 中文乱码的根因分析

中文乱码的本质是编码不一致。数据从输入框到数据库,中间经过了多个环节,每个环节都有自己的编码方式:

  1. MFC 输入框:Unicode(宽字符)
  2. CT2A 转换:取决于系统区域设置,中文系统默认是 GBK
  3. MySQL C API:默认 latin1,需要手动设为 utf8mb4
  4. MySQL 表字段:建表时指定的字符集
  5. MySQL 服务端:配置文件里的 character-set-server

只要有一个环节不一致,就会出现乱码。最稳妥的做法是全部统一为 utf8mb4:

  • 建表时指定DEFAULT CHARSET=utf8mb4
  • 连接后执行SET NAMES utf8mb4
  • 或者在 mysql_options 里设置MYSQL_SET_CHARSET_NAME为utf8mb4
  • CT2A 转换时指定代码页为 CP_UTF8:CT2A userA(strUser, CP_UTF8);

我实测下来,最后这种组合最稳:数据库、表、连接全部 utf8mb4,CT2A 显式指定 CP_UTF8。

4.3 密码明文存储的安全隐患

Demo 里密码是明文存的,但实际项目绝对不能这么干。正确的做法是:

  1. 注册时:生成一个随机盐值(salt),把password + salt做哈希(推荐 bcrypt 或 argon2),把哈希值和盐值一起存进数据库。
  2. 登录时:根据用户名取出盐值,把用户输入的密码加盐哈希,和数据库里的哈希值比对。

如果不想引入第三方哈希库,至少也要用 SHA-256 加盐。虽然 SHA-256 抗暴力破解能力不如 bcrypt,但比明文强太多了。

// 伪代码示意 std::string salt = GenerateRandomSalt(); std::string hash = SHA256(password + salt); // 存库:INSERT INTO user_info (username, password, salt) VALUES (?, ?, ?)

实操心得:盐值长度建议至少 16 字节,每个用户独立生成,不要用固定盐。固定盐等于没加盐,彩虹表照样能破。

4.4 内存泄漏与资源释放

MySQL C API 有几个资源需要手动释放:

  • mysql_init返回的 MYSQL* 需要mysql_close
  • mysql_store_result返回的 MYSQL_RES* 需要mysql_free_result
  • mysql_fetch_row返回的 MYSQL_ROW 不需要手动释放,它指向结果集内部的内存

在 Debug 模式下,VS 会在程序退出时输出内存泄漏报告。如果看到Detected memory leaks!,大概率是某个 MYSQL_RES 忘了释放。我的习惯是在每个mysql_store_result之后立刻写mysql_free_result,中间不要插入其他逻辑,避免忘记。

5. 功能扩展与优化方向

5.1 记住用户名功能的实现

“记住用户名”是个很实用的功能,实现起来也不复杂。思路是把用户名写进注册表或者配置文件,下次打开时自动填充。

用注册表的方式:

// 保存 HKEY hKey; RegCreateKeyEx(HKEY_CURRENT_USER, _T("Software\\MyLoginApp"), 0, nullptr, REG_OPTION_NON_VOLATILE, KEY_WRITE, nullptr, &hKey, nullptr); RegSetValueEx(hKey, _T("LastUser"), 0, REG_SZ, (const BYTE*)strUser.GetString(), (strUser.GetLength() + 1) * sizeof(TCHAR)); RegCloseKey(hKey); // 读取 TCHAR buf[256] = { 0 }; DWORD bufSize = sizeof(buf); DWORD type = REG_SZ; if (RegOpenKeyEx(HKEY_CURRENT_USER, _T("Software\\MyLoginApp"), 0, KEY_READ, &hKey) == ERROR_SUCCESS) { RegQueryValueEx(hKey, _T("LastUser"), nullptr, &type, (LPBYTE)buf, &bufSize); RegCloseKey(hKey); SetDlgItemText(IDC_EDIT_USER, buf); }

用配置文件的方式更简单,直接读写 ini 文件:

WritePrivateProfileString(_T("Login"), _T("LastUser"), strUser, _T(".\\config.ini")); GetPrivateProfileString(_T("Login"), _T("LastUser"), _T(""), buf, 256, _T(".\\config.ini"));

两种方式各有优劣:注册表更“正规”,但卸载时容易残留;ini 文件更直观,但容易被用户误删。我个人偏好 ini 文件,因为调试方便,出问题了直接打开看就行。

5.2 登录失败次数限制

为了防止暴力破解,可以加一个失败次数限制:连续失败 3 次就锁定账号 5 分钟。实现思路是在数据库里加两个字段:

ALTER TABLE user_info ADD COLUMN fail_count INT DEFAULT 0; ALTER TABLE user_info ADD COLUMN lock_until TIMESTAMP NULL;

每次登录失败时fail_count + 1,达到阈值就设置lock_until = NOW() + INTERVAL 5 MINUTE。登录时先检查lock_until是否大于当前时间,如果是就拒绝登录。

这个逻辑放在 SQL 里做比放在 C++ 里做更可靠,因为 SQL 是原子的,不会出现并发问题。

5.3 从 Demo 到生产环境的差距

这个 Demo 跑通之后,距离生产环境还有不少距离。我列几个必须补上的点:

  • 密码加密:前面说过了,必须做哈希加盐。
  • 连接池:Demo 里是单连接,并发高了会排队。生产环境要用连接池。
  • 日志记录:每次登录成功/失败都要记日志,方便审计和排查。
  • 异常处理:网络断开、数据库重启这些情况要有兜底逻辑,不能直接崩溃。
  • 界面美化:MFC 默认界面比较朴素,可以用自绘或者第三方库美化一下。

不过话说回来,Demo 的价值在于跑通流程、理解原理。把这些基础打牢了,往上加功能就是水到渠成的事。

6. 我个人在实际操作中的几点体会

最后分享几个我在实际项目中总结的小经验,都是文档里不会写的。

第一,连接字符串不要硬编码。我见过太多项目把数据库密码写死在代码里,换环境就要重新编译。正确的做法是放在配置文件里,程序启动时读取。哪怕是个 Demo,养成这个习惯也是好的。

第二,编译平台要统一。32 位和 64 位的库不能混用,这个坑我踩过不止一次。建议在项目属性里明确指定目标平台,不要用“Any CPU”这种模糊的选项。

第三,测试用例要覆盖边界情况。空用户名、超长用户名、特殊字符、SQL 注入尝试,这些都要测一遍。我习惯在数据库里预置几个测试账号,包括一个用户名为空的、一个密码为空的,专门用来验证边界逻辑。

第四,libmysql.dll 的版本要和 lib 文件一致。有时候从不同地方下载的 dll 和 lib 版本不匹配,编译能过但运行时报错。最保险的做法是只用 Connector/C 安装目录里的那一套,不要从别处拷贝。

这套流程我前后配过不下十次,每次换新机器都要重新走一遍。现在把它完整写下来,一方面是给自己留个备忘,另一方面也希望能帮到正在踩坑的人。MFC 虽然老,但把基础打扎实了,后面学 Qt 或者 Web 开发,很多概念是相通的。

相关新闻

浏览器里的VSCode:安卓平板开发者的远程IDE实战指南

浏览器里的VSCode:安卓平板开发者的远程IDE实战指南

1. 为什么“浏览器里的VSCode”不是噱头&#xff0c;而是安卓平板开发者的现实刚需最近在某高校的移动开发实训课上&#xff0c;带教导师让学员用安卓平板完成一个轻量级API调试任务。结果一半人卡在环境搭建环节&#xff1a;装Termux配Python环境失败&#xff0c;另一部分人试…

2026/10/19 16:16:11 阅读更多 →
Spring Boot+微信小程序宠物领养平台全栈开发实战解析

Spring Boot+微信小程序宠物领养平台全栈开发实战解析

宠物领养平台这个题目&#xff0c;在 Java 全栈项目里算是出现频率很高的类型了。我前后带过好几个版本&#xff0c;从最早的 PC 端后台&#xff0c;到后面配合微信小程序做前后端分离&#xff0c;踩过的坑不算少。今天这篇文章&#xff0c;就按最近一版“Java Spring Boot 微…

2026/10/19 16:16:11 阅读更多 →
TensorFlow分布式FFT落地方案:选型、实现与调优指南

TensorFlow分布式FFT落地方案:选型、实现与调优指南

1. 分布式FFT到底解决什么问题做数值计算的人对快速傅里叶变换&#xff08;FFT&#xff09;都不陌生&#xff0c;但TensorFlow里的分布式快速傅里叶变换&#xff0c;表面看是把一个FFT调用包进tf.distribute&#xff0c;实际上牵扯到数据划分方式、通信模式、内存墙三件难缠的事…

2026/10/19 16:14:54 阅读更多 →

最新新闻

菲涅尔衍射模型解析WiFi呼吸检测:从原理到工程实践

菲涅尔衍射模型解析WiFi呼吸检测:从原理到工程实践

1. 从光学衍射到无线感知&#xff1a;这个项目到底在做什么 菲涅尔衍射和WiFi呼吸检测&#xff0c;乍一看是两个八竿子打不着的领域。一个是光学课本里的经典波动光学内容&#xff0c;一个是近几年火起来的无线感知应用。但把这两个东西放在一起&#xff0c;恰恰说明了一个很有…

2026/10/19 20:48:59 阅读更多 →
西门子1200与FactoryIO机械手仿真:状态机实现虚拟调试全流程

西门子1200与FactoryIO机械手仿真:状态机实现虚拟调试全流程

做工业自动化调试&#xff0c;最怕设备还没到场、程序就得交付&#xff1b;最怕机械没接线、电气没上电&#xff0c;写好的逻辑只能在脑子里跑。我前阵子捣鼓的一套FactoryIO机械手仿真取料程序&#xff0c;算是把这个困局撕开了一个口子&#xff1a;FactoryIO提供虚拟车间&…

2026/10/19 20:48:59 阅读更多 →
图表设计实战指南:从认知到维护的完整方法论

图表设计实战指南:从认知到维护的完整方法论

1. 从"diagram-design"这个标题能读出什么 第一次看到"diagram-design"这个标题&#xff0c;我的直觉是&#xff1a;这大概率不是一个单纯的"画图工具推荐"或者"设计规范文档"&#xff0c;而是一个把 图表设计 这件事当成一个完整工…

2026/10/19 20:46:54 阅读更多 →
图表设计方法论:从沟通逻辑到视觉规范的完整实践指南

图表设计方法论:从沟通逻辑到视觉规范的完整实践指南

1. 图表设计&#xff1a;从“画出来”到“讲清楚”这些年我看了不少技术文档、项目方案和系统说明&#xff0c;发现一个共性问题&#xff1a;大部分人根本不把图表当“设计”来做&#xff0c;而是当“画图”来应付。打开绘图工具&#xff0c;拖几个方框&#xff0c;连几条线&am…

2026/10/19 20:43:51 阅读更多 →
Python+Vue游戏装备交易商城系统:架构设计与实战全解析

Python+Vue游戏装备交易商城系统:架构设计与实战全解析

“基于PythonVue的游戏装备交易商城系统”这个标题&#xff0c;我太熟了。这几乎是每一届想做点东西但又不想只写个管理系统的同学都会碰到的题&#xff0c;也是后台私信里被问得最多的项目类型之一。但说句实话&#xff0c;真正把“交易”两个字做明白的&#xff0c;十个里可能…

2026/10/19 20:42:50 阅读更多 →
Java授权实战:TrueLicense密钥管理与License验证全解析

Java授权实战:TrueLicense密钥管理与License验证全解析

开头&#xff1a;从一次授权失效事故说起 做Java桌面应用授权这块&#xff0c;很多团队第一反应就是找个现成的License库&#xff0c;生成个密钥文件塞进去&#xff0c;完事。我早年也这么干过&#xff0c;结果用户改了系统时间&#xff0c;软件直接罢工&#xff1b;换台机器&a…

2026/10/19 20:42:50 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介&#xff1a;本资源为电源技术方向的学术研究文档&#xff0c;聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略&#xff0c;面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址&#xff1a; https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集&#xff0c;共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →