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

C#如何在不隐藏WinForm的情况下截取其后方屏幕?

解决WinForm前置状态下截取后方屏幕内容的方案

方案一:利用分层窗口透明色(无闪烁,窗体全程可见)

通过Windows API将窗体设置为分层窗口,指定一个透明色键,让屏幕捕获操作忽略窗体区域,同时保持窗体视觉上正常显示。

步骤1:导入所需Windows API

在窗体类中添加以下API声明:

using System.Runtime.InteropServices;

private const int WS_EX_LAYERED = 0x80000;
private const int LWA_COLORKEY = 0x1;
private const int WM_SETREDRAW = 0x000B;

[DllImport("user32.dll")]
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, int dwFlags);

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

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

步骤2:修改截图方法

private void GetScreen(string file_path)
{
    // 保存原始状态
    int originalExStyle = GetWindowLongPtr(this.Handle, -20);
    Color originalBackColor = this.BackColor;
    // 选择一个不常用的颜色作为透明键(比如品红色)
    Color transparentKey = Color.Magenta;

    try
    {
        // 禁止窗体重绘,避免闪烁
        SendMessage(this.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);

        // 启用分层窗口并设置透明色键
        SetWindowLongPtr(this.Handle, -20, originalExStyle | WS_EX_LAYERED);
        this.BackColor = transparentKey;
        SetLayeredWindowAttributes(this.Handle, (uint)transparentKey.ToArgb(), 255, LWA_COLORKEY);

        // 强制刷新使透明设置生效
        this.Update();

        // 捕获目标区域的屏幕内容(此时窗体区域会被视为透明,捕获后方内容)
        var rect = new Rectangle(Location.X, Location.Y, Width, Height);
        using var bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format64bppArgb);
        using var gfx = Graphics.FromImage(bmp);
        gfx.CopyFromScreen(rect.Left, rect.Top, 0, 0, this.Size);

        bmp.Save(file_path, ImageFormat.Tiff);
    }
    finally
    {
        // 恢复窗体原始状态
        SetWindowLongPtr(this.Handle, -20, originalExStyle);
        this.BackColor = originalBackColor;

        // 恢复重绘并刷新
        SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
        this.Refresh();
    }
}

说明:如果窗体包含控件,需确保控件背景色不与透明键冲突,或给控件设置不透明的背景色,避免控件也被透明化。


方案二:临时隐藏窗体(实现简单,闪烁极轻微)

通过快速隐藏并恢复窗体,结合禁止重绘和顶层窗口设置,将闪烁降到最低,同时保持窗体前置状态。

步骤1:导入所需Windows API

using System.Runtime.InteropServices;

private const int SW_HIDE = 0;
private const int SW_SHOWNOACTIVATE = 4;
private const int HWND_TOPMOST = -1;
private const int SWP_NOSIZE = 0x0001;
private const int SWP_NOMOVE = 0x0002;
private const int SWP_NOACTIVATE = 0x0010;
private const int WM_SETREDRAW = 0x000B;

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);

[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

步骤2:修改截图方法

private void GetScreen(string file_path)
{
    try
    {
        // 禁止窗体重绘,避免闪烁
        SendMessage(this.Handle, WM_SETREDRAW, IntPtr.Zero, IntPtr.Zero);

        // 隐藏窗体(不激活其他窗口)
        ShowWindow(this.Handle, SW_HIDE);
        // 强制处理消息队列,确保屏幕刷新
        Application.DoEvents();

        // 捕获目标区域的屏幕内容
        var rect = new Rectangle(Location.X, Location.Y, Width, Height);
        using var bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format64bppArgb);
        using var gfx = Graphics.FromImage(bmp);
        gfx.CopyFromScreen(rect.Left, rect.Top, 0, 0, this.Size);

        bmp.Save(file_path, ImageFormat.Tiff);
    }
    finally
    {
        // 显示窗体(不激活)并恢复顶层状态
        ShowWindow(this.Handle, SW_SHOWNOACTIVATE);
        SetWindowPos(this.Handle, (IntPtr)HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);

        // 恢复重绘并刷新
        SendMessage(this.Handle, WM_SETREDRAW, (IntPtr)1, IntPtr.Zero);
        this.Refresh();
    }
}

说明:该方案实现简单,闪烁几乎不可察觉,适合大多数场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 16:14:52