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

C# .NET 8.0自定义屏保捕获桌面返回纯色问题求助

解决方案

问题核心是系统触发屏保时,Windows会先切换到纯色背景再启动屏保程序,你当前在Form构造函数里截图的时机太晚,已经截到了纯色背景。解决思路是在Windows切换背景前提前捕获桌面,再分配给每个屏幕窗口。

修改步骤

1. 提前捕获全局桌面截图

在创建任何屏保窗口前,先捕获整个虚拟桌面的截图,此时系统还未切换到纯色背景:

static void ShowScreenSaver()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    // 捕获整个虚拟桌面(覆盖所有显示器)
    var virtualScreen = SystemInformation.VirtualScreen;
    Bitmap fullDesktop = new Bitmap(virtualScreen.Width, virtualScreen.Height, PixelFormat.Format24bppRgb);
    using (Graphics g = Graphics.FromImage(fullDesktop))
    {
        g.CopyFromScreen(virtualScreen.Location, Point.Empty, virtualScreen.Size);
    }

    // 为每个屏幕创建窗口并传入全局截图
    foreach (Screen screen in Screen.AllScreens)
    {
        var screensaver = new ScreenSaverForm(screen, fullDesktop);
        screensaver.Show();
    }

    Application.Run();
}

2. 修改屏保窗口构造逻辑

从全局截图中截取当前屏幕的区域,同时优化窗口样式确保覆盖全屏:

public Bitmap screenBitmap;

public ScreenSaverForm(Screen screen, Bitmap fullDesktop)
{
    InitializeComponent();
    
    // 设置窗口位置与尺寸
    StartPosition = FormStartPosition.Manual;
    Bounds = screen.Bounds;
    FormBorderStyle = FormBorderStyle.None;
    WindowState = FormWindowState.Maximized;
    TopMost = true;

    // 从全局桌面截图中提取当前屏幕的区域
    screenBitmap = fullDesktop.Clone(screen.Bounds, PixelFormat.Format24bppRgb);

    // 初始化其他属性
    DoubleBuffered = true;
    Paint += ScreenSaverForm_Paint;
    timer1.Start();

    // 可选:设置分层窗口减少闪烁
    SetWindowLongPtr(Handle, GWL_EXSTYLE, GetWindowLongPtr(Handle, GWL_EXSTYLE) | WS_EX_LAYERED);
    SetLayeredWindowAttributes(Handle, 0, 255, LWA_ALPHA);
}

// 引入Windows API用于分层窗口设置
private const int GWL_EXSTYLE = -20;
private const int WS_EX_LAYERED = 0x80000;
private const int LWA_ALPHA = 0x2;

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

[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern int SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr dwNewLong);

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

关键说明

  • 提前截图:将截图逻辑移到窗口创建之前,避开Windows切换纯色背景的时机。
  • 全局截图复用:只捕获一次全局桌面,再为每个屏幕截取对应区域,减少系统资源占用。
  • 窗口样式优化:设置无边框、最大化、最顶层,确保窗口完全覆盖屏幕,阻止纯色背景透出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 14:56:07