Win32 透明效果相关基础知识

Layered Windows 分层窗口。这是Windows2000开始引入的概念,重新定义了窗口的Hit Testing方法,以前都是把窗口按rectangle的方式裁剪,而把窗口加上WS_EX_LAYERED的Style后就可以根据窗口的形状和像素 值进行Hit Testing,这样我们的不规则窗口就变成了真正意义上的独立窗口,而不是传统的被一个不可见的矩形窗口所包含。

分层窗口重绘方式、透明效果产生

创建不规则窗口的三种方式

  1. 通过区域相关API设置窗口的区域SetWindowRgn;;
  2. 通过 SetLayeredWindowAttributes来指定特殊的透明颜色,让背景图的部分位置全透从而实现窗口的“不规则”;
  3. 通过 UpdateLayeredWindow来指定特殊颜色透明或者根据图片的ALPHA值来设置窗口全透。

  • UpdateLayeredWindow():直接更新一个分层的窗口的位置,大小,形状,内容和半透明度。优点是一劳永逸,不需要在窗口函数中响应各种重绘事件。

  • 先用SetLayeredWindowAttributes()函数设置关于窗口透明度的信息,然后用传统方式,在窗口函数中响应各种重绘事件。

注:分层窗口上的控件会随着窗口一同变透明

解决方案:准备两个窗口,窗口A和窗口B,窗口A作为显示窗口,也就是异形窗口,而窗口B作为逻辑窗口,然后让这两个窗口 重叠在一块,也可以说是在窗口B上创建了窗口A,然后通过UpdateLayeredWindow对窗口A实现异形,因为窗口A在窗口B上,那么势必会遮 盖住窗口B的控件,然后我们就要对窗口A通过SetWindowRgn进行裁剪,通过镂空出控件的位置从而达到显示出控件。

不规则区域重绘

SetWindowRgn() 函数:用于设置了一个窗口的区域.只有被包含在这个区域内的地方才会被重绘,而不包含在区域内的其他区域系统将不会显示.

我们的不规则形状由此而来。这个函数和它的朋友们十分强大,不仅可以定义独立的基本形状的区 域,还可以通过运算(CombineRgn:可对两个区域进行交集、拷贝、相减、异或运算)来组合已有区域从而产生新的区域。

异形窗口效果示例

  • 简单效果

  • 复杂效果

DUILIB库 对透明效果的实现

DUILIB中,窗体透明度设置方法

1.设置window标签属性bktrans="true" alpha="200" alpha的值为0-255。这种设置是全体窗体透明度,所有控件都将变透明。

2.如果想单纯设置背景透明度控件不透明度,可以制作半透明的背景图片,设置window标签的bktrans="true",并且不设置alpha属性,此时背景透明,其它控件不透明。

3.单独设置某个控件的透明度,可以使用图片的fade属性,或者mask属性。fade表示设置图片透明度,取值0-255。mask为设置透明的颜色。

DuiLib.CRenderEngine.LoadImage 对控件指定颜色mask的透明:在加载图片资源位图时,对颜色为mask的像素进行置零,绘制时这些像素的位置将被透明
    1. if( *(DWORD*)(&pDest[i*4]) == mask ) {
    1. pDest[i*4] = (BYTE)0;
    1. pDest[i*4 + 1] = (BYTE)0;
    1. pDest[i*4 + 2] = (BYTE)0;
    1. pDest[i*4 + 3] = (BYTE)0;
    1. bAlphaChannel = true;
    1. }
图片资源文件只加载一次,加载成功后缓存于内存中。
    1. // data : 加载的图片资源
    1. if( !data ) return NULL;
    1. if( type != NULL ) data->sResType = type;
    1. data->dwMask = mask;
    1. if( !m_mImageHash.Insert(bitmap, data) ) {// 缓存提速
    1. ::DeleteObject(data->hBitmap);
    1. delete data;
    1. data = NULL;
    1. }
DuiLib.CRenderEngine.DrawImage 渲染引擎:透明效果渲染过程
    1. static LPALPHABLEND lpAlphaBlend = (LPALPHABLEND) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "AlphaBlend");
    1. .... ....
    1. if( lpAlphaBlend && (alphaChannel || uFade < 255) ) {
    1. // uFade:设置背景图片透明度; alphaChannel:启用指定颜色(Mask)透明
    1. BLENDFUNCTION bf = { AC_SRC_OVER, 0, uFade, AC_SRC_ALPHA };
    1. if( lpAlphaBlend == NULL ) lpAlphaBlend = AlphaBitBlt;
    1. .... ....
    1. // Alpha混合贴图
    1. lpAlphaBlend(hDC, lDestLeft, rcDest.top, lDestRight - lDestLeft, rcDest.bottom,
    1. hCloneDC, rcBmpPart.left + rcCorners.left, rcBmpPart.top + rcCorners.top, \
    1. lDrawWidth, rcBmpPart.bottom - rcBmpPart.top - rcCorners.top - rcCorners.bottom, bf);
DuiLib.CControlUI.DoPaint 控件重绘过程
    1. void CControlUI::DoPaint(HDC hDC, const RECT& rcPaint)
    1. {
    1. if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;
    1. // 绘制循序:背景颜色->背景图->状态图->文本->边框
    1. if( m_cxyBorderRound.cx > 0 || m_cxyBorderRound.cy > 0 ) {
    1. CRenderClip roundClip;
    1. // CRenderClip内部以SetWindowRgn()函数对绘制区域进行控制
    1. CRenderClip::GenerateRoundClip(hDC, m_rcPaint, m_rcItem, m_cxyBorderRound.cx, m_cxyBorderRound.cy, roundClip);
    1. PaintBkColor(hDC);
    1. PaintBkImage(hDC);// 调用渲染引擎绘制背景图片
    1. PaintStatusImage(hDC);
    1. PaintText(hDC);
    1. PaintBorder(hDC);
    1. }
    1. else {
    1. PaintBkColor(hDC);
    1. PaintBkImage(hDC);
    1. PaintStatusImage(hDC);
    1. PaintText(hDC);
    1. PaintBorder(hDC);
    1. }
    1. }
DuiLib.CPaintManagerUI.MessageHandler 各控件绘制完成后,整体粘贴到主窗口进行显示
    1. BLENDFUNCTION blendPixelFunction = {AC_SRC_OVER, 0, m_nOpacity, AC_SRC_ALPHA};
    1. BOOL bRet = ::UpdateLayeredWindow(m_hWndPaint, NULL, &pt, &szWindow, m_hDcOffscreen, &ptSrc, 0, &blendPixelFunction, ULW_ALPHA);
备课神器中,封面截图过程中遮罩效果的实现

目标效果

A为用户鼠标选取部分,无遮罩;

B为未选取部分,全部阴影遮罩(示例图未完善,遮罩未覆盖整个图片)

B为Window窗口,设置bktrans=“true”从而实现透明;

通过SetWindowRgn裁剪,使B不绘制A区域,从而实现用户选取效果

存在问题:A区域无法响应鼠标消息,用户拖动操作无法响应!

改进方案

  1. A为用户鼠标选取部分,无遮罩;

  2. B为未选取部分,全部阴影遮罩(示例图未完善,未覆盖整个图片)

  3. C为逻辑窗口,覆盖整个图片(示例图未完善,未覆盖整个图片),负责用户操作响应

C为Window窗口,设置bktrans=“true”,背景图要求无限接近全透明,以消除到A区域的影响。

B为控件,通过背景图产生遮罩效果

B通过SetWindowRgn裁剪,使B不绘制A区域,从而实现用户选取效果

最终效果

专题:DUILIB Win32 透明效果的更多相关文章

  1. Android课程---Android设置透明效果的三种方法(转)

    1.使用Android系统自带的透明效果资源 <Button  android:background="@android:color/transparent"/>   ...

  2. Unity3D ShaderLab 使用alpha参数创建透明效果

    Unity3D ShaderLab 使用alpha参数创建透明效果 其实Unity为了方便我们的工作,为我们内置了很多参数.比如马上用到的透明功能. 准备场景新建Shader Material ,一张 ...

  3. 用CSS实现Firefox 和IE 都支持的Alpha透明效果

    有的时候,为了实现一些特殊效果,需要将页面元素变透明,本文介绍的就是用 CSS 实现 Firefox 和 IE 都支持的 Alpha 透明效果.CSS: filter:alpha(opacity=50 ...

  4. 一些有用的 Emacs 配置(窗口快速切换、一键透明效果、任意位置删除整行等)

    本篇文章记录的是一些有用的 Emacs 配置,有些是自己原创,有些是借鉴别人(能记起来出处的我放了链接). 规定:C 代表 Ctrl,M 代表 Alt. 1.设置一次跳跃 n 行的快捷键 按 C-M- ...

  5. Css实现透明效果,兼容IE8

    Css实现透明效果,兼容IE8 >>>>>>>>>>>>>>>>>>>>> ...

  6. CentOS下Qt窗口透明效果失效,成黑色背景的问题

    一.问题 Linux系统下Qt窗口的透明效果成了黑色,但同样的代码在windows机子上有透明效果,主要是修改系统的配置,仅在centos6.3及其以上版本实验过.其他系统可以相应配置. 二.问题运行 ...

  7. QT下的几种透明效果(三种方法:调色板,透明度属性,自绘)

    1.窗口整体透明,但是窗体上的控件不透明.    通过设置窗体的背景色来实现,将背景色设置为全透.  QPalette pal = palette();  pal.setColor(QPalette: ...

  8. android:android:background="#00000000",透明效果

    ImageButton中设置 android:background="#00000000",可以达到透明效果 具体的源码 管理-->文件中的 viewpager0829.ra ...

  9. Windows窗体透明效果

    虚拟机里的win7也想实现透明效果, 使用vitrite这个免费软件就可以了.

随机推荐

  1. linux:基本命令

    1.显示日期与时间:date 显示2009/08/17形式的格式:date +%Y/%m/%d 显示17:04时间格式:date +%H/%M 2.显示日历:cal 常用的命令:cal 2009:ca ...

  2. C++设计模式——抽象工厂模式

    问题描述 之前讲到了C++设计模式——工厂方法模式,我们可能会想到,后期产品会越来越多了,建立的工厂也会越来越多,工厂进行了增长,工厂变的凌乱而难于管理:由于工厂方法模式创建的对象都是继承于Produ ...

  3. SecureCRT 选择Courier New等其他字体.

    http://justwinit.cn/post/5813/ 如何解决SecureCRT无法选择Courier New等其他字体最终解决办法:到C:\Windows\Fonts目录下,找到Courie ...

  4. android:在ViewPager中使用Button

    最近在项目用用到ViewPager ,其中页面包含有Button,因为之前也有使用个ViewPager ,所以这个也照搬之前的方式,测试后发现点击button无法执行,这个button是在第一页面的默 ...

  5. 条形码--JsBarcode

    介绍一下在GitHub生成条形码的js插件→JsBarcode 支持的条形码: 条码支持的有: CODE128  CODE128 (自动模式切换)  CODE128 A/B/C (强制模式)EAN  ...

  6. cygwin 运行窗口程序

    首先, 默认安装的cygwin是不能运行窗口程序的 比如,一段python窗口程序: import * from tkinter Tk() mainloop() 如果使用命令行: python3 py ...

  7. 开源OSS.Social项目进阶介绍和使用展示

    在开源OSS.Social微信项目解析的随笔中,我简单给大家分享了进行中微信项目的概要设计,没有全局介绍,没有详细讲解,也没有如何使用,很多朋友估计匆匆一瞥就忙着抢开工红包去了.本着不能马虎的态度,这 ...

  8. [html5] 学习笔记-Canvas标签的使用

    Canvas通过JavaScript来绘制2D图形.Canvas是逐像素渲染的.在Canvas中,一旦图形被绘制完成,它就不会继续得到浏览器的关注.如果其位置发生变化,那么整个场景也需要重新绘制,包括 ...

  9. VS Code C# 插件离线版 1.6.2

    VS Code C# 插件离线版,目前最新稳定版为:1.6.2 . 由于在扩展中下载C#插件总是缓慢,或者容易出现错误,特制作离线版本共享出来. 本离线版本为Windows版本,其他系统请在扩展中下载 ...

  10. SQL Server 安装报错找不到vc_red.msi

    问题描述: 今天给 WIN 7 SP1 操作系统安装 SQL Server 2014 ,报错找不到vc_red.msi   (图片来源网络,请忽略2012字样..)   问题解决: 1.由于安装程序提 ...