C#教程

关注公众号 jb51net

关闭
首页 > 软件编程 > C#教程 > C#鼠标穿透

C# WinForm实现鼠标穿透功能

作者:yue008

在WinForm开发时,会用到这样一个场景,给屏幕增加水印Logo,但不影响画面的操作,这里就会用到鼠标穿透功能,下面我们就来学习一下鼠标穿透功能的具体实现吧

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();
        }
    }
}

到此这篇关于C# WinForm实现鼠标穿透功能的文章就介绍到这了,更多相关C#鼠标穿透内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文