2502,索界面3

原文

SonicUI,你从未见过的方便GUI引擎-源码

介绍

SonicUI是基于原生GDIAPIGUI引擎.它提供了几个简单的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.其他组件

还有许多其他组件,如ISonicTextScrollBarISonicAnimation,你可用它们实现许多熟悉的UI效果,如滚动文本,平滑移动图片,旋转或平滑拉伸并很爽.

用法非常简单,可在ISonicUI.h接口文件中查找它.在此,这里说下兴趣点.

兴趣点

这里展示一些包含ASMAPI勾挂技术的技巧.

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 ecx
        push [pReserve]
        push [pBase]
        mov ecx, [pClass]
        call [pFunc]
        pop ecx
    }
}

有时,这破坏了C++语法检查的安全性,因此必须确保回调函数的声明严格遵守以下规则:

void WINPAI Func(ISonicBase *, LPVOID)

否则,会导致栈崩溃某些致命错误.

2.分层窗口

广泛使用分层窗口来实现透明窗口或不规则窗口.有两个用来显示分层窗口API:SetLayeredWindowAttributesUpdateLayeredWindow.

但是,尽管如MSDN所述,SetLayeredWindowAttributes内部使用UpdateLayeredWindow,但对应用开发者来说,这两个函数之间有致命的区别.

在此,只能说主要区别是使用UpdateLayeredWindow时,会丢弃WM_PAINT消息,不会显示你的所有子控件,且通用的GDIAPI可能无法正常工作,而SetLayeredWindowAttributes使用重定向机制来使一切正常运行.

似乎UpdateLayeredWindow只是一个麻烦制造者,但是如果你要创建一个每像素α窗口并按背景使用PNG实现某些阴影效果,则只能选择UpdateLayeredWindow.

因为ISonicWndEffect只是,在现有窗柄上附加的"附件",我该如何要求引擎用户重写BeginPaintEndPaint间的所有渲染代码?因此,我使用了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支持,以减轻引擎重量.优化了一些内核工具,如脏矩形更新机制.
ISonicUIISonicString添加了接口,ISonicString中修改了"p"关键字的格式.

这是一个制作带四种状态平铺图像的自绘按钮示例:

ISonicString::Format("/a, p4=%d/", pImg->GetObjectId());

丢弃原来的"ph""pc"关键字.见ISonicUI.h获取更多细节.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/964830.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【OpenCV实战】基于 OpenCV 的多尺度与模板匹配目标跟踪设计与实现

文章目录 基于 OpenCV 的模板匹配目标跟踪设计与实现1. 摘要2. 系统概述3. 系统原理3.1 模板匹配的基本原理3.2 多尺度匹配 4. 逻辑流程4.1 系统初始化4.2 主循环4.3 逻辑流程图 5. 关键代码解析5.1 鼠标回调函数5.2 多尺度模板匹配 6. 系统优势与不足6.1 优势6.2 不足 7. 总结…

【系统架构设计师】操作系统 ② ( 存储管理 | 页式存储 | 逻辑地址 与 物理地址 | 页表结构 | 物理内存淘汰机制 )

文章目录 一、页式存储1、CPU 调用数据2、内存存储数据弊端3、分页存储4、逻辑地址 和 物理地址 的结构5、逻辑地址 和 物理地址 的结构 示例6、页式存储 优缺点 二、逻辑地址 与 物理地址1、逻辑地址2、物理地址3、逻辑地址 与 物理地址 区别4、逻辑地址 与 物理地址 的转换 三…

AMD数据中心业务创纪录,Instinct MI355X提前发布

没有人能预料到生成式人工智能(GenAI)会如此迅速地推动英伟达的扩张,也没有人能预料到英伟达的崛起和英特尔的衰落会如此之快。对于那些相信“第二名可以更努力并取得成功”的人来说,AMD的崛起无疑证明了这一点。然而,…

C++ 中的 `string` 类型:全面解析与高效操作

C 中的 string 类型:全面解析与高效操作 在 C 中,string 类型是对字符数组的高级封装,它提供了大量内置函数,使得字符串的处理变得更为简便和高效。与 C 风格的字符数组不同,string 类型不仅自动管理内存,…

穷举vs暴搜vs深搜vs回溯vs剪枝系列一>黄金矿工

目录 决策树&#xff1a;代码设计代码&#xff1a; 决策树&#xff1a; 代码设计 代码&#xff1a; class Solution {boolean[][] vis;int ret,m,n;public int getMaximumGold(int[][] grid) {m grid.length;n grid[0].length;vis new boolean[m][n]; for(int i 0; i <…

DeepSeek 的含金量还在上升

大家好啊&#xff0c;我是董董灿。 最近 DeepSeek 越来越火了。 网上有很多针对 DeepSeek 的推理测评&#xff0c;除此之外&#xff0c;也有很多人从技术的角度来探讨 DeepSeek 带给行业的影响。 比如今天就看到了一篇文章&#xff0c;探讨 DeepSeek 在使用 GPU 进行模型训练…

使用SpringBoot发送邮件|解决了部署时连接超时的bug|网易163|2025

使用SpringBoot发送邮件 文章目录 使用SpringBoot发送邮件1. 获取网易邮箱服务的授权码2. 初始化项目maven部分web部分 3. 发送邮件填写配置EmailSendService [已解决]部署时连接超时附&#xff1a;Docker脚本Dockerfile创建镜像启动容器 1. 获取网易邮箱服务的授权码 温馨提示…

两种文件类型(pdf/图片)打印A4半张纸方法

环境:windows10、Adobe Reader XI v11.0.23 Pdf: 1.把内容由横排变为纵排&#xff1a; 2.点击打印按钮&#xff1a; 3.选择打印页范围和多页&#xff1a; 4.内容打印在纸张上部 图片&#xff1a; 1.右键图片点击打印&#xff1a; 2.选择打印类型&#xff1a; 3.打印配置&am…

C语言打印输出星号图形(三角形、菱形、漏斗)

文章目录 1. 介绍2. 案例分析3. 漏斗型4. 直角三角形4.1 左上直角三角形4.2 右上直角三角形4.3 左下直角三角形4.4 右下直角三角形 5. 等腰三角形5.1 正等腰三角形5.2 倒等腰三角形 6. 平行四边形6.1 纵向左下平行四边形6.2 纵向左上平行四边形6.3 横向左上平行四边形6.4 横向左…

刷题记录 动态规划-7: 63. 不同路径 II

题目&#xff1a;63. 不同路径 II 难度&#xff1a;中等 给定一个 m x n 的整数数组 grid。一个机器人初始位于 左上角&#xff08;即 grid[0][0]&#xff09;。机器人尝试移动到 右下角&#xff08;即 grid[m - 1][n - 1]&#xff09;。机器人每次只能向下或者向右移动一步。…

springboot+vue+uniapp的校园二手交易小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

Python 自学秘籍:开启编程之旅,人生苦短,我用python。

从2009年&#xff0c;用了几次python后就放弃了&#xff0c;一直用的php&#xff0c;现在人工智能时代&#xff0c;完全没php什么事情。必须搞python了&#xff0c;虽然已经40多岁了。死磕python了。让滔滔陪着你一起学python 吧。 开启新世界 在当今人工智能化的时代&#xff…

react的antd表格自定义图标

将原版的加号换成箭头 自定义图标 安装图标包&#xff1a; npm install --save ant-design/icons 引入&#xff1a; import { RightOutlined, DownOutlined } from ant-design/icons; 参数是一个函数 <Table columns{columns} dataSource{data} indentSize{20}expandIc…

chrome浏览器chromedriver下载

chromedriver 下载地址 https://googlechromelabs.github.io/chrome-for-testing/ 上面的链接有和当前发布的chrome浏览器版本相近的chromedriver 实际使用感受 chrome浏览器会自动更新&#xff0c;可以去下载最新的chromedriver使用&#xff0c;自动化中使用新的chromedr…

Vim的基础命令

移动光标 H(左) J(上) K(下) L(右) $ 表示移动到光标所在行的行尾&#xff0c; ^ 表示移动到光标所在行的行首的第一个非空白字符。 0 表示移动到光标所在行的行首。 W 光标向前跳转一个单词 w光标向前跳转一个单词 B光标向后跳转一个单词 b光标向后跳转一个单词 G 移动光标到…

算法与数据结构(括号匹配问题)

思路 从题干可以看出&#xff0c;只要给出的括号对应关系正确&#xff0c;那么就可以返回true,否则返回false。这个题可以使用栈来解决 解题过程 首先从第一个字符开始遍历&#xff0c;如果是括号的左边&#xff08;‘&#xff08;‘&#xff0c;’[‘&#xff0c;’}‘&…

deepseek、qwen等多种模型本地化部署

想要在本地部署deepseek、qwen等模型其实很简单,快跟着小编一起部署吧 1 环境搭建 1.1下载安装环境 首先我们需要搭建一个环境ollama,下载地址如下 :Ollama 点击Download 根据自己电脑的系统选择对应版本下载即可 1.2 安装环境(window为例) 可以直接点击安装包进行安…

(2025,LLM,下一 token 预测,扩散微调,L2D,推理增强,可扩展计算)从大语言模型到扩散微调

Large Language Models to Diffusion Finetuning 目录 1. 概述 2. 研究背景 3. 方法 3.1 用于 LM 微调的高斯扩散 3.2 架构 4. 主要实验结果 5. 结论 1. 概述 本文提出了一种新的微调方法——LM to Diffusion (L2D)&#xff0c;旨在赋予预训练的大语言模型&#xff08;…

一款wordpress AI免费插件自动内容生成+前端AI交互+文章批量采集

一款wordpressAI自动内容生成前端AI会话窗口交互文章批量采集免费插件 1. SEO优化文章生成 关键词驱动的内容生成&#xff1a;用户可以输入关键词或长尾关键词&#xff0c;插件会根据这些关键词生成高质量的SEO优化文章。文章结构清晰&#xff0c;语言自然流畅&#xff0c;符合…

2024年12月 Scratch 图形化(一级)真题解析 中国电子学会全国青少年软件编程等级考试

202412 Scratch 图形化&#xff08;一级&#xff09;真题解析 中国电子学会全国青少年软件编程等级考试 一、单选题(共25题&#xff0c;共50分) 第 1 题 点击下列哪个按钮&#xff0c;可以将红框处的程序放大&#xff1f;&#xff08; &#xff09; A. B. C. D. 标…