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 ) {
  2. pDest[i*4] = (BYTE)0;
  3. pDest[i*4 + 1] = (BYTE)0;
  4. pDest[i*4 + 2] = (BYTE)0;
  5. pDest[i*4 + 3] = (BYTE)0;
  6. bAlphaChannel = true;
  7. }
图片资源文件只加载一次,加载成功后缓存于内存中。
  1. // data : 加载的图片资源
  2. if( !data ) return NULL;
  3. if( type != NULL ) data->sResType = type;
  4. data->dwMask = mask;
  5. if( !m_mImageHash.Insert(bitmap, data) ) {// 缓存提速
  6. ::DeleteObject(data->hBitmap);
  7. delete data;
  8. data = NULL;
  9. }
DuiLib.CRenderEngine.DrawImage 渲染引擎:透明效果渲染过程
  1. static LPALPHABLEND lpAlphaBlend = (LPALPHABLEND) ::GetProcAddress(::GetModuleHandle(_T("msimg32.dll")), "AlphaBlend");
  2. .... ....
  3. if( lpAlphaBlend && (alphaChannel || uFade < 255) ) {
  4. // uFade:设置背景图片透明度; alphaChannel:启用指定颜色(Mask)透明
  5. BLENDFUNCTION bf = { AC_SRC_OVER, 0, uFade, AC_SRC_ALPHA };
  6. if( lpAlphaBlend == NULL ) lpAlphaBlend = AlphaBitBlt;
  7. .... ....
  8. // Alpha混合贴图
  9. lpAlphaBlend(hDC, lDestLeft, rcDest.top, lDestRight - lDestLeft, rcDest.bottom,
  10. hCloneDC, rcBmpPart.left + rcCorners.left, rcBmpPart.top + rcCorners.top, \
  11. lDrawWidth, rcBmpPart.bottom - rcBmpPart.top - rcCorners.top - rcCorners.bottom, bf);
DuiLib.CControlUI.DoPaint 控件重绘过程
  1. void CControlUI::DoPaint(HDC hDC, const RECT& rcPaint)
  2. {
  3. if( !::IntersectRect(&m_rcPaint, &rcPaint, &m_rcItem) ) return;
  4. // 绘制循序:背景颜色->背景图->状态图->文本->边框
  5. if( m_cxyBorderRound.cx > 0 || m_cxyBorderRound.cy > 0 ) {
  6. CRenderClip roundClip;
  7. // CRenderClip内部以SetWindowRgn()函数对绘制区域进行控制
  8. CRenderClip::GenerateRoundClip(hDC, m_rcPaint, m_rcItem, m_cxyBorderRound.cx, m_cxyBorderRound.cy, roundClip);
  9. PaintBkColor(hDC);
  10. PaintBkImage(hDC);// 调用渲染引擎绘制背景图片
  11. PaintStatusImage(hDC);
  12. PaintText(hDC);
  13. PaintBorder(hDC);
  14. }
  15. else {
  16. PaintBkColor(hDC);
  17. PaintBkImage(hDC);
  18. PaintStatusImage(hDC);
  19. PaintText(hDC);
  20. PaintBorder(hDC);
  21. }
  22. }
DuiLib.CPaintManagerUI.MessageHandler 各控件绘制完成后,整体粘贴到主窗口进行显示
  1. BLENDFUNCTION blendPixelFunction = {AC_SRC_OVER, 0, m_nOpacity, AC_SRC_ALPHA};
  2. 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. ora-04031

    诊断并解决ORA-04031 错误 当我们在共享池中试图分配大片的连续内存失败的时候,Oracle首先清除池中当前没使用的所有对象,使空闲内存块合并.如果仍然没有足够大单个的大块内存满足请求,就会产生 ...

  2. java如何获取本机IP

    java如何获取本机IP import java.net.*; public class Test6 { public static void main(String[] args) { // TOD ...

  3. 【长 PI】

    /* 长 PI 说明: 圆周率后的小数位数是无止境的,如何使用电脑来计算这无止境的小数是一些数学家与程式设计师所感兴趣的,在这边介绍一个公式配合 大 数运算,可以计算指定位数的圆周率. 解法 : 首先 ...

  4. ubuntu 压缩软件

    7-zip 安装: sudo apt-get install p7zip-full 使用方法: 7z x file file是你要解压的文件名 更多使用方法: man 7z rar sudo apt- ...

  5. C++ Primer 笔记 第二章

    C++ Primer 第二章 变量和基本类型 2.1基本内置类型 有算数类型和void类型:算数类型储存空间大小依及其而定. 算数类型表: 类型 含义 最小储存空间 bool 布尔型 - char 字 ...

  6. shell 快速入门

    1: 脚本开始行 #!/bin/bash 这一行表明,不管用户选择的是那种交互式shell,该脚本需要使用bash shell来运行. 由于每种shell的语法大不相同,所以这句非常重要. 2:变量 ...

  7. 5种IE hasLayoutt的属性及其值

    hasLayout 是Windows  Internet  Explore 渲染引擎的一个内部组成部分.在 Internet Explore 中,一个元素要么自己对自身内容进行计算大小和组织,要么依赖 ...

  8. JavaScript从作用域到闭包

    目录 作用域 全局作用域和局部作用域 块作用域与函数作用域 作用域中的声明提前 作用域链 函数声明与赋值 声明式函数.赋值式函数与匿名函数 代码块 自执行函数 闭包  作用域(scope) 全局作用域 ...

  9. DBCC CHECKIDENT在 SQL Server修改指定表的当前标识值

    强制将当前标识值设为新值 ---最后 0 表示新值从1开始 --注意若前边有内容,最好删除,不然id会重复 DBCC CHECKIDENT ("表名称", RESEED, 0);

  10. 打开phpmyadmin显示高级功能尚未完全设置部分功能未激活

    问题:老师,打开phpmyadmin显示高级功能尚未完全设置部分功能未激活,应该如何解决? 这是前一阵子学生问过我的一个问题,今天我就在博客里解答你的疑问吧. 总共三步可以搞定 1.导入相关文件到数据 ...