如何让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
相关产品推荐
相关产品推荐

