You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让WinForm窗体透明但不允许点击穿透?

WinForm屏幕绘图应用:解决透明窗体鼠标穿透问题

问题说明

开发WinForm屏幕绘图工具时,设置窗体透明后出现鼠标点击穿透到后方应用/桌面的问题,无法正常进行绘图操作。尝试过SetStyle(ControlStyles.SupportsTransparentBackColor, true)和BackColor = Color.Transparent,但未解决问题。

解决方案

核心思路是使用Windows API实现分层窗口+色键透明,仅让指定颜色的区域穿透鼠标,绘图区域正常接收事件。

修改后的完整代码

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace screendrawer1
{
    public partial class Form1 : Form
    {
        // Windows API 常量与导入
        private const int WS_EX_LAYERED = 0x80000;
        private const int GWL_EXSTYLE = -20;
        private const int LWA_COLORKEY = 0x1;

        [DllImport("user32.dll", SetLastError = true)]
        private static extern int GetWindowLongPtr(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll", SetLastError = true)]
        private static extern int SetWindowLongPtr(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("user32.dll")]
        private static extern bool SetLayeredWindowAttributes(IntPtr hWnd, uint crKey, byte bAlpha, uint dwFlags);

        private Color currentLineColor = Color.Blue;
        private float currentLineWidth = 2.0f;
        private Point? previousPoint = null;

        public Form1()
        {
            InitializeComponent();

            // 窗体基础配置
            this.FormBorderStyle = FormBorderStyle.None;
            this.WindowState = FormWindowState.Maximized;
            this.TopMost = true;
            this.ShowInTaskbar = false;

            // 启用分层窗口并设置色键透明
            SetWindowLongPtr(this.Handle, GWL_EXSTYLE, GetWindowLongPtr(this.Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
            // 选择洋红色作为透明色,该颜色区域会允许鼠标穿透
            Color transparentKey = Color.Magenta;
            this.BackColor = transparentKey;
            SetLayeredWindowAttributes(this.Handle, (uint)transparentKey.ToArgb(), 255, LWA_COLORKEY);

            // 绑定鼠标移动事件
            this.MouseMove += Form1_MouseMove;
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                using (Graphics g = this.CreateGraphics())
                {
                    Pen pen = new Pen(currentLineColor, currentLineWidth);
                    Point currentPoint = e.Location;

                    if (previousPoint != null)
                    {
                        g.DrawLine(pen, previousPoint.Value, currentPoint);
                    }

                    previousPoint = currentPoint;
                }
            }
            else
            {
                previousPoint = null;
            }
        }

        private void guna2ControlBox1_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}

关键说明

  • 分层窗口与色键透明:通过WS_EX_LAYERED样式启用分层窗口,再用LWA_COLORKEY指定一个颜色(这里用Color.Magenta)作为透明色。窗体中该颜色的区域会完全透明且允许鼠标穿透,其他区域(包括绘图的线条)则能正常接收鼠标事件。
  • 替代原透明方案:放弃了Opacity和TransparentBackColor的设置,色键透明能精准控制穿透区域,避免整体透明导致的鼠标穿透问题。
  • 移除冗余代码:原有的transparentRegion相关代码已不再需要,色键透明机制自动处理穿透区域。

内容的提问来源于stack exchange,提问作者Nicocosaurus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 20:35:30