资料准备

  • WS_EX_TRANSPARENT | WS_EX_LAYERED
  • WM_NCHITTEST & return HTTRANSPARENT
  • SetLayeredWindowAttributes(…)
  • UpdateLayeredWindow(…)

旁征博引

窗口类型

  • Overlapped Windows
  • Pop-up Windows
  • Child Windows
  • Layered Windows             \\分层窗口(这是我们这节课研究的重点)
  • Message-Only Windows     \\消息窗口

分层窗口详解:

Using a layered window can significantly improve performance and visual effects for a window that has a complex shape, animates its shape, or wishes to use alpha blending effects. The system automatically composes and repaints layered windows and the windows of underlying applications. As a result, layered windows are rendered smoothly, without the flickering typical of complex window regions. In addition, layered windows can be partially translucent, that is, alpha-blended.

这段大概就是说,layered窗口能够改善显示效果,给你的窗体加个alpha通道,可以平滑半透明地显示。嗯,还可以设置为一部分透明一部分不透明的样子。(据我研究,应该还能设置成渐变透明。)

To create a layered window, specify the WS_EX_LAYERED extended window style when calling the CreateWindowEx function, or call the SetWindowLong function to set WS_EX_LAYERED after the window has been created. After the CreateWindowEx call, the layered window will not become visible until the SetLayeredWindowAttributes or UpdateLayeredWindow function has been called for this window. Note that WS_EX_LAYERED cannot be used for child windows.

一旦你指定了这个属性,刚开始这个窗体是不能显示的,你得先设置整个窗体的Alpha通道。通过这两个函数SetLayeredWindowAttributes、UpdateLayeredWindow 。

值得一提的的是这个不能用于子窗体(也就是不能和WS_CHILD共存呗)。

To set the opacity level or the transparency color key for a given layered window, call SetLayeredWindowAttributes. After the call, the system may still ask the window to paint when the window is shown or resized. However, because the system stores the image of a layered window, the system will not ask the window to paint if parts of it are revealed as a result of relative window moves on the desktop. Legacy applications do not need to restructure their painting code if they want to add translucency or transparency effects for a window, because the system redirects the painting of windows that called SetLayeredWindowAttributes into off-screen memory and recomposes it to achieve the desired effect.

嗯,这段说实话以我高一的英语水平也没看太懂。大致意思就是,系统可能仍然会给你发送WM_PAINT,但是请注意,系统会自动帮你半透明。你不需要更改任何代码就能够实现半透明效果。

总的来说就是:除非程序中调用了InvalidateRect之类的函数,否则系统将接管窗口的绘制,用户收不到WM_PAINT消息!

这个图片可以帮你理解:

For faster and more efficient animation or if per-pixel alpha is needed, call UpdateLayeredWindow. UpdateLayeredWindow should be used primarily when the application must directly supply the shape and content of a layered window, without using the redirection mechanism the system provides through SetLayeredWindowAttributes. In addition, using UpdateLayeredWindow directly uses memory more efficiently, because the system does not need the additional memory required for storing the image of the redirected window. For maximum efficiency in animating windows, call UpdateLayeredWindow to change the position and the size of a layered window. Please note that after SetLayeredWindowAttributes has been called, subsequent UpdateLayeredWindow calls will fail until the layering style bit is cleared and set again.

这段很重要!这俩函数是互相冲突的!想为窗口的每个像素设置Alpha通道你就直接调用UpdateLayeredWindow ,请不要调用SetLayeredWindowAttributes. 如果你想要重置,那就清除WS_EX_LAYERED然后重新设置!

Hit testing of a layered window is based on the shape and transparency of the window. This means that the areas of the window that are color-keyed or whose alpha value is zero will let the mouse messages through. However, if the layered window has the WS_EX_TRANSPARENT extended window style, the shape of the layered window will be ignored and the mouse events will be passed to other windows underneath the layered window.

碰撞测试(就是测试你的键鼠操作是不是落在这个窗体上)取决于你的透明度!也就是说:透明度为完全透明的窗体部分会被“穿透”。如果你想要整个窗体都被“穿透”,请设置WS_EX_TRANSPARENT属性!

——Come From MSDN

WM_NCHITTEST & return HTTRANSPARENT

了解这一部分的时候请注意了:这一部分不能实现穿透功能(准确的说是他的穿透功能很有限)。

首先我们先了解一下这个 WM_NCHITTEST 是什么玩意儿:

The WM_NCHITTEST message is sent to a window in order to determine what part of the window corresponds to a particular screen coordinate. This can happen, for example, when the cursor moves, when a mouse button is pressed or released, or in response to a call to a function such as WindowFromPoint. If the mouse is not captured, the message is sent to the window beneath the cursor. Otherwise, the message is sent to the window that has captured the mouse.

这个消息主要用于帮助系统判断窗体的哪一部分被点到了,哪一部分被操作了。

它的返回值有一条是这样的:

HTTRANSPARENT

In a window currently covered by another window in the same thread (the message will be sent to underlying windows in the same thread until one of them returns a code that is not HTTRANSPARENT).

这段我也不翻译了,相信你也注意到了“in the same thread ”已经连续出现了两次了!微软到底在强调什么呢…….呵呵

SetLayeredWindowAttributes

函数说明:
BOOL SetLayeredWindowAttributes(__in  HWND hwnd,__in  COLORREF crKey,__in  BYTE bAlpha,__in  DWORD dwFlags
);
\\这函数用于设置窗口的alpha混合(不透明度)
\\实现出来的效果是整个窗体都以某一透明度显示
函数参数:

hwnd [in] HWND

Handle to the layered window. A layered window is created by specifying WS_EX_LAYERED when creating the window with the CreateWindowEx function or by setting WS_EX_LAYERED via SetWindowLong after the window has been created.

拥有WS_EX_LAYERED 属性的窗口句柄。

crKey [in] COLORREF

COLORREF structure that specifies the transparency color key to be used when composing the layered window. All pixels painted by the window in this color will be transparent. To generate a COLORREF, use the RGB macro.

具体说起来又要长篇大论了,简单来说就是透明窗体的底色是什么??我们不需要底色,只需要能够看到该窗体下面的另一个窗体,我们就可以忽略这个参数。

bAlpha [in]

BYTE

Alpha value used to describe the opacity of the layered window. Similar to the SourceConstantAlpha member of the BLENDFUNCTION structure. When bAlpha is 0, the window is completely transparent. When bAlpha is 255, the window is opaque.

该值为0全透明,该值为255不透明。为什么是255呢??

该参数是BYTE类型 只有8位可存储来着 你把 11111111 转换为十进制就是255。

dwFlags [in] DWORD

Specifies an action to take. This parameter can be one or more of the following values.

指定哪个参数我们使用了,因为我们忽略了crKey参数,所以我们仅仅指定LWA_ALPHA就可以了。

LWA_COLORKEY

Use crKey as the transparency color.

LWA_ALPHA

Use bAlpha to determine the opacity of the layered window.

函数返回:

BOOL

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero. To get extended error information, call GetLastError.

不解释,你懂得。

需要注意:

Note that once SetLayeredWindowAttributes has been called for a layered window, subsequent UpdateLayeredWindow calls will fail until the layering style bit is cleared and set again.

什么?你问我这一段意思是什么????那就请你重头认真看我的教程,不要走马观花!

UpdateLayeredWindow

函数说明:
BOOL UpdateLayeredWindow(__in  HWND hwnd,__in  HDC hdcDst,__in  POINT *pptDst,__in  SIZE *psize,__in  HDC hdcSrc,__in  POINT *pptSrc,__in  COLORREF crKey,__in  BLENDFUNCTION *pblend,__in  DWORD dwFlags
)\\该函数更新分层窗口的位置、大小、形状、内容、透明度
函数参数:

hwnd [in] HWND

Handle to a layered window. A layered window is created by specifying WS_EX_LAYERED when creating the window with the CreateWindowEx function.

hdcDst [in] HDC

Handle to a DC for the screen. This handle is obtained by specifying NULL when calling the function. It is used for palette color matching when the window contents are updated. If hdcDst is NULL, the default palette will be used.

输出到的DC句柄(GetDC(NULL)),你也可以写NULL使用默认调色盘(不改变内容)。

If hdcSrc is NULL, hdcDst must be NULL.

pptDst [in] POINT

Pointer to a POINT structure that specifies the new screen position of the layered window. If the current position is not changing, pptDst can be NULL.

更新位置信息(写NULL表示不移动)

psize [in] SIZE

Pointer to a SIZE structure that specifies the new size of the layered window. If the size of the window is not changing, psize can be NULL. If hdcSrc is NULL, psize must be NULL.

更新大小信息(写NULL表示不缩放)

hdcSrc [in] HDC

Handle to a DC for the surface that defines the layered window. This handle can be obtained by calling the CreateCompatibleDC function. If the shape and visual context of the window are not changing, hdcSrc can be NULL.

内容信息(用于更新窗口颜色)

pptSrc [in] POINT

Pointer to a POINT structure that specifies the location of the layer in the device context. If hdcSrc is NULL, pptSrc should be NULL.

从hdcSrc的哪个位置开始更新?

crKey [in] COLORREF

COLORREF structure that specifies the color key to be used when composing the layered window. To generate a COLORREF, use the RGB macro.

这个,同上个函数。

pblend [in] BLENDFUNCTION

Pointer to a BLENDFUNCTION structure that specifies the transparency value to be used when composing the layered window.

用于更新alpha(我们将在下面给出详解)

dwFlags [in] DWORD

This parameter can be one of the following values.

同上个函数

ULW_ALPHA

Use pblend as the blend function. If the display mode is 256 colors or less, the effect of this value is the same as the effect of ULW_OPAQUE.

ULW_COLORKEY

Use crKey as the transparency color.

ULW_OPAQUE

Draw an opaque layered window.

If hdcSrc is NULL, dwFlags should be zero.

函数返回:

If the function succeeds, the return value is nonzero.

If the function fails, the return value is zero.

需要注意:
  • 更新一次就像永久更改了整个窗体的位图一样
  • 效率较低
  • 系统自动重新绘制
  • 没有WM_PAINT

最后是极其重要的内容:BLENDFUNCTION参数的讲解:

基本概念:

BLENDFUNCTION结构体

AlphaBlend是Window自带的GDI函数,在作GUI的时候为了达到更漂亮的效果我们常常用它。 

这种结构的混合控制通过指定源和目标位图的混合功能。 

typedef struct _BLENDFUNCTION {

BYTE BlendOp;

BYTE BlendFlags;

BYTE SourceConstantAlpha;

BYTE AlphaFormat;

} BLENDFUNCTION, *PBLENDFUNCTION, *LPBLENDFUNCTION;

BlendOp 指定源混合操作。目前,唯一的源和目标的混合方式已定义为AC_SRC_OVER; 

BlendFlags 必须是0; 

SourceConstantAlpha 指定一个alpha透明度值,这个值将用于整个源位图;该SourceConstantAlpha值与源位图的每个像素的alpha值组合;如果设置为0,就会假定你的图片是透明的;如果需要使用每像素本身的alpha值,设置SourceConstantAlpha值255(不透明); 

AlphaFormat 这个参数控制源和目标的解析方式,AlphaFormat参数有以下值:

AC_SRC_ALPHA: 这个值在源或者目标本身有Alpha通道时(也就是操作的图本身带有透明通道信息时),提醒系统API调用函数前必须预先乘以alpha值,也就是说位图上某个像素位置的red、green、blue通道值必须先与alpha相乘。例如,如果alpha透明值是x,那么red、green、blue三个通道的值必须乘以x并且再除以255(因为alpha的值的范围是0~255),之后才能被调用。

应用备注:

1、当AlphaFormat参数的值是AC_SRC_ALPHA,那么源位图必须是32位深,否则的话,AlphaBland函数将调用失败

2、当BlendOp参数是AC_SRC_OVER时,源位图根据alpha透明度值直接覆盖在目标位图之上

3、如果源位图不带有透明度信息(那样的话,AC_SRC_ALPHA不设置),将由SourceConstanAlpha的值来决定如何混合源位图与目标位图,如下表中所示。表中SCA代表SourceConstantAlpha的值,同样,SCA除以了255,因为它的范围是从0到255.

Dst.Red = Src.Red * (SCA/255.0) + Dst.Red * (1.0 - (SCA/255.0))

Dst.Green = Src.Green * (SCA/255.0) + Dst.Green * (1.0 - (SCA/255.0))

Dst.Blue = Src.Blue * (SCA/255.0) + Dst.Blue * (1.0 - (SCA/255.0))

在这种情况下,如果目标位图有透明度信息,那么混合方式将按照下面的公式来:

Dst.Alpha = Src.Alpha * (SCA/255.0) + Dst.Alpha * (1.0 - (SCA/255.0))

4、如果源位图没有用SourceConstantAlpha参数值(那表示该参数等于255),每一个像素的透明度将决定源位图和目标位图的混合结果,如下所示:

Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Red

Dst.Green = Src.Green + (1 - Src.Alpha) * Dst.Green

Dst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue

在这种情况下,如果如果目标位图有透明度信息,那么混合方式将按照下面的公式来:

Dest.alpha = Src.Alpha + (1 - SrcAlpha) * Dst.Alpha

5、如果源位图既有SourceConstantAlpha值(也就是它的值不是255),每个像素又有透明度值,那么源位图的每一个像素将首先乘以SourceConstantAlpha的值,然后根据每个像素的透明度值混合,如下表中所示。同样,SourceConstantAlpha除以了255,因为它的范围是从0到255.

Src.Red = Src.Red * SourceConstantAlpha / 255.0;

Src.Green = Src.Green * SourceConstantAlpha / 255.0;

Src.Blue = Src.Blue * SourceConstantAlpha / 255.0;

Src.Alpha = Src.Alpha * SourceConstantAlpha / 255.0;

Dst.Red = Src.Red + (1 - Src.Alpha) * Dst.Red

Dst.Green = Src.Green + (1 - Src.Alpha) * Dst.Green

Dst.Blue = Src.Blue + (1 - Src.Alpha) * Dst.Blue

Dst.Alpha = Src.Alpha + (1 - Src.Alpha) * Dst.Alpha

——该部分来自《百度百科》

现在重点来了!

=>!!!前方高能请注意!!!<=

透明渐变&鼠标穿透的实现方法,实现效果如图:

=》传送门《=

转载于:https://www.cnblogs.com/xnzzj/p/4524085.html

[随笔]关于如何实现鼠标穿透窗口和窗口半透明相关推荐

  1. VC++ SetLayeredWindowAttributes 部分窗口透明鼠标穿透

    在初始化中使用下面两行代码 ModifyStyleEx(0, WS_EX_LAYERED); ::SetLayeredWindowAttributes(m_hWnd, RGB(1, 255, 0), ...

  2. C# Winform 窗体美化(五、鼠标穿透)

    五.鼠标穿透 以前在玩射击游戏的时候,狙击枪的设定一般是开镜才有准星,所以想是不是可以自己造一个默认准星出来,思路是现在窗口上画一个准星,然后把窗体其他区域都透明,然后设置鼠标穿透: 结果是: Upd ...

  3. 无边框透明窗口设置鼠标穿透与不穿透功能

    一.设置鼠标穿透功能: 1.先设置鼠标穿透.无边框.透明,其中鼠标穿透属性要放在第一个位置设置: this->setAttribute(Qt::WA_TransparentForMouseEve ...

  4. Simple WPF:实现一个透明、无边框、鼠标穿透的WPF窗体

    WPF 透明窗体和鼠标事件穿透 一个自定义WPF窗体的解决方案,借鉴了吕毅老师的WPF制作高性能的透明背景的异形窗口一文,并在此基础上增加了鼠标穿透的功能.可以使得透明窗体的鼠标事件穿透到下层,在下层 ...

  5. 关于怎么实现鼠标穿透窗体,实现窗体透明

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  6. winform和wpf如何实现鼠标穿透的效果

    先看一下鼠标穿透的效果: 可以看到Form1这个程序虽然遮在了桌面的上面,但是我们还可以在窗体上点击桌面上的必应词典和网易邮箱大师,好像这个叫"Form1"的窗口被"穿透 ...

  7. C#模拟鼠标键盘控制其他窗口(一)

    编写程序模拟鼠标和键盘操作可以方便的实现你需要的功能,而不需要对方程序为你开放接口.比如,操作飞信定时发送短信等.我之前开发过飞信耗子,用的是对飞信协议进行抓包,然后分析协议,进而模拟协议的执行,开发 ...

  8. C#使用Windows API实现桌面上的遮罩层(鼠标穿透)

    C#实现实现桌面上的遮罩层(鼠标穿透)主要通过一下几个API函数来实现:GetWindowLong,SetWindowLong,SetLayeredWindowAttributes.其中有一个Wind ...

  9. WPF 获取鼠标屏幕位置、窗口位置、控件位置

    原文:WPF 获取鼠标屏幕位置.窗口位置.控件位置 public struct POINT{public int X;public int Y;public POINT(int x, int y){t ...

最新文章

  1. vCenter的安装
  2. WPF 提供了以下关键帧动画类[msdn]
  3. sublime text3的php代码合法检查
  4. 16汇编 and和or实现大小写转换
  5. MFC中将CBitmap画到cdc上
  6. 如何高效的比较两个 Object 对象是否相等?
  7. MySQL数据库的权限表
  8. 一周消息树:程序员想找好工作?那就学好Linux!
  9. python while循环if_20170403Python控制流if、while、for语句学习
  10. 20199计算机二级java答案_计算机二级Java练习题-2019.9
  11. python爬虫过程中遇到的问题_python爬虫过程中出现的问题汇总-Go语言中文社区
  12. (转)VC 字节对齐
  13. IDC:IoT市场即将井喷的5大标志
  14. java 远程调试 端口_java – 远程调试:在端口8787上没有连接到OpenJDK 11上的Wildfly 14...
  15. pythotn基础篇——条件分支与循环--2
  16. 华为交换机配置时区_华为交换机设置时间问题
  17. 互联网日报 | 6月8日 星期二 | 华为30亿成立数字能源公司;阿里明星直播业务“天猫星选”上线;苹果WWDC 2021开幕...
  18. 常用数据库URL地址的写法
  19. RC滤波分析计算——信号与系统
  20. 业务监控 开源_将您的开源项目转变为业务的钥匙

热门文章

  1. pdd实现主图详情图片一键下载
  2. 西安电子科技大学硕士论文latex模板第1章修改为第一章
  3. flutter调用android 原生TextView
  4. Github中如何给项目创建GitHub Pages官方网页
  5. 数字化转型大咖群研讨实录20210506
  6. Linux驱动开发 -- touch驱动注册
  7. 录播系统的服务器,录播系统服务器ip地址
  8. 【思维导图】vue的思维导图(超全的)
  9. 学习Vue3 第十三章(实操组件和认识less 和 scoped)
  10. S4 HANA BP 新增客商公司代码数据