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

[LVGL] 在VC_MFC中移植LVGL

前言:

0. 在MFC中开发LVGL的优点是可以用多个Window界面做辅助扩展【类似GUIguider】

1.本文基于VC2022-MFC单文档框架移植lvgl8

2. gitee上下载lvgl8.3 源码,并将其文件夹改名为lvgl

lvgl: LVGL 是一个开源图形库,提供您创建具有易于使用的图形元素、漂亮的视觉效果和低内存占用的嵌入式 GUI 所需的一切。 - Gitee.com

步骤:

1.新建一个MFC应用程序,命名为LVGL_MFC [可以自定义]

2.将下载的lvgl源码放到刚新建的LVGL_MFC工程目录下

3. 设置VS工程的属性:取消C/C++ 预编译头 ;VC++目录包含目录 添加:$(MSBuildThisFileDirectory)lvgl;$(MSBuildThisFileDirectory)lvgl\src;$(IncludePath)

4.在解决方案资源管理器第一栏,点击“显示所有文件”,然后展开lvgl文件夹,在src文件夹右击选择“包含在项目中”。

5.在lvgl目录下将lv_conf_template.h改名为lv_conf.h

6.编译MFC工程,此时应该会出现一个空白的对话框。

7.在lvgl目录下新建文件夹my_porting,文件夹里新建lv_driver_mfc.cpp,并将examples文件夹下的lv_port_disp_template.c 和lv_port_indev_template.c 复制到my_porting目录中,然后两个C文件分别改名为lv_port_disp.c和lv_port_indev.c ;注意将这两个C文件里面开头的#if 0 改为 #if 1 ; 然后在my_porting后击选择“包含在项目中”

8.在lv_port_disp.c中修改如下:

/**********************      DEFINES*********************/
#ifndef MY_DISP_HOR_RES//#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.#define MY_DISP_HOR_RES   400// Define your window size width
#endif#ifndef MY_DISP_VER_RES//#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen height, default value 240 is used for now.#define MY_DISP_VER_RES    400// Define your window size height
#endif#define LV_VER_RES_MAX  600//此函数修改如下
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{extern void mfc_disp_flush_ex(lv_disp_drv_t* disp_drv, const lv_area_t* area, lv_color_t* color_p);if (disp_flush_enabled) {mfc_disp_flush_ex(disp_drv, area, color_p);}return;
}

 9.在lv_port_indev.c中修改如下:

static void mouse_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{extern void mfc_mouse_read_ex(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);mfc_mouse_read_ex(indev_drv, data);return;
}void lv_port_indev_init(void)
{static lv_indev_drv_t indev_drv;/*Register a mouse input device*/lv_indev_drv_init(&indev_drv);indev_drv.type = LV_INDEV_TYPE_POINTER;indev_drv.read_cb = mouse_read;indev_mouse = lv_indev_drv_register(&indev_drv);    return;
}

 10. lv_driver_mfc.cpp 内容如下:

#include "afxdialogex.h"
#include"lvgl.h"
#include <src/hal/lv_hal_disp.h>HWND g_myMainWnd;#include <io.h>
#include <fcntl.h>
void RedirectIOToConsole()
{
#if 1  //enable=1,在MFC下仍能使用printf在cmd窗口看日志,在初始化中调用即可// 分配控制台AllocConsole();// 重定向标准输入、输出和错误流FILE* fp;freopen_s(&fp, "CONOUT$", "w", stdout); // 将 stdout 绑定到控制台freopen_s(&fp, "CONOUT$", "w", stderr); // 将 stderr 绑定到控制台freopen_s(&fp, "CONIN$", "r", stdin);  // 将 stdin 绑定到控制台
#endif
}extern "C"
{void lv_init(void);void lv_port_disp_init(void);void lv_port_indev_init(void);void ui_init(void);void mfc_mouse_read_ex(lv_indev_drv_t* indev_drv, lv_indev_data_t* data);void mfc_disp_flush_ex(lv_disp_drv_t* disp_drv, const lv_area_t* area, lv_color_t* color_p);}void mfc_disp_flush_ex(lv_disp_drv_t* disp_drv, const lv_area_t* area, lv_color_t* color_p)
{CWnd* pWnd = CWnd::FromHandle(g_myMainWnd);CDC* pDC = pWnd->GetDC(); // 获取设备上下文指针if (pDC) {// 定义位图信息BITMAPINFO bitmapInfo;memset(&bitmapInfo, 0, sizeof(bitmapInfo));// 设置位图信息头bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);bitmapInfo.bmiHeader.biWidth = area->x2 - area->x1 + 1;bitmapInfo.bmiHeader.biHeight = -(area->y2 - area->y1 + 1);  // 使用负值以表示自上而下的位图bitmapInfo.bmiHeader.biPlanes = 1;bitmapInfo.bmiHeader.biBitCount = LV_COLOR_DEPTH;  // 与LV_COLOR_DEPTH相符bitmapInfo.bmiHeader.biCompression = BI_RGB;  // 不压缩// 使用StretchDIBits将LVGL显存绘制到窗口,比单点SetPixel刷图效率高很多StretchDIBits(pDC->GetSafeHdc(),area->x1, area->y1,area->x2 - area->x1 + 1,area->y2 - area->y1 + 1,0, 0,area->x2 - area->x1 + 1,area->y2 - area->y1 + 1,color_p,&bitmapInfo,DIB_RGB_COLORS,SRCCOPY);}// 通知LVGL刷新完成lv_disp_flush_ready(disp_drv);
}void mfc_mouse_read_ex(lv_indev_drv_t* indev_drv, lv_indev_data_t* data)
{POINT pt;GetCursorPos(&pt);  // 获取鼠标位置ScreenToClient(g_myMainWnd, &pt);  // 转换为窗口内坐标data->point.x = pt.x;data->point.y = pt.y;data->state = (GetAsyncKeyState(VK_LBUTTON) & 0x8000) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
}UINT Thread_Lvgl_UiTimer(LPVOID pParam)
{while (1){lv_tick_inc(5);// 提供lvlg系统定时基准Sleep(5);  // 模拟耗时任务}return 0;
}UINT Thread_Lvgl_Flushing(LPVOID pParam)
{RedirectIOToConsole();//启动日志printf打印窗口printf("Start Thread_Lvgl_Flushing.\n");int hor = lv_disp_get_hor_res(lv_disp_get_default());int ver = lv_disp_get_ver_res(lv_disp_get_default());printf("window h=%d,v=%d.\n", hor, ver);while (1){lv_timer_handler();Sleep(50);  // 模拟耗时任务}return 0;  // 返回值
}extern "C"
{void my_event_cb(lv_event_t* ev){static int cnt = 0;lv_obj_t* m_parent = lv_scr_act();lv_obj_t* m_label = lv_obj_get_child(m_parent, 0);lv_label_set_text_fmt(m_label, "LVGL Cnt=%d.", ++cnt);printf("UI_Event_Code=%d.Count=%d.\n", ev->code,cnt);}void ui_init(){lv_obj_t* m_parent = lv_scr_act();lv_obj_t* m_label = lv_label_create(m_parent);lv_obj_t* m_btn = lv_btn_create(m_parent);lv_obj_set_style_bg_opa(m_parent, 0xFF, 0);lv_obj_set_style_bg_color(m_parent, lv_color_hex(0xeeaabb), 0);lv_label_set_text(m_label, "LVGL on MFC!");lv_obj_align(m_label, LV_ALIGN_CENTER, 0, 0);lv_obj_align(m_btn, LV_ALIGN_DEFAULT, 0, 50);lv_obj_add_event_cb(m_btn, my_event_cb, LV_EVENT_CLICKED, NULL);}
}void lvgl_init()
{AfxBeginThread(Thread_Lvgl_UiTimer, NULL);AfxBeginThread(Thread_Lvgl_Flushing, NULL);lv_init();lv_port_disp_init();lv_port_indev_init();ui_init();//do your demo ui layout code}

11. 在主界面LVGL_MFCDlg.cpp的OnInitDialog()中添加初始化代码:

	// TODO: 在此添加额外的初始化代码extern HWND g_myMainWnd; g_myMainWnd = m_hWnd;extern void lvgl_init(void);lvgl_init();

12. 在lv_conf_internal.h 修改   #define LV_COLOR_DEPTH 32  【PC在16bit颜色下会有色差】

13.运行效果:

后续:

完整工程VS_Demo:

lvgl_mfc: 基于lvgl8.3源代码移植到MFC(VC2022)单对话框平台。

        

相关文章:

[LVGL] 在VC_MFC中移植LVGL

前言&#xff1a; 0. 在MFC中开发LVGL的优点是可以用多个Window界面做辅助扩展【类似GUIguider】 1.本文基于VC2022-MFC单文档框架移植lvgl8 2. gitee上下载lvgl8.3 源码&#xff0c;并将其文件夹改名为lvgl lvgl: LVGL 是一个开源图形库&#xff0c;提供您创建具有易于使用…...

MySQL视图索引操作

创建学生表&#xff1b; mysql> create table Student(-> Sno int primary key auto_increment,-> Sname varchar(30) not null unique,-> Ssex char(2) check (Ssex男 or Ssex女) not null,-> Sage int not null,-> Sdept varchar(10) default 计算机 not …...

一次奇怪的空指针问题分析:事务、死锁与隐式回滚

最近我们在排查一个诡异的 空指针异常&#xff0c;整个分析过程可以说是跌宕起伏&#xff0c;最终的结论也颇具隐蔽性。今天就把这个问题分享出来&#xff0c;希望对大家有所帮助。 问题现象 在系统中&#xff0c;我们有 单据 B&#xff0c;它通过一个 关联 ID 字段与 上级单…...

解决aspose将Excel转成PDF中文变成方框的乱码问题

原文网址&#xff1a;解决aspose将Excel转成PDF中文变成方框的乱码问题_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何解决aspose将Excel转成PDF中文变成方框的乱码问题。 问题描述 用aspose将word、excel等转成PDF后&#xff0c;英文展示正常&#xff0c;但中文全部变成了…...

.net8.0使用EF连接sqlite数据库及使用Gridify实现查询的简易实现

EF Core EF Core 是一个流行的对象关系映射&#xff08;ORM&#xff09;框架&#xff0c;它简化了与数据库的交互&#xff0c;提供了一个高效、灵活且易于使用的数据访问层。 Entity Framework (EF) Core 是轻量化、可扩展、开源和跨平台版的常用 Entity Framework 数据访问技…...

2025.2.5——五、[网鼎杯 2020 青龙组]AreUSerialz

题目来源&#xff1a;BUUCTF [网鼎杯 2020 青龙组]AreUSerialz 一、打开靶机&#xff0c;整理信息 直接得到一串php代码&#xff0c;根据题目可以看到还有序列化 二、解题思路 step 1&#xff1a;代码审计 <?phpinclude("flag.php");highlight_file(__FILE__…...

电风扇各国检测认证详细介绍美国FCC+UL欧盟CE+ROHS日本PSE+METI备案+英国UKCA

美国 &#xff1a; FCC认证 &#xff1a;产品进入美洲市场的通行证&#xff0c;需通过FCC SDOC认证。 FCC第15部分B: 该标准适用于非故意辐射设备&#xff0c;如家用电器、电脑设备等。它规定了这些设备在电磁环境中不会产生过多的辐射。 ​射频标准: FCC第15部分C:该标准适…...

Flutter Isolate解决耗时任务导致卡死

先来对比一下在Flutter的ui主线程下直接计算一个耗时任务的情况&#xff1a; import package:flutter/material.dart;void main() {runApp(const MaterialApp(home: H(),)); }class H extends StatefulWidget {const H({super.key});overrideState<H> createState() >…...

使用deepseek快速创作ppt

目录 1.在DeekSeek生成PPT脚本2.打开Kimi3.最终效果 DeepSeek作为目前最强大模型&#xff0c;其推理能力炸裂&#xff0c;但是DeepSeek官方没有提供生成PPT功能&#xff0c;如果让DeepSeek做PPT呢&#xff1f; 有个途径&#xff1a;在DeepSeek让其深度思考做出PPT脚本&#xf…...

STM32的HAL库开发---高级定时器---输出比较模式实验

一、高级定时器输出比较模式实验原理 定时器的输出比较模式总共有8种&#xff0c;本文使用其中的翻转模式&#xff0c;当TIMXCCR1TIMXCNT时&#xff0c;翻转OC1REF的电平&#xff0c;OC1REF为输出参考信号&#xff0c;高电平有效&#xff0c;OC1REF信号连接到0C1上面&#xff…...

python Excel 表读取合并单元格以及清除空格符

读取合并单元格并保留合并信息 读取合并单元格并保留合并信息清除各单元格的空格和换行符&#xff0c;并去除列名中的空格和换行符 读取合并单元格并保留合并信息 当我们只是使用 pandas 的 read_excel 方法读取 Excel 文件时&#xff0c;我们可能会遇到一个很棘手的问题&…...

额外题目汇总2-链表

链表 1.24. 两两交换链表中的节点 力扣题目链接(opens new window) 给定一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后的链表。 你不能只是单纯的改变节点内部的值&#xff0c;而是需要实际的进行节点交换。 思路 使用虚拟头结点会很方便&#xff…...

C#控件开发6—指示灯

按钮功能&#xff1a;手自动旋转&#xff0c;标签文本显示、点击二次弹框确认&#xff08;源码在最后边&#xff09;&#xff1b; 【制作方法】 找到控件的中心坐标&#xff0c;画背景外环、内圆&#xff1b;再绘制矩形开关&#xff0c;进行角度旋转即可获得&#xff1b; 【关…...

探索从传统检索增强生成(RAG)到缓存增强生成(CAG)的转变

在人工智能快速发展的当下&#xff0c;大型语言模型&#xff08;LLMs&#xff09;已成为众多应用的核心技术。检索增强生成&#xff08;RAG&#xff09;&#xff08;RAG 系统从 POC 到生产应用&#xff1a;全面解析与实践指南&#xff09;和缓存增强生成&#xff08;CAG&#x…...

【学习总结|DAY036】Vue工程化+ElementPlus

引言 在前端开发领域&#xff0c;Vue 作为一款流行的 JavaScript 框架&#xff0c;结合 ElementPlus 组件库&#xff0c;为开发者提供了强大的构建用户界面的能力。本文将结合学习内容&#xff0c;详细介绍 Vue 工程化开发流程以及 ElementPlus 的使用&#xff0c;助力开发者快…...

【GitHub】GitHub 2FA 双因素认证 ( 使用 Microsoft Authenticator 应用进行二次验证 )

文章目录 一、GitHub 的 2FA 双因素认证二、使用 Microsoft Authenticator 应用进行二次验证1、TOTP 应用2、下载 Microsoft Authenticator 应用3、安装使用 Authenticator 应用 三、恢复码重要性 一、GitHub 的 2FA 双因素认证 现在登录 GitHub 需要进行二次身份验证 ; 先登录…...

c# 2025/2/7 周五

13.《表达式&#xff0c;语句详解1》 18未完。。 表达式&#xff0c;语句详解_1_哔哩哔哩_bilibili...

蓝桥杯思维训练(五)

文章目录 子集II1191.K次串联后最大子数组之和 子集II 子集II 思路分析&#xff1a; 求解子集的问题的关键就是&#xff0c;通过递归与回溯&#xff0c;我们就是得确定以某个元素开始的子集&#xff0c;对于这个题目来说&#xff0c;比较麻烦的一点就是&#xff0c;存在重复的…...

I.MX6ULL 中断介绍下

GIC重点寄存器 1.中断分发器寄存器&#xff08;Distributor register &#xff09; a.Distributor Control Register(中断分发控制寄存器), GICD_CTLR Purpose Enables the forwarding of pending interrupts from the Distributor to the CPU interfaces 使能将挂起的中断从…...

Elasticsearch 生产集群部署终极方案

Elasticsearch 集群部署 1.集群部署1.1 新增用户1.2 优化操作系统1.3 JDK1.4 elasticsearch1.5 开机自启动 2.安全认证功能2.1 生成CA证书2.2 生成密钥2.3 上传至其他节点2.4 修改属主、属组2.5 配置文件添加参数2.6 各节点添加密钥库密码2.7 设置用户密码 1.集群部署 1.1 新增…...

C语言入门知识全解析:基本结构、数据类型及示例特点

1. C语言简介 C语言是一种通用的、过程式的编程语言&#xff0c;由贝尔实验室的Dennis Ritchie在1972年开发。来源&#xff1a;不全面&#xff0c;仅供参考 http://nanhaitongcheng.com/kx/8106.html它被广泛应用于系统软件开发、嵌入式系统、游戏开发等领域。 2. C语言的基本结…...

3步掌握VectorBT:Python量化交易框架的终极指南

3步掌握VectorBT&#xff1a;Python量化交易框架的终极指南 【免费下载链接】vectorbt Find your trading edge, using the fastest engine for backtesting, algorithmic trading, and research. 项目地址: https://gitcode.com/gh_mirrors/ve/vectorbt 在量化交易的世…...

Java Web新手必看:EDUCODER头哥MVC用户登录实战(含JDBC连接避坑指南)

Java Web新手实战&#xff1a;EDUCODER平台MVC用户登录全流程解析 第一次接触Java Web开发时&#xff0c;最让人兴奋的莫过于亲手实现一个完整的用户登录系统。这不仅是对MVC架构的直观理解&#xff0c;更是打通前后端数据流的关键里程碑。在EDUCODER这样的实训平台上&#xff…...

ArcGIS PRO布局视图避坑指南:地图框添加与专题图制作的5个关键步骤

ArcGIS PRO布局视图避坑指南&#xff1a;地图框添加与专题图制作的5个关键步骤 在专业地理信息系统中&#xff0c;布局视图是将数据分析成果转化为出版级图纸的核心环节。许多城市规划师和地质工程师常陷入这样的困境&#xff1a;明明数据框中的地图效果完美&#xff0c;切换到…...

C语言结构体内存对齐原理与实践

1. 结构体内存布局基础在C语言中&#xff0c;结构体&#xff08;struct&#xff09;是一种将不同类型的数据组合成一个整体的复合数据类型。理解结构体在内存中的实际存储方式&#xff0c;对于编写高效、可移植的代码至关重要。让我们从一个简单的例子开始&#xff1a;struct S…...

**实时内核中的任务调度机制:从理论到C++实现的深度探索**在嵌入式系统和高实时性应用中,**实时内核(Real-

实时内核中的任务调度机制&#xff1a;从理论到C实现的深度探索 在嵌入式系统和高实时性应用中&#xff0c;实时内核&#xff08;Real-Time Kernel&#xff09; 是整个系统稳定运行的核心。它不仅负责资源分配&#xff0c;还承担着任务调度、中断响应、同步机制等关键职责。本文…...

从YOLO到A*:手把手教你用PyTorch和OpenCV搭建一个简易的自动驾驶避障仿真器

从YOLO到A*&#xff1a;用PyTorch和OpenCV构建自动驾驶避障仿真器 想象一下&#xff0c;你正坐在一辆自动驾驶汽车里&#xff0c;车辆能够自动识别前方的行人、车辆和障碍物&#xff0c;并规划出安全的行驶路径。这种看似科幻的场景&#xff0c;如今正逐渐成为现实。本文将带你…...

如何用Tool-SQL解决Text2SQL中的条件不匹配问题?实战案例分享

实战解析&#xff1a;用Tool-SQL攻克Text2SQL条件不匹配难题 当数据工程师面对"帮我找出上季度华东区销售额超50万但退货率低于5%的客户"这类业务查询时&#xff0c;传统Text2SQL方案常陷入条件错配的泥潭——系统生成的SQL要么遗漏关键约束&#xff0c;要么将"…...

ncmdumpGUI:一站式NCM音乐格式转换解决方案,轻松搞定加密音乐跨设备播放

ncmdumpGUI&#xff1a;一站式NCM音乐格式转换解决方案&#xff0c;轻松搞定加密音乐跨设备播放 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换&#xff0c;Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 清晨的音乐烦恼…...

从BIOS到BMC:手把手拆解Redfish协议在服务器开机时的‘数据握手’全过程

从BIOS到BMC&#xff1a;手把手拆解Redfish协议在服务器开机时的‘数据握手’全过程 凌晨3点的数据中心&#xff0c;一台刚上电的服务器正以毫秒级速度完成自检。在这不足5秒的瞬间里&#xff0c;BIOS与BMC之间正通过Redfish协议进行着精密的数据舞蹈——这不是简单的信息交换&…...