C#开发MAC地址悬浮窗:如何实现覆盖全屏应用?
问题:C#悬浮窗无法覆盖全屏应用的解决办法
我给在投注站做现场技术的姐夫开发了个悬浮窗程序,用来显示设备MAC地址,帮他和同事提高效率。找总部申请同款程序要等至少一年,他老板已经批准我来开发。现在用C#写完了,但悬浮窗盖不住全屏应用,有没有简单的解决办法?
现有实现代码
using System; using System.Net.NetworkInformation; using System.Reflection.Metadata; using System.Runtime.InteropServices; using Timer = System.Windows.Forms.Timer; namespace TransparentOverlay { public partial class DisplayMac : Form { private Label macLabel; public DisplayMac() { InitializeComponent(); InitializeUI(); ShowMACAddress(); SetForegroundWindow(this.Handle); } private void InitializeUI() { FormBorderStyle = FormBorderStyle.None; BackColor = System.Drawing.Color.Black; // Set the color to the stroke color TransparencyKey = System.Drawing.Color.Blue; Size = new System.Drawing.Size(200, 30); StartPosition = FormStartPosition.Manual; Location = new System.Drawing.Point(Screen.PrimaryScreen.WorkingArea.Width - Width, Screen.PrimaryScreen.WorkingArea.Height - Height); macLabel = new Label { Text = "MAC Address: ", Location = new System.Drawing.Point(10, 10), AutoSize = true, ForeColor = System.Drawing.Color.White, BackColor = System.Drawing.Color.Black, }; Controls.Add(macLabel); // Then add the main label on top } private void ShowMACAddress() { string macAddress = GetMACAddress(); macLabel.Text += macAddress; Timer timer = new Timer { Interval = 1000 // Update every 1000 milliseconds (1 second) }; timer.Tick += (sender, e) => macLabel.Text = "MAC Address: " + GetMACAddress(); timer.Start(); SetWindowExTransparent(this.Handle); } private string GetMACAddress() { string mac = string.Empty; foreach (NetworkInterface nic in NetworkInterface.GetAllNetworkInterfaces()) { if (nic.NetworkInterfaceType != NetworkInterfaceType.Loopback && nic.OperationalStatus == OperationalStatus.Up) { byte[] physicalAddressBytes = nic.GetPhysicalAddress().GetAddressBytes(); mac = string.Join(":", physicalAddressBytes.Select(b => b.ToString("X2"))); break; } } return mac; } [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); private const int WS_EX_LAYERED = 0x80000; private const int WS_EX_TRANSPARENT = 0x20; private const uint SWP_NOMOVE = 0x2; private const uint SWP_NOSIZE = 0x1; private static readonly IntPtr HWND_TOPMOST = new IntPtr(-1); [DllImport("user32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags); private const uint LWA_COLORKEY = 0x1; private const uint LWA_ALPHA = 0x2; private void SetWindowExTransparent(IntPtr handle) { SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); SetLayeredWindowAttributes(handle, 0, 128, LWA_ALPHA); SetWindowLong(handle, GWL_EXSTYLE, GetWindowLong(handle, GWL_EXSTYLE) | WS_EX_LAYERED | WS_EX_TRANSPARENT); } private const int GWL_EXSTYLE = -20; [DllImport("user32.dll", SetLastError = true)] static extern int GetWindowLong(IntPtr hWnd, int nIndex); [DllImport("user32.dll", SetLastError = true)] static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); [System.Runtime.InteropServices.DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr hWnd); /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new DisplayMac()); } } }
解决步骤
要让悬浮窗稳定覆盖全屏应用,需要从窗口层级、样式优先级两个方面调整,以下是具体修改:
1. 添加关键窗口扩展样式
在类中新增两个常量:
private const int WS_EX_TOOLWINDOW = 0x00000080; // 标记为工具窗口,避免被全屏应用忽略 private const int WS_EX_NOACTIVATE = 0x08000000; // 窗口不获取焦点,始终保持在顶层
2. 修正SetWindowExTransparent方法的执行顺序
原方法的调用顺序错误,导致置顶效果失效,修改后确保先设置扩展样式,再应用置顶和透明度:
private void SetWindowExTransparent(IntPtr handle) { // 先获取并更新扩展样式 int exStyle = GetWindowLong(handle, GWL_EXSTYLE); exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW | WS_EX_NOACTIVATE; SetWindowLong(handle, GWL_EXSTYLE, exStyle); // 设置窗口透明度 SetLayeredWindowAttributes(handle, 0, 128, LWA_ALPHA); // 强制窗口置顶,添加SWP_SHOWWINDOW确保窗口正常显示 SetWindowPos(handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW); }
3. 绑定到桌面窗口(针对硬件加速全屏应用)
如果是DirectX/OpenGL类的全屏应用,需要把悬浮窗绑定到桌面窗口,避免被独占模式屏蔽:
// 新增DllImport声明 [DllImport("user32.dll", SetLastError = true)] static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr GetDesktopWindow();
然后在Form的构造函数中添加:
public DisplayMac() { InitializeComponent(); InitializeUI(); ShowMACAddress(); // 绑定到桌面窗口 SetParent(this.Handle, GetDesktopWindow()); SetForegroundWindow(this.Handle); }
4. 移除冗余的TransparencyKey设置
原代码中同时使用了TransparencyKey和分层窗口透明度,可能导致冲突,建议删除:
// 从InitializeUI方法中删除这一行 // TransparencyKey = System.Drawing.Color.Blue;
验证效果
修改后重新编译运行,悬浮窗应该能稳定覆盖在各类全屏应用上方,同时保持MAC地址的实时更新。
内容的提问来源于stack exchange,提问作者zeebaah
相关产品推荐
相关产品推荐

