当前位置: 首页 > article >正文

C#鼠标穿透功能(WinForm)

C#鼠标穿透功能(WinForm)

在WinForm开发时,会用到这样一个场景,给屏幕增加水印Logo,但不影响画面的操作。这里就会用到鼠标穿透功能。

User32.Dll函数

要想实现鼠标穿透功能,需要用到User32.Dll的几个函数:SetWindowLong、GetWindowLong、SetLayeredWindowAttributes。

SetWindowLong

语法规则

LONG SetWindowLongA(
  [in] HWND hWnd,
  [in] int  nIndex,
  [in] LONG dwNewLong
);

描述:更改指定窗口的属性。 函数还将指定偏移量的 32 位 (长) 值设置为额外的窗口内存。

参数类型描述
[in] hWndHWND窗口的句柄,以及窗口所属类的间接句柄。
[in] nIndexint要设置的值的从零开始的偏移量。 有效值在零到额外窗口内存的字节数之间,减去整数的大小。 若要设置任何其他值,请指定以下值之一。
[in]dwNewLongLONG替换值

其中nIndex的值含义如下,常用到值为GWL_EXSTYLE=(-20)和GWL_STYLE=(-16)

含义
GWL_EXSTYLE-20设置新的 扩展窗口样式
GWL_HINSTANCE-6设置新的应用程序实例句柄。
GWL_ID-12设置子窗口的新标识符。 该窗口不能是顶级窗口。
GWL_STYLE-16设置新 窗口样式
GWL_USERDATA-21设置与窗口关联的用户数据。 此数据供创建窗口的应用程序使用。 其值最初为零。
GWL_WNDPROC-4为窗口过程设置新地址。如果窗口不属于调用线程所在的进程,则无法更改此属性。

返回值:Long

如果函数成功,则返回值是指定 32 位整数的上一个值。

如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。

如果指定的 32 位整数的上一个值为零,并且函数成功,则返回值为零,但函数不会清除最后一个错误信息。 这使得很难确定成功或失败。 若要处理此问题,在调用 SetWindowLong 之前,应通过调用 SetLastError 0 来清除最后一个错误信息。 然后,函数失败将由返回值零和 GetLastError 结果指示为非零。

目前基本不做判断

GetWindowLong

语法规则

LONG GetWindowLongA(
  [in] HWND hWnd,
  [in] int  nIndex
);

描述

检索有关指定窗口的信息。 该函数还会检索 32 位 (DWORD) 指定偏移量到额外窗口内存的值。

参数类型描述
[in] hWndHWND窗口的句柄,以及窗口所属类的间接句柄。
[in] nIndexint要检索的值的从零开始的偏移量。 有效值的范围是零到额外窗口内存的字节数减去 4;例如,如果指定了 12 个或更多字节的额外内存,则值 8 将是第三个 32 位整数的索引。 若要检索任何其他值,请指定以下值之一。

其中nIndex的值含义如下,常用到值为GWL_EXSTYLE=(-20)和GWL_STYLE=(-16)

含义
GWL_EXSTYLE-20检索 扩展窗口样式
GWL_HINSTANCE-6检索应用程序实例的句柄。
GWL_HWNDPARENT-8检索父窗口的句柄(如果有)。
GWL_ID-12检索窗口的标识符。
GWL_STYLE-16检索 窗口样式
GWL_USERDATA-21检索与窗口关联的用户数据。 此数据供创建窗口的应用程序使用。 其值最初为零。
GWL_WNDPROC-4检索窗口过程的地址,或表示窗口过程地址的句柄。 必须使用 CallWindowProc函数调用窗口过程。

返回值
类型: LONG

如果函数成功,则返回值为请求的值。

如果函数失败,则返回值为零。 要获得更多的错误信息,请调用 GetLastError。

如果以前未调用 SetWindowLong , 则 GetWindowLong 为额外窗口或类内存中的值返回零。

SetLayeredWindowAttributes

语法规则

BOOL SetLayeredWindowAttributes(
  [in] HWND     hwnd, 
  [in] COLORREF crKey,
  [in] BYTE     bAlpha,
  [in] DWORD    dwFlags
);

描述:设置分层窗口的不透明度和透明度颜色键。

参数类型描述
[in] hWndHWND分层窗口的句柄。 使用 CreateWindowEx 函数创建窗口时指定WS_EX_LAYERED,或者在创建窗口后通过 SetWindowLong 设置WS_EX_LAYERED来创建分层窗口。

Windows 8: 顶级窗口和子窗口支持 WS_EX_LAYERED 样式。 以前的 Windows 版本仅支持 顶级窗口WS_EX_LAYERED 。
[in] crKeyCOLORREFCOLORREF 结构,指定要在组合分层窗口时使用的透明度颜色键。 窗口以这种颜色绘制的所有像素都是透明的。 若要生成 COLORREF,请使用 RGB 宏。
[in]bAlphaBYTE用于描述分层窗口的不透明度的 Alpha 值。 类似于 BLENDFUNCTION 结构的 SourceConstantAlpha 成员。 当 bAlpha 为 0 时,窗口是完全透明的。 当 bAlpha 为 255 时,窗口是不透明的。
[in]dwFlagsDWORD要执行的操作。 此参数可使用以下一个或多个值。
含义
LWA_ALPHA0x00000002使用 bAlpha 确定分层窗口的不透明度。
LWA_COLORKEY0x00000001使用 crKey 作为透明度颜色。

第二个就是要设置的一个透明色,第三个是要设置的透明度,bAlpha的范围是 0-255,如果是0,那么完全透明,如果是255,是完全不透明。 第四个参数,就是设置是按照透明色来透明,还是按照bAlpha来透明。或者两个都设置。 如果 dwFlags 设置了LWA_COLORKEY,那么crKey就起作用,窗口中所有的crKey颜色区域就会全部透明,如果dwFlags设置了LWA_ALPHA,那么bAlpha就会起作用,整个窗口就会按照bAlpha的值来透明。也可以这两个一起设置来同时实现这两个效果。

功能代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace demo189_窗体移动
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        //定义user32.dll参数值
        private const uint WS_EX_LAYERED = 0x80000;
        private const int WS_EX_TRANSPARENT = 0x20;
        private const int GWL_STYLE = (-16);
        private const int GWL_EXSTYLE = (-20);
        private const int LWA_ALPHA = 0;

        //更改指定窗口的属性
        [DllImport("user32", EntryPoint = "SetWindowLong")]
        private static extern uint SetWindowLong(IntPtr hwnd,int nIndex,uint dwNewLong
        );
        //检索有关指定窗口的信息
        [DllImport("user32", EntryPoint = "GetWindowLong")]
        private static extern uint GetWindowLong(IntPtr hwnd,int nIndex
        );
        //设置分层窗口的不透明度和透明度颜色键
        [DllImport("user32", EntryPoint = "SetLayeredWindowAttributes")]
        private static extern int SetLayeredWindowAttributes(IntPtr hwnd,int crKey,int bAlpha,int dwFlags
        );

        /// <summary> 
        /// 设置窗体具有鼠标穿透效果 
        /// </summary> 
        public void SetPenetrate()
        {
            this.TopMost = true;
           //GetWindowLong(this.Handle, GWL_EXSTYLE);
            SetWindowLong(this.Handle, GWL_EXSTYLE, WS_EX_TRANSPARENT | WS_EX_LAYERED);
            SetLayeredWindowAttributes(m_hWnd,0,(BYTE)220,LWA_ALPHA);
           //SetLayeredWindowAttributes(m_hWnd,RGB(255,0,255),(BYTE)220,LWA_ALPHA|LWA_COLORKEY);
            //SetLayeredWindowAttributes(m_hWnd,RGB(0,255,0),0,LWA_COLORKEY);
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            this.Opacity = 0.7;
            SetPenetrate();
        }
    }
}


http://www.kler.cn/a/149097.html

相关文章:

  • 应用系统开发(1)涡流检测设备以及关键技术要点
  • c++11(一)
  • 数据仓库之 Atlas 血缘分析:揭示数据流奥秘
  • Linux服务器screen命令和系统日志
  • UniAPP u-popup 禁止背景滑动
  • 「Mac畅玩鸿蒙与硬件31」UI互动应用篇8 - 自定义评分星级组件
  • 命令模式 (Command Pattern)
  • OPENWRT路由配置IPV6公网访问
  • PTA:用函数实现从数列中删除一个数
  • Redis深入理解-主从架构下内核数据结构、主从同步以及主节点选举
  • 微信小程序获取手机号流程以及用到的API
  • 零信任安全:远程浏览器隔离(RBI)的重要性
  • 283. 移动零(双指针)
  • webform使用ajax访问后端接口的两种方法
  • 这个蓄电池监控神技,谁用谁知道!
  • C++数据结构:图
  • react项目自行配置热更新
  • 2023金盾杯线上赛-AGRT战队-WP
  • MySQL -DDL 及表类型
  • Django RestFramework
  • 【Rust】结构体与枚举
  • AIGC: 关于ChatGPT中Prompt模板的优化
  • 人工智能_机器学习053_支持向量机SVM目标函数推导_SVM条件_公式推导过程---人工智能工作笔记0093
  • Mysql8.1.0 安装问题-缺少visual studio 2019x64组件
  • Linux内核--内存管理(三)物理内存分页机制--kmalloc及slub机制
  • 解决Maven项目jar包下载失败的问题