Windows SDK(五)按钮静态文本与编辑框控件
我们首先应该知道,所谓按钮静态文本等等控件都是窗口,他们都是隶属于父窗口下的子窗口,所
以在创建控件前,我们要首先创建一个父窗口,此处我们直接使用Windows桌面程序创建时,程
序自动为我们创建的一个窗口,该窗口如下表示:
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,750,
400, 500, 800, nullptr, nullptr, hInstance, nullptr);
此时我们已经有了一个主窗口,接下来开始讲解控件的创建和应用
在以下控件内容中,我们首先在全局变量中定义我们的控件ID,以便我们后续控件的查找
#define IDC_BUTTON_CHECK_1 0
#define IDC_BUTTON_CHECK_2 1
#define IDC_BUTTON_CHECK_3 2
按钮的创建
常见按钮类型如下:
BS_PUSHBUTTON; 按压式按钮
BS_DEFPUSHBUTTON; 显眼的按压式按钮
BS_CHECKBOX; 复选框
BS_AUTOCHECKBOX; 自动复选框
BS_RADIOBUTTON; 单选按钮
BS_AUTORADIOBUTTON; 自动单选按钮
BS_3STATE; 三状态按钮
BS_AUTO3STATE; 自动三状态按钮
BS_GROUPBOX; 按钮群
BS_OWNERDRAW; 自绘按钮
HWND CreateWindow(LPCTSTR lpClassName,LPCTSTR lpWindowName,DWORD dwStyle,int
x,int y,int nWidth,int nHeight,HWND hWndParent,HMENU hMenu,HANDLE hlnstance,LPVOID lpParam);
如上是我们创建窗口类的函数,该函数除了可以创建窗口以外,也可以创建一些预定义的系统类即
控件,如按钮类,编辑框类等等,所以我们可以根据该函数进行按钮(控件)的设置
由于控件本身属于父窗口,是作为父窗口的子窗口所存在,所以我们的控件在窗口主消息消息中窗
口创建的同时调用,而非在WM_PAINT中绘制控件,也就是如下函数中创建:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
此处创建子窗口即控件
break;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
此时我们正在WM_CREATE选项中创建一个子窗口,作为父窗口的按钮也就是父窗口的控件,并返回新窗口的句柄
HWND hwndButton = CreateWindow(
L"BUTTON", 预设的类名
L"OK", 按钮显示的文字
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 选择应用哪个控件,此处应用按钮
10, 窗口相对于父窗口左上角x坐标
10, 窗口相对于父窗口左上角y坐标
80, 窗口宽度
20, 窗口高度
hWnd, 所创建窗口的父窗口句柄,此处是程序自行创建的窗口的句柄
IDC_BUTTON_CHECK_1, 子窗口ID也是控件ID,一般是全局变量,每个子窗口都要有ID,通常我们要通过该ID找窗口句柄,因为该函数返回的句柄可能不是全局
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE)
);
通过以上步骤我们创建好了一个按钮,创建完毕后我们需要应用它,当我们点击按钮时,发送一个点击消息,该消息发送至消息循环中的WM_COMMAND中,然后进行二次分发,也就是在下面函数中:
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
此处填写点击消息
}
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
此后我们填写点击消息默认在此选项中填写
按钮的应用
在应用按钮之前,我们应该知道wParam:高16为时通知码,低16位是子窗口ID,IParam存储的是
触发消息的子控件的句柄
接下来我们将使用前文中创建的按钮进行应用
应用一:单击按钮,按钮名称改变
if (LOWORD(wParam) == IDC_BUTTON_CHECK_1) 此处判断是子窗口ID是否相等:找到自己想要处理的控件
{
HWND hSWnd = GetDlgItem(hWnd, IDC_BUTTON_CHECK_1); 该函数用于间接获取窗口句柄,利用该函数可以获取返回窗口中指定参数ID的子元素的句柄,此处参数为父窗口的句柄和控件ID
SetWindowText(hSWnd,L’sad’); 此时修改按钮标题为sad
}
应用二:点击一个按钮把另一个按钮名称改变
我们首先要创建第二个按钮:
CreateWindow(
L"BUTTON",
L"but2",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10,
40,
80,
20,
hWnd,
(HMENU)IDC_BUTTON_CHECK_2,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL
);
此时第二个按钮创建完毕
接下来我们要开始按钮的应用了:
if (LOWORD(wParam) == IDC_BUTTON_CHECK_1) 此处判断是否点击子窗口1
{
HWND hSWnd = GetDlgItem(hWnd, IDC_BUTTON_CHECK_2);
SetWindowText(hSWnd,L’sadXS’); 此时修改按钮2标题
}
应用三:隐藏和显示目标按钮
if(IsWindowVisible(hSWnd)) 判断窗口可不可见,此处为可见
{
ShowWindow(hSWnd, SW_HIGH); 隐藏目标窗口
}
else
{
ShowWindow(hSWnd, SW_SHOW); 显示目标窗口
}
应用四:禁用按钮
if(IsWindowEnabled(hSWnd)) 判断按钮是否正常,此处为正常
{
EnableWindow(hSWnd, FALSE); 禁用目标按钮
}
else
{
EnableWindow(hSWnd, TURE); 启用目标窗口
}
应用五:将按钮2的文本修改为按钮1的文本
if (LOWORD(wParam) == IDC_BUTTON_CHECK_2) 点击按钮2
{
HWND hSWnd = GetDlgItem(hWnd, IDC_BUTTON_CHECK_1);
此处有两种获取按钮文本的方式:
方式一:WCHAR szBuffer[256] = { 0 }; 作为获取文本的缓冲区
方式二:DWORD dwLength = GetWindowTextLength(hSWnd)
WCHAR *szBuffer = new WCHAR[dwLength];
GetWindowText(hSWnd, szBuffer, 256) 获取按钮1的文本
SetWindowText((HWND)lParam,szBuffer); 此时修改按钮标题为按钮1的标题
}
复选框的创建
首先我们创建两个复选框
CreateWindow(
L"BUTTON",
L"OK",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_NOTIFY,
注:BS_NOTIFY 用于双击,BS_NOTIFY多选按钮,该类型按钮,点击后,按钮前置空格不会把对号勾上
10,
10,
80,
20,
hWnd,
IDC_BUTTON_CHECK_1,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
CreateWindow(
L"BUTTON",
L"but2",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_CHECKBOX | BS_NOTIFY,
10,
40,
80,
20,
hWnd,
(HMENU)IDC_BUTTON_CHECK_2,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
复选框的应用
应用一:将复选框转换为自动复选框
switch (HIWORD(wParam))
{
case BN_CLICKED: 单击点击时
{
SendMessage((HWND)lParam,BM_SETCHECK,!SendMessage((HWND)lParam,
BM_GETCHECK, 0, 0), 0);
break;
}
}
原理是:单击时发送消息BM_SETCHECK给触发控件的窗口用于检测窗口是否被点击,之后再次发送信息BM_GETCHECK给该窗口以获取该窗口点击状态, 此时该信息取反,如此执行,该多选按钮点击后会有对号勾上
单选框的创建
首先我们要创建一个群用于存放我们的单选框
HWND hGroup = CreateWindow( 此处创建一个群
L"BUTTON",
L"Radio",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_GROUPBOX,
10,
10,
400,
300,
hWnd,
(HMENU)0,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
然后创建两个单选框
CreateWindow( 创建第一个单选框
L"BUTTON",
L"Radio1",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
50,
40,
80,
40,
hGroup,
(HMENU)IDC_BUTTON_CHECK_1,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
CreateWindow( 创建第二个单选框
L"BUTTON",
L"Radio2",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_AUTORADIOBUTTON,
BS_AUTORADIOBUTTON 该类型按钮,点击后,按钮前置空格会自动有对号勾上
50,
80,
80,
40,
hGroup,
(HMENU)IDC_BUTTON_CHECK_2,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
CreateWindow( 创建一个表示ok的按钮
L"BUTTON",
L"OK",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
10,
70,
80,
20,
hWnd,
(HMENU)IDC_BUTTON_CHECK_3
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
此时运行程序后,在一个群中,多个按钮只能有一个被勾选
单选框的应用
应用一:判断某按钮是否被选中
switch (HIWORD(wParam))
{
case BN_CLICKED:
if (LOWORD(wParam) == IDC_BUTTON_CHECK_3) 判断按钮3是否被点击
{
HWND hSWnd = GetDlgItem(hWnd, IDC_BUTTON_CHECK_1);获取窗口1句柄以判断点取状态
if (SendMessage(hSWnd, BM_GETCHECK, 0, 0) == TRUE) 判断该按钮是否被点击
{
MessageBox(NULL, L"选中", L"Msg", MB_OK);
}
else
{
MessageBox(NULL, L"未选中", L"Msg", MB_OK);
}
}
break;
}
自绘按钮的创建
HWND BTN = CreateWindow( 此处创建一个自绘按钮
L"BUTTON",
L"",
WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_OWENRORAW | BS_ICON,
BS_OWENRORAW 可以给图标上色 BS_ICON 可以在图标上加载图片
10,
40,
80,
20,
hWnd,
(HMENU)IDC_BUTTON_CHECK_2,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
此时运行程序,发现创建了一个空的按钮
自绘按钮的应用
应用一:按钮上加载图像
紧跟在按钮创建后面:
SendMessage(BTN, BM_SETIMAGE, IMAGE_ICON, (LPARAM)LoadIcon(NULL, IDI_ERROR)); 该API可以加载一个图在该空白按钮上,此时没有图片地址,所以会加载一个叉号图标
应用二:按钮涂色
该函数在消息循环WM_CTLCOLORBTN设定文字颜色的控件选项中:
return (LRESULT)CreateSolidBrush(RGB(0, 0, 255)); 创建一个实心画刷,此处再次运行程序,按钮变成蓝色
静态文本的创建
CreateWindow(L"static", L"test", WS_VISIBLE | WS_CHILD | SS_LEFT, 10, 10, 100, 30, hWnd,
NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
此处有一个新的获取程序实例句柄的方式:((LPCREATESTRUCT)lParam)->hInstance
此时运行程序以后,有一个test的文本
显示图标的创建
HWND hStatic = CreateWindow(L"static", L"test", WS_VISIBLE | WS_CHILD | SS_ICON, 10, 10, 100, 30, hWnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
SendMessage(hStatic, STM_SETICON, (WPARAM)LoadIcon(NULL, IDI_ERROR), NULL);
此时运行程序,显示一个叉号的图标
显示位图的创建
HWND hStatic = CreateWindow(L"static", L"test", WS_VISIBLE | WS_CHILD | SS_BITMAP, 10, 10, 100, 30, hWnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL);
HBITMAP hBitMap = (HBITMAP)LoadImage(NULL, L"bg.bmp", IMAGE_BITMAP, 500, 100, LR_LOADFROMFILE); 加载位图,假设bg.bmp是我们的文件名
SendMessage(hStatic, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hBitMap);
此时运行程序会加载出我们自己的位图
编辑框的创建
HWND hwndEdit = CreateWindowEx(
0, L"EDIT",
NULL,
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
100, 10, 80, 200,
hWnd,
(HMENU)12138,
(HINSTANCE)GetWindowLongPtr(hWnd, GWLP_HINSTANCE),
NULL);
}
此时运行程序出现一个编辑框,会有垂直滚动条
相关文章:
Windows SDK(五)按钮静态文本与编辑框控件
我们首先应该知道,所谓按钮静态文本等等控件都是窗口,他们都是隶属于父窗口下的子窗口,所 以在创建控件前,我们要首先创建一个父窗口,此处我们直接使用Windows桌面程序创建时,程 序自动为我们创建的一个窗…...
基于SSM框架实现的在线心理评测与咨询系统(技术栈 spring+springmvc+mybatis+jsp+jquery+css)
一、项目简介 本项目是一套基于SSM框架实现的在线心理评测与咨询系统,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试&am…...
GD32F470_ DS18B20温度传感器模块移植
DS18B20温度传感器 DS18B20数字温度传感器提供9位至12位精度的温度测量,并具有非易失性用户可编程上下触发点报警功能。DS18B20通过单总线通信,根据定义,只需要一条数据线(和地线)即可与单片机通信。此外,DS18B20可以直接从数据线…...
【JAVASE】带你了解instanceof和equals的魅力
✅作者简介:大家好,我是橘橙黄又青,一个想要与大家共同进步的男人😉😉 🍎个人主页:再无B~U~G-CSDN博客 1.instanceof instanceof 是 Java 的保留关键字。它的作用是测试…...
【Linux】进程控制详解
目录 前言 进程创建 认识fork 写时拷贝 再谈fork 进程终止 进程退出码 用代码来终止进程 常见的进程终止的方式 exit _exit 进程等待 进程等待的必要性 进程等待的方式 wait waitpid 详解status参数 详解option参数 前言 本文适合有一点基础的人看的&#…...
Mysql 高性能的sql优化方案和建议
优化MySQL的性能是一项复杂而关键的任务,它可以通过多种方式来实现。下面是一些SQL优化的方案和建议: 索引优化: 确保经常查询的列都有索引。但不要过度索引,因为它可能会增加写入操作的开销。使用组合索引来覆盖多个查询条件。…...
鸿蒙实战开发:【实现应用悬浮窗】
如果你要做的是系统级别的悬浮窗,就需要判断是否具备悬浮窗权限。然而这又不是一个标准的动态权限,你需要兼容各种奇葩机型的悬浮窗权限判断。 fun checkPermission(context: Context): Boolean if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)…...
应用开发:python解析斗鱼弹幕
解决问题 互动弹幕,关注提问 ,ai回答 技术 python playwright 调用接口 https://github.com/broven/DouYudanmu/blob/master/douyu.py 演示 放弃 这个根本不是研究方向 定位错误 你浪费下午时间,定位错误 这个跟本不是你的方向。 4个小时看斗…...
【面试经典150 | 动态规划】交错字符串
文章目录 写在前面Tag题目来源解题思路方法一:动态规划 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行…...
设计模式(17):中介者模式
核心: 如果一个系统中对象之间的联系呈现网状结构,对象之间存在大量多对多关系,导致关系及其复杂,这些对象称为“同事对象”。我们可以引入一个中介者对象,使各个同事对象只跟中介者对象打交道,将复杂的网…...
echart 折线图或散点图当横坐标为小数位时,若想显示整数该如何处理?
如图当前是这样的: 横坐标刻度目前是小数位,如果直接将小数位取整则会失去精度,所以我们要做的是刻度即是整数,又能显示小数位对应的数值; 思路就是直接手动设置刻度:设置xAxis的min,max,splitNumber,同时不…...
一套C#自主版权+应用案例的手麻系统源码
手术麻醉信息管理系统源码,自主版权应用案例的手麻系统源码 手术麻醉信息管理系统包含了患者从预约申请手术到术前、术中、术后的流程控制。手术麻醉信息管理系统主要是由监护设备数据采集子系统和麻醉临床系统两个子部分组成。包括从手术申请到手术分配,…...
31.2k star, 免费开源的白板绘图工具 tldraw
31.2k star, 免费开源的白板绘图工具 tldraw 分类 开源分享 项目名: tldraw -- 无限画布白板 Github 开源地址: https://github.com/tldraw/tldraw 在线测试地址: tldraw 文档地址: tldraw SDK tldraw 是一款开源免费的无限画布白板&…...
Redis开源协议调整,我们怎么办?
2024年3月20日, Redis官方宣布,从 Redis 7.4版本开始,Redis将获得源可用许可证 ( RSALv2 ) 和服务器端公共许可证 ( SSPLv1 ) 的双重许可,时间点恰逢刚刚完成最新一轮融资,宣布的时机耐人寻味。 Redis协议调整,对云计算…...
干了三年外包。。。忘了什么是CICD。。。
干了三年外包。。。忘了什么是CICD。。。 CI/CD(持续集成与持续交付) 是一种软件开发实践,它可以帮助我们更快地交付高质量的软件产品。CI/CD的核心思想是将软件开发过程中的各个阶段自动化,从而减少人工干预,提高开发效率和产品质量。本文将…...
【LeetCode】454. 四数相加 II
目录 题目 思路 代码 题目 题目链接:. - 力扣(LeetCode) 给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足: 0 < i, j, k, l < nnums1…...
搜索(DFS BFS)
DFS 常规DFS: 二叉树前序,中序,后序遍历-CSDN博客 void postorderTraversal(root)初始化一个空列表 arrfind访问总树(root,arr)return arrvoid find(temp, arr)if temp 为空return // 调用顺序由前中后序决定find递归访问左子树find递归访问右子树arr加入当前节点…...
koc和kol是什么意思?
一、koc和kol是什么意思? koc和kol是专业术语。KOC是关键意见消费者的意思,是Key Opinion Consumer的缩写;KOL是关键意见领袖的意思,是Key Opinion Leader的缩写。 1、关键意见领袖kol “关键意见领袖”通俗地讲是达人。这些人…...
基于vscode Arduino插件开发Arduino项目
基于vscode Arduino插件开发arduino项目 插件配置问题记录1. 指定编译输出文件夹2. 编译下载时不输出详细信息3. 输出端口信息乱码4. 通过串口输出中文,vscode对应的串口助手上会显示乱码(未解决) 插件配置 环境:Arduino插件版本…...
AI 驱动强大是视频转换处理软件
由 AI 驱动的视频工具包。 增强、转换、录制和编辑视频AI 驱动的顶级视频工具包。 不论是老旧、低质、噪声或模糊的影片/图像,都能升级至 4K,稳定抖动的影片,提升帧率至 120/240fps,并能以全面 GPU 加速进行转换、压缩、录制和编辑…...
从90%到99%:实战提升Tesseract在C++项目中的识别准确率(附调参技巧)
从90%到99%:实战提升Tesseract在C项目中的识别准确率(附调参技巧) 在工业级文档处理系统中,我们常遇到这样的困境:测试集上的OCR识别准确率卡在90%左右,而业务部门要求必须达到99%以上才能上线。去年负责某…...
目标检测:YOLOv12训练自己的数据集,手把手教学一看就会
目录 1. 环境配置 2. 数据集 2.1 网上搜索公开数据集 2.1.1 搜索引擎 2.1.2 Kaggle 2.1.3 Roboflow 2.2 自制数据集 2.2.1 Labelimg安装 2.2.2 Labelimg使用 2.3 数据集转换及划分 2.3.1 数据集VOC格式转yolo格式 2.3.2 数据集划分 3. 训练模型 3.1 创建data.yam…...
构建 AI Agent 应用商店的构想
构建 AI Agent 应用商店的构想:从“单骑救主”的工具到“生态协同”的智能枢纽关键词 AI Agent、应用商店、多Agent协作、工具调用链、Prompt工程标准化、安全沙箱、智能分发摘要 当你在凌晨2点对着一份混乱的月度财务报表焦虑时,有没有想过:…...
告别I2C的龟速:用STM32的SPI接口榨干ICM20948的性能(实测对比与配置优化)
突破传感器性能瓶颈:STM32 SPI驱动ICM20948的极致优化实践 在无人机飞控、姿态解算和高频数据采集领域,传感器接口的选择往往成为系统性能的决定性因素。当开发者面对ICM20948这款集成了三轴陀螺仪、加速度计和磁力计的9轴运动传感器时,一个关…...
别再硬编码数据了!用QAbstractTableModel+QTableView打造你的第一个Qt桌面表格应用(附完整源码)
从零构建Qt桌面表格应用:实战学生信息管理系统 在桌面应用开发领域,数据展示与交互一直是核心需求。无论是企业内部的员工管理系统,还是学校里的成绩统计工具,一个高效、美观的表格界面往往能极大提升工作效率。对于C开发者而言&a…...
别再只盯着Modbus了!聊聊MBUS总线在智慧水务中的那些坑与最佳实践
MBUS总线在智慧水务中的实战指南:从协议解析到避坑实践 当智慧水务项目进入实施阶段,技术选型团队往往会陷入协议选择的困境。Modbus以其通用性成为首选,LoRa凭借无线优势占据一席之地,而MBUS(Meter-Bus)这…...
DDrawCompat完整教程:Windows 11上经典游戏DirectDraw兼容性修复终极指南
DDrawCompat完整教程:Windows 11上经典游戏DirectDraw兼容性修复终极指南 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh…...
百度网盘秒传技术终极指南:打破文件分享的时间限制
百度网盘秒传技术终极指南:打破文件分享的时间限制 【免费下载链接】rapid-upload-userscript-doc 秒传链接提取脚本 - 文档&教程 项目地址: https://gitcode.com/gh_mirrors/ra/rapid-upload-userscript-doc 在数字信息爆炸的时代,文件分享已…...
SpringBoot项目里用Sharding-JDBC做分库分表,这5个配置项最容易踩坑
SpringBoot整合Sharding-JDBC分库分表:五大高频配置陷阱与实战解决方案 当数据库单表数据量突破千万级大关时,分库分表几乎是每个Java开发者必须面对的课题。作为Apache ShardingSphere的核心模块,Sharding-JDBC以其轻量级、低侵入的特性成为…...
终极指南:5分钟让Figma界面全面中文化,设计师效率翻倍!
终极指南:5分钟让Figma界面全面中文化,设计师效率翻倍! 【免费下载链接】figmaCN 中文 Figma 插件,设计师人工翻译校验 项目地址: https://gitcode.com/gh_mirrors/fi/figmaCN 还在为Figma的英文界面而烦恼吗?每…...
