前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >minigui/mgncs:自定义渲染器(renderer)实现透明背景按钮(transparent button)

minigui/mgncs:自定义渲染器(renderer)实现透明背景按钮(transparent button)

作者头像
10km
发布2019-05-25 21:00:36
1K0
发布2019-05-25 21:00:36
举报
文章被收录于专栏:10km的专栏10km的专栏

版权声明:本文为博主原创文章,转载请注明源地址。 https://cloud.tencent.com/developer/article/1433487

一般来说,对于mStatic,mImage这样的控件,只要设置了透明属性(transparent=true),就可以实现背景透明,但对于mButton按钮却不行,即使设置了透明属性,也不能实现透明背景。

miniStudio中对按钮设置透明属性示例:

这是为什么呢?通过跟踪minigui/mgncs的代码发现了原因:

以下是libmgncs-1.2.0/src/renderer/flat/flat_boxpieces.c中,按钮类(mButtonBoxPiece)渲染器的paint处理函数(flat风格)的代码:

代码语言:javascript
复制
// button box
static void flat_buttonbox_paint(mButtonBoxPiece *self, HDC hdc, mWidget * owner, DWORD add_data)
{
    RECT rc;

    if(!_c(self)->getRect(self, &rc))
        return ;

    flat_draw_3dbox(hdc, &rc, NCSRF_FILL, add_data&NCS_PIECE_PAINT_STATE_MASK,
            NCS_PIECE_PAINT_GET_CHECK(add_data), owner);
}

从这个代码可以看出,每次重绘窗口区域时,不论是否有设置透明属性,都会先调用flat_draw_3dbox函数填充背景。

其他风格的渲染器处理mButtonBoxPiece的逻辑也是一样的(classic,fashion,skin,flat)

知道了原因,解决问题的方案就有了

解决方案1

修改libmgncs源码:

还以上面的flat_buttonbox_paint函数为例,在函数开始添加一行代码判断透明属性是否设置就可以了。

代码语言:javascript
复制
////////////////////////////////////////////
// button box
static void flat_buttonbox_paint(mButtonBoxPiece *self, HDC hdc, mWidget * owner, DWORD add_data)
{
    /* 如果有透明直接返回 */
    if(GetWindowExStyle(owner->hwnd) & WS_EX_TRANSPARENT)return;
    RECT rc;

    if(!_c(self)->getRect(self, &rc))
        return ;

    flat_draw_3dbox(hdc, &rc, NCSRF_FILL, add_data&NCS_PIECE_PAINT_STATE_MASK,
            NCS_PIECE_PAINT_GET_CHECK(add_data), owner);
}

上面这样修改带来的效果就是按钮边框也没有了。如果你要背景透明但还希望画上按钮边框,修改如下:

代码语言:javascript
复制
static void flat_buttonbox_paint(mButtonBoxPiece *self, HDC hdc, mWidget * owner, DWORD add_data)
{
    // 根据透明背景属性来决定flat_draw_3dbox函数的flag参数
    int flag = GetWindowExStyle(owner->hwnd) & WS_EX_TRANSPARENT ? 0 : NCSRF_FILL;
    RECT rc;

    if(!_c(self)->getRect(self, &rc))
        return ;

    flat_draw_3dbox(hdc, &rc, flag, add_data&NCS_PIECE_PAINT_STATE_MASK,
            NCS_PIECE_PAINT_GET_CHECK(add_data), owner);
}

解决方案2

如果你不想修改源码,可以在外部自己为mButtonBoxPiece写个渲染器函数,然后调用ncsRegisterCtrlRDRs替换掉flat_buttonbox_paint函数就可以了:

代码语言:javascript
复制
#include <minigui/common.h>
#include <minigui/minigui.h>
#include <minigui/gdi.h>
#include <minigui/window.h>
#include <minigui/fixedmath.h>

#include <mgncs/mgncs.h>
// 自定义的mButtonBoxPiece 渲染器函数,do nothing
static void transparent_buttonbox_paint(mButtonBoxPiece *self, HDC hdc, mWidget * owner, DWORD add_data)
{
}

//init boxpiece
void transparent_init_boxpiece_renderer(void)
{
    NCS_RDR_ENTRY entries [] = {
        {Class(mButtonBoxPiece).typeName, (mWidgetRenderer*)(void*)transparent_buttonbox_paint},
    };
    // 注册控件的渲染器函数,修改flat风格的button渲染器函数,
    // 可以用这个函数同时替换其他风格(`classic`,`fashion`,`skin`,`flat`)的对应函数
    ncsRegisterCtrlRDRs("flat",
        entries,
        sizeof(entries)/sizeof(NCS_RDR_ENTRY));
    ncsRegisterCtrlRDRs("classic",
        entries,
        sizeof(entries)/sizeof(NCS_RDR_ENTRY));
    ncsRegisterCtrlRDRs("fashion",
        entries,
        sizeof(entries)/sizeof(NCS_RDR_ENTRY));
    ncsRegisterCtrlRDRs("skin",
        entries,
        sizeof(entries)/sizeof(NCS_RDR_ENTRY));
}

注意要在应用程序启动前调用transparent_init_boxpiece_renderer函数完成transparent_buttonbox_paint的注册。

同样,如果你希望背景透明的同时保留按钮边框。上面transparent_buttonbox_paint要这样写:

代码语言:javascript
复制
// 声明外部调用函数
void flat_draw_3dbox(HDC hdc, const RECT *rc, int flag ,int state, int check_state, mWidget *owner);

static void transparent_buttonbox_paint(mButtonBoxPiece *self, HDC hdc, mWidget * owner, DWORD add_data)
{
    int flag = GetWindowExStyle(owner->hwnd) & WS_EX_TRANSPARENT ? 0 : NCSRF_FILL;
    RECT rc;

    if(!_c(self)->getRect(self, &rc))
        return ;

    flat_draw_3dbox(hdc, &rc, flag, add_data&NCS_PIECE_PAINT_STATE_MASK,
            NCS_PIECE_PAINT_GET_CHECK(add_data), owner);
}

有边框的背景透明按钮和无边框的透明背景按钮的显示效果对比:

注意:修改渲染器(renderer)对所有同类型的控件都有效

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年08月30日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 解决方案1
  • 解决方案2
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档