2502,索界面3
原文
SonicUI,你从未见过的方便GUI引擎-源码
介绍
SonicUI是基于原生GDIAPI的GUI引擎.它提供了几个简单的UI组件来实现高效的UI效果,如自绘按钮,不规则窗口,动画,窗口中的网径和图像操作方法.
主要目的是用最少的代码来达到最佳效果.
背景
周知,UI开发一般重复用无趣.因此,设计此引擎时遵守了两个原则:易于使用和高效.看看下面引擎的用法,和一些有趣的要点.
使用代码
首先,让我介绍类工厂和组件管:ISonicUI.用此接口来创建和析构对象,并用作某些全局函数.
1.显示和旋转图像
图像操作接口:ISonicImage,用来加载,保存,旋转,拉伸,灰度或HSL调整等.感谢CxImage的作者,我使用此库来避免编码或解码多种图像格式.
但是,在由CxImage加载图像并按标准dib格式转换后,我自己处理它们.ISonicImage的用法很简单:
ISonicImage * pImg = GetSonicUI()->CreateImage();
pImg->Load("C:\\demo.png");
pImg->Rotate(90);
pImg->Draw(hdc);
2.制作一个网径
使用某些控件输出彩色串,或向窗口添加网径可能很无聊.使用原生GDIAPI,你必须不断地选择不同字体或其他GDI对象进出dc.
但是,使用ISonicString,你只需三到四行就可干活.
ISonicString * pStr = GetSonicUI()->CreateString();
pStr->Format("/a='http://hi.csdn.net/zskof', c=%x/Hello I'm a clik", RGB(0, 0, 255));
pStr->TextOut(hdc, 10, 10);
注意:不要在WM_PAINT过程中创建ISonicString并设置其格式,以避免重复初化,及在BeginPaint()和EndPaint()间放置pStr->TextOut()方法.
是的,在没有在窗口中放置控件,或不关心无聊的分发消息时,仅需三行即可构成一个网径,这似乎是不可能的吗?嗯,这只是子类的把戏.
这样,你可让你的代码与超文本代码一样简单.你唯一要参加的是ISonicString的关键字.你可在ISonicUI.h接口文件中找到特定的说明.
3.制作动画自绘按钮
对UI人,也很熟悉自定义按钮.使用ISonicString,可轻松创建漂亮的按钮,只与创建网径稍有不同.
void WINAPI OnMove(ISonicString * pStr, LPVOID)
{...
}ISonicImage * pImgNormal = GetSonicUI()->CreateImage();
pImgNormal->Load(BMP_NORMAL);
pImgNormal->SetColorKey(RGB(255, 0, 255));ISonicImage * pImgHover = GetSonicUI()->CreateImage();
pImgHover->Load(BMP_HOVER);
pImgHover->SetColorKey(RGB(255, 0, 255));ISonicImage * pImgClick = GetSonicUI()->CreateImage();
pImgClick->Load(BMP_CLICK);
pImgClick->SetColorKey(RGB(255, 0, 255));ISonicString * pAniButton = GetSonicUI()->CreateString();
pAniButton->Format("/a, p=%d, ph=%d, pc=%d, animation=40/",pImgNormal->GetObjectId(), pImgHover->GetObjectId(), pImgClick->GetObjectId());
pAniButton->Delegate(DELEGATE_EVENT_CLICK, NULL, NULL, OnMove);
pAniButton->TextOut(hdc, 10, 10);
"p,ph,pc"关键字代表按钮的三个状态(正常,移过,点击).每个关键字都按其显示项,指定一个ISonicImage.如果你取得一个包含三个状态的源图像,则也没有关系.
只需要按ISonicImage的相同对象ID指定"p,ph,pc",ISonicImage会完成所有操作.内部就搞了源矩剪切.
"animation=40"表示这是一个阴影按钮,即,在切换状态时显示动画.40是阴影速度,越高,速度越快.Delegate()方法给按回调转发点击事件的过程,然后,如果你点击按钮,则调用该过程.
4.制作不规则窗口
ISonicWndEffect组件用来造不规则窗口,或给窗口加动画,如平滑移动,平滑旋转或平滑拉伸等.制作不规则窗口的方法有两个:使用窗口区域或分层窗口.
首先是窗口区域方式:
...
// ISonicImage * pImg
SetWindowRgn(hWnd, pImg->CreateRgn());
第二个是使用分层窗口:
...
ISonicWndEffect * pEffect = GetSonicUI()->CeateWndEffect();
// 用α每像素附加模式
pEffect->Attach(hWnd, TRUE);
// ISonicImage * pImg
pEffect->SetShapeByImage(pImg);
5.其他组件
还有许多其他组件,如ISonicTextScrollBar和ISonicAnimation,你可用它们实现许多熟悉的UI效果,如滚动文本,平滑移动图片,旋转或平滑拉伸并很爽.
用法非常简单,可在ISonicUI.h接口文件中查找它.在此,这里说下兴趣点.
兴趣点
这里展示一些包含ASM和API勾挂技术的技巧.
1.闭包
当然,希望找到简单方法来给不同过程转发自绘按钮,以可普遍使用组件.但是函数声明中有问题.VC禁止你按普通方式按参数,传递类的成员函数.
你必须使用与类相关的成员函数指针,且显然违反"通用"原则.因此,我使用易失参数来避免该限制.
void ISonicBase::Delegate(UINT message, LPVOID pReserve, LPVOID pClass, ...)
{if(IsValid() == FALSE){return;}ISonicBaseData * pData = dynamic_cast(this);if(pData == NULL){return;}DELEGATE_PARAM pm = {0};pm.pClass = pClass;pm.pReserve = pReserve;va_list argPtr;va_start(argPtr, pClass);pm.pFunc = va_arg(argPtr, LPVOID);va_end(argPtr);pData->m_mapDelegate[message] = pm;
}
而且也无法正常回调.不用担心,只需一点ASM代码即可完成工作.
void ISonicBaseData::OnDelegate(UINT message)
{MSG_TO_DELEGATE_PARAM::iterator it = m_mapDelegate.find(message);if(it == m_mapDelegate.end()){return;}DELEGATE_PARAM &pm = it->second;if(pm.pFunc == NULL || IsBadCodePtr((FARPROC)pm.pFunc)){return;}ISonicBase * pBase = dynamic_cast(this);if(pBase == NULL){return;}LPVOID pReserve = pm.pReserve;LPVOID pClass = pm.pClass;LPVOID pFunc = pm.pFunc;__asm{push ecxpush [pReserve]push [pBase]mov ecx, [pClass]call [pFunc]pop ecx}
}
有时,这破坏了C++语法检查的安全性,因此必须确保回调函数的声明严格遵守以下规则:
void WINPAI Func(ISonicBase *, LPVOID)
否则,会导致栈崩溃或某些致命错误.
2.分层窗口
广泛使用分层窗口来实现透明窗口或不规则窗口.有两个用来显示分层窗口的API:SetLayeredWindowAttributes和UpdateLayeredWindow.
但是,尽管如MSDN所述,SetLayeredWindowAttributes内部使用UpdateLayeredWindow,但对应用开发者来说,这两个函数之间有致命的区别.
在此,只能说主要区别是使用UpdateLayeredWindow时,会丢弃WM_PAINT消息,不会显示你的所有子控件,且通用的GDIAPI可能无法正常工作,而SetLayeredWindowAttributes使用重定向机制来使一切正常运行.
似乎UpdateLayeredWindow只是一个麻烦制造者,但是如果你要创建一个每像素α窗口并按背景使用PNG来实现某些阴影效果,则只能选择UpdateLayeredWindow.
因为ISonicWndEffect只是,在现有窗柄上附加的"附件",我该如何要求引擎用户重写BeginPaint和EndPaint间的所有渲染代码?因此,我使用了API的勾挂技巧.
// ...HMODULE hMod = GetModuleHandle("User32.dll");if(hMod == NULL){return FALSE;}m_pOldBeginPaint = ReplaceFuncAndCopy(GetProcAddress(hMod, "BeginPaint"), MyBeginPaint);m_pOldEndPaint = ReplaceFuncAndCopy(GetProcAddress(hMod, "EndPaint"), MyEndPaint);HDC CSonicUI::MyBeginPaint( HWND hwnd, LPPAINTSTRUCT lpPaint )
{HDC hdc;if(m_hPaintDC){memset(lpPaint, 0, sizeof(PAINTSTRUCT));lpPaint->hdc = m_hPaintDC;GetClientRect(hwnd, &lpPaint->rcPaint);hdc = m_hPaintDC;g_UI.m_rtUpdate = lpPaint->rcPaint;}else{GetUpdateRect(hwnd, g_UI.m_rtUpdate, FALSE);__asm{push [ebp + 0ch]push [ebp + 8h]call [m_pOldBeginPaint]mov [hdc], eax}}g_UI.m_bPainting = TRUE;return hdc;
}BOOL CSonicUI::MyEndPaint( HWND hWnd, CONST PAINTSTRUCT *lpPaint )
{BOOL bRet = TRUE;// ...if(m_hPaintDC){m_hPaintDC = NULL;return TRUE;}else{__asm{push [ebp + 0ch]push [ebp + 8h]call [m_pOldEndPaint]mov [bRet], eax}}GetClientRect(hWnd, g_UI.m_rtUpdate);g_UI.m_bPainting = FALSE;return bRet;
}
这样,当我想使用(内部由UpdateLayeredWindow实现的)每像素α模式重画由ISonicWndEffect附加的窗口时,我只是向窗口发送了假WM_PAINT消息,并按WM_PAINT的字参使用memdc,无需更改渲染代码就正确渲染了.
实际上,使用此技巧带来为一些礼物.使用此引擎时,即使隐藏了窗口,也可在指定memdc上绘画所有窗口.
结论
还有许多其他技巧和技术,如按整转换浮运算,更新脏矩形机制,SSE2指令等,以优化引擎效率.
历史
更改了函数勾挂代码,以避免泄漏内存警告.修改了CSonicString::TextOut一些代码,使其可与内存dc一起使用,而无需指定窗柄.给ISonicImage添加了高斯模糊甚至模糊功能.
修复了ISonicImage中的可能导致崩溃的服务器错误.给ISonicWndEffect添加DirectTransfrom方法.给ISonicTextScrollBar添加了一些功能.
添加了ISonicSkin组件.可仅用三行代码来装饰窗口和对话框.很酷,很方便!添加了统一支持,添加了静态库输出支持.
几种类型从MFC,更改为ATL支持,以减轻引擎重量.优化了一些内核工具,如脏矩形更新机制.
为ISonicUI和ISonicString添加了接口,ISonicString中修改了"p"关键字的格式.
这是一个制作带四种状态的平铺图像的自绘按钮的示例:
ISonicString::Format("/a, p4=%d/", pImg->GetObjectId());
已丢弃原来的"ph"和"pc"关键字.见ISonicUI.h以获取更多细节.
相关文章:
2502,索界面3
原文 SonicUI,你从未见过的方便GUI引擎-源码 介绍 SonicUI是基于原生GDIAPI的GUI引擎.它提供了几个简单的UI组件来实现高效的UI效果,如自绘按钮,不规则窗口,动画,窗口中的网径和图像操作方法. 主要目的是用最少的代码来达到最佳效果. 背景 周知,UI开发一般重复用无趣.因此…...
ChatGPT提问技巧:行业热门应用提示词案例--咨询法律知识
ChatGPT除了可以协助办公,写作文案和生成短视频脚本外,和还可以做为一个法律工具,当用户面临一些法律知识盲点时,可以向ChatGPT咨询获得解答。赋予ChatGPT专家的身份,用户能够得到较为满意的解答。 1.咨询法律知识 举…...
[吾爱出品]CursorWorkshop V6.33 专业鼠标光标制作工具-简体中文汉化绿色版
CursorWorkshop V6.33 专业鼠标光标制作工具 链接:https://pan.xunlei.com/s/VOIFeq5DFB9FS56Al_mT2EfdA1?pwd7ij4# 产品概述 Axialis CursorWorkshop 是一个专业光标创作工具它在 Windows 下运行,让您轻松创建高质量的静态和动态光标适用于 Windows …...
《运维:技术的基石,服务的保障》
1. LVS(Linux Virtual Server):基于Linux内核的四层负载均衡解决方案 2. Bonding(链路聚合):物理网卡冗余与带宽叠加技术 3. RHEL(Red Hat Enterprise Linux):企业级Li…...
【C语言】自定义类型讲解
文章目录 一、前言二、结构体2.1 概念2.2 定义2.2.1 通常情况下的定义2.2.2 匿名结构体 2.3 结构体的自引用和嵌套2.4 结构体变量的定义与初始化2.5 结构体的内存对齐2.6 结构体传参2.7 结构体实现位段 三、枚举3.1 概念3.2 定义3.3 枚举的优点3.3.1 提高代码的可读性3.3.2 防止…...
Day25 洛谷 提高- 1007
零基础洛谷刷题记录 Day01 2024.11.18 Day02 2024.11.25 Day03 2024.11.26 Day04 2024.11.28 Day05 2024.11.29 Day06 2024 12.02 Day07 2024.12.03 Day08 2024 12 05 Day09 2024.12.07 Day10 2024.12.09 Day11 2024.12.10 Day12 2024.12.12 Day13 2024.12.16 Day14 2024.12.1…...
LabVIEW涡轮诊断系统
一、项目背景与行业痛点 涡轮机械是发电厂、航空发动机、石油化工等领域的核心动力设备,其运行状态直接关系到生产安全与经济效益。据统计,涡轮故障导致的非计划停机可造成每小时数十万元的经济损失,且突发故障可能引发严重安全事故。传统人…...
GGML、GGUF、GPTQ 都是啥?
GGML、GGUF和GPTQ是三种与大型语言模型(LLM)量化和优化相关的技术和格式。它们各自有不同的特点和应用场景,下面将详细解释: 1. GGML(GPT-Generated Model Language) 定义:GGML是一种专为机器学习设计的张量库,由Georgi Gerganov创建。它最初的目标是通过单一文件格式…...
Kafka 使用说明(kafka官方文档中文)
文章来源:kafka -- 南京筱麦软件有限公司 第 1 步:获取 KAFKA 下载最新的 Kafka 版本并提取它: $ tar -xzf kafka_{{scalaVersion}}-{{fullDotVersion}}.tgz $ cd kafka_{{scalaVersion}}-{{fullDotVersion}} 第 2 步:启动 KAFKA 环境 注意:您的本地环境必须安装 Java 8+。…...
Kubernetes 中 BGP 与二层网络的较量:究竟孰轻孰重?
如果你曾搭建过Kubernetes集群,就会知道网络配置是一个很容易让人深陷其中的领域。在负载均衡器、服务通告和IP管理之间,你要同时应对许多变动的因素。对于许多配置而言,使用二层(L2)网络就完全能满足需求。但边界网关…...
大模型综述一镜到底(全文八万字) ——《Large Language Models: A Survey》
论文链接:https://arxiv.org/abs/2402.06196 摘要:自2022年11月ChatGPT发布以来,大语言模型(LLMs)因其在广泛的自然语言任务上的强大性能而备受关注。正如缩放定律所预测的那样,大语言模型通过在大量文本数…...
物理群晖SA6400核显直通win10虚拟机(VMM)
写在前面:请先确保你的核显驱动支持开启SR-IOV 确保你的BIOS开启了以下选项: VT-D VMX IOMMU Above 4G ResizeBAR 自行通过以下命令确认支持情况: dmesg | grep -i iommudmesg | grep DMAR分配1个虚拟vGPU:echo 1 | sudo tee /sy…...
【python】tkinter实现音乐播放器(源码+音频文件)【独一无二】
👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 【python】tkinter实现音乐播放器(源码…...
ESP32开发工具介绍:Thonny——初学者的MicroPython利器
文章目录 引言什么是 Thonny?为什么选择 Thonny 开发 ESP32?1. **MicroPython 的天然支持**2. **极简的配置流程**3. **适合快速原型开发**如何用 Thonny 开发 ESP32?步骤 1:准备工作步骤 2:烧录 MicroPython 固件步骤 3:在 Thonny 中连接 ESP32步骤 4:编写并运行代码Th…...
进程的环境变量
export MUDUO_LOG_DEBUG1 ./testif (::getenv("MUDUO_LOG_TRACE"))return true;有时在程序运行前,我们希望设置环境变量。此处::表示全局命名空间。 在类 Unix 系统(如 Linux、macOS)中,环境变量并不直接存储在堆、栈或…...
Qwen2.5-Max:AI技术的新里程碑
随着人工智能(AI)技术的不断进步,全球各大科技公司都在竞相推出更强大的语言模型。近日,阿里巴巴发布了其最新的超大规模混合专家模型(MoE)——Qwen2.5-Max,这一成果不仅在多个基准测试中超越了…...
MyBatis-Plus速成指南:常用注解
Table Name: 概述: MyBatis-Plus 在确定操作的表时,由 BaseMapper的泛型决定,即实体类决定,且默认操作的表名和实体类的类名一致 问题: 如果实体类类型的类名和要操作表的表名不一致会出现什么问题?(把 us…...
Vue.js组件开发-Vue实现上传word模版打印设置自定义样式和布局
要使用 Vue 实现上传 Word 模板、打印并设置自定义样式和布局,可以借助一些工具和库来完成这个任务。 实现步骤 创建 Vue 项目:使用 Vue CLI 创建一个新的 Vue 项目。安装依赖:安装 docx-templates 库来处理 Word 模板,file-sav…...
Linux 压缩打包
Linux压缩打包 文章目录 Linux压缩打包压缩的意义和原理压缩的意义压缩的原理压缩与解压缩的好处 压缩打包命令.zipzip 命令用法unzip 的用法 .gzgzip 的用法gunzip 的用法 .bz2bzip2 的用法bunzip2 的用法 .xzxz 命令用法 tar 04-Linux压缩打包课后习题 压缩的意义和原理 压缩…...
RabbitMQ深度探索:前置知识
消息中间件: 消息中间件基于队列模式实现异步 / 同步传输数据作用:可以实现支撑高并发、异步解耦、流量削峰、降低耦合 传统的 HTTP 请求存在的缺点: HTTP 请求基于响应的模型,在高并发的情况下,客户端发送大量的请求…...
29.日常算法
1. 验证回文串 II 题目来源 给定一个非空字符串 s,请判断如果 最多 从字符串中删除一个字符能否得到一个回文字符串。 示例 1: 输入: s “aba” 输出: true 示例 2: 输入: s “abca” 输出: true 解释: 可以删除 “c” 字符 或者 “b” …...
智慧校园平台:构建现代化教育体系的技术支撑
在当今信息技术飞速发展的时代,智慧校园平台成为了现代教育领域中的重要组成部分。智慧校园平台不仅能够提升学校的管理水平,还能提供更为个性化和高效的教学服务,从而促进学生的全面发展。 数据分析是智慧校园平台的重要组成部分。通过对学生…...
【单层神经网络】基于MXNet的线性回归实现(底层实现)
写在前面 刚开始先从普通的寻优算法开始,熟悉一下学习训练过程下面将使用梯度下降法寻优,但这大概只能是局部最优,它并不是一个十分优秀的寻优算法 整体流程 生成训练数据集(实际工程中,需要从实际对象身上采集数据…...
20250204将Ubuntu22.04的默认Dash的shell脚本更换为bash
20250204将Ubuntu22.04的默认Dash的shell脚本更换为bash 2025/2/4 23:45 百度:dash bash https://blog.csdn.net/2201_75772333/article/details/136955776 【Linux基础】dash和bash简介 Dash(Debian Almquist Shell)和 Bash(Bou…...
Golang 并发机制-3:通道(channels)机制详解
并发编程是一种创建性能优化且响应迅速的软件的强大方法。Golang(也称为 Go)通过通道(channels)这一特性,能够可靠且优雅地实现并发通信。本文将揭示通道的概念,解释其在并发编程中的作用,并提供…...
Python处理数据库:MySQL与SQLite详解
Python处理数据库:MySQL与SQLite详解 在数据处理和存储方面,数据库扮演着至关重要的角色。Python提供了多种与数据库交互的方式,其中pymysql库用于连接和操作MySQL数据库,而SQLite则是一种轻量级的嵌入式数据库,Pytho…...
可视化大屏在石油方面的应用。
可视化大屏通过整合石油工业全链条数据,构建数字孪生驱动的运营监控体系,显著提升油气勘探、开采、储运及炼化的管理效能。其技术架构依托工业物联网(IIoT)实时采集钻井参数、管道压力、储罐液位等数据,通过OPC UA协议…...
【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】从计算机基础到HTML开发:Web开发的第一步
会议官网:www.acvra.org 简介 2025年计算机视觉研究进展与应用(ACVRA 2025)将于2025年2月28-3月2日在中国广州召开,将汇聚世界各地的顶尖学者、研究人员和行业专家,聚焦计算机视觉领域的最新研究动态与应用成就。本次…...
【 AI agents】letta:2024年代理堆栈演进(中英文翻译)
The AI agents stack AI 代理堆栈 November 14, 2024 11月 14, 2024原文: The AI agents stack官方教程教程学习笔记: 【memgpt】letta 课程1/2:从头实现一个自我编辑、记忆和多步骤推理的代理Understanding the AI agents landscape 了解 AI 代理环境 Although we see a …...
Axure PR 9 旋转效果 设计交互
大家好,我是大明同学。 这期内容,我们将学习Axure中的旋转效果设计与交互技巧。 旋转 创建旋转效果所需的元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.在元件库中拖出一个按钮元件。 创建交互 创建按钮交互状态 1.选中按钮元件…...
