当前位置: 首页 > 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 新增…...

TalkiePCM:嵌入式LPC语音合成库,纯C++轻量级PCM音频引擎

1. TalkiePCM&#xff1a;嵌入式平台上的轻量级LPC语音合成引擎TalkiePCM 是一个面向资源受限嵌入式系统的纯C语音合成库&#xff0c;其核心目标是在不依赖特定硬件外设&#xff08;如PWM、DAC或I2S控制器&#xff09;的前提下&#xff0c;以最小耦合方式生成标准PCM音频流。它…...

别再只查‘待办’了!Flowable任务查询的三种高级场景:拾取、归还与候选组权限控制详解

Flowable任务管理的三大高阶场景&#xff1a;从候选池到个人待办的完整控制策略 当我们在处理业务流程自动化时&#xff0c;任务管理往往是最容易被简化的环节。大多数开发者止步于基础的待办列表查询&#xff0c;却忽视了任务流转过程中的精细控制。本文将带您深入Flowable任务…...

C++笔记 继承关系中构造和析构顺序(面向对象)

在C面向对象编程中&#xff0c;继承是实现代码复用和类层次设计的核心特性。当存在基类与派生类的继承关系时&#xff0c;构造函数和析构函数的调用顺序有严格的规则——这不仅是面试高频考点&#xff0c;更是避免内存泄漏、保证对象正确初始化/清理的关键。核心结论先明确&…...

Fix | Resolving ImportError: libGL.so.1 Missing in Docker/Local Environments

1. 遇到libGL.so.1缺失报错怎么办&#xff1f; 最近在部署一个基于OpenGL的图形处理项目时&#xff0c;又双叒叕遇到了这个熟悉的报错&#xff1a;"ImportError: libGL.so.1: cannot open shared object file: No such file or directory"。这已经是这个月第三次碰到…...

CryptoJS不同加密模式对比:AES-CBC vs GCM在前端安全中的选择指南

AES加密模式深度解析&#xff1a;CBC与GCM在前端安全中的实战抉择 前端开发者在处理用户敏感数据时&#xff0c;AES加密已成为标配技术方案。但在具体实施过程中&#xff0c;加密模式的选择往往成为决策难点——是选择经典的CBC模式&#xff0c;还是拥抱更现代的GCM模式&#x…...

快马AI助力:十分钟用Python搭建免费股票行情网站原型

最近想验证一个股票行情网站的原型&#xff0c;但作为独立开发者&#xff0c;从零搭建前后端实在太耗时。尝试用PythonFlask快速实现&#xff0c;结合InsCode(快马)平台的AI辅助功能&#xff0c;居然十分钟就完成了基础框架。记录下关键实现思路&#xff1a; 数据获取层设计 选…...

AI 视频生成美女跳舞测评 | 顶级 Prompt实测版(Grok Imagine、Kling AI 3.0、Veo 3.1)

兄弟们&#xff0c;AI 视频生成已经卷到飞起了&#xff01;之前写小黄文靠grok&#xff0c;现在生成“美女舞蹈”视频也得靠它。 今天上手实测截至今天热门的3款视频生成工具&#xff0c;专攻“美女跳舞”这个高难度场景&#xff1a;动作流畅度、人物一致性、性感画面感、提示…...

目录中不显示标题中间的软换行符Shift+Enter

文档中的标题过长时&#xff0c;通常使用ShiftEnter软换行符来给标题在合适的位置换行&#xff0c;以实现美观的排版效果。然而&#xff0c;插入软换行符会造成自动产生的目录中标题文本中间出现空格&#xff0c;如图所示&#xff1a;那么&#xff0c;如何让目录中不显示这个软…...

DLSS状态监控完全指南:从问题诊断到性能优化

DLSS状态监控完全指南&#xff1a;从问题诊断到性能优化 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 你是否曾经遇到过这样的困惑&#xff1a;在游戏中开启了DLSS功能&#xff0c;却无法确定它是否真的在工作&#…...

新能源车BMS低压管理避坑指南:如何解决上下电时序中的典型问题

新能源车BMS低压管理避坑指南&#xff1a;如何解决上下电时序中的典型问题 在新能源汽车的电池管理系统&#xff08;BMS&#xff09;开发中&#xff0c;低压上下电时序控制是确保系统稳定运行的关键环节。许多开发团队在实际项目中都会遇到信号冲突、时序错乱、异常处理机制不完…...