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

如何基于窗口句柄录制指定窗口?C#录屏程序改造需求

可以通过窗口句柄实现仅录制目标窗口

完全可以通过窗口句柄实现指定窗口的录制,核心思路是通过窗口句柄获取目标窗口的位置和尺寸,然后只捕获该区域的画面,以下是具体实现方案:

一、添加必要的Windows API调用

首先在NativeMethods类中补充获取窗口信息和捕获窗口画面的API:

public static class NativeMethods
{
    [DllImport("winmm.dll", EntryPoint = "mciSendStringA", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
    public static extern int record(string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback);

    // 获取窗口的位置和尺寸
    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hWnd, out Rectangle lpRect);

    // 直接捕获窗口画面(即使窗口被遮挡也能捕获)
    [DllImport("user32.dll")]
    public static extern bool PrintWindow(IntPtr hWnd, IntPtr hdcBlt, uint nFlags);

    // 获取当前激活窗口句柄
    [DllImport("user32.dll")]
    public static extern IntPtr GetForegroundWindow();
}

二、获取目标窗口的句柄和区域

你可以通过两种方式获取目标窗口句柄:

  • 方式1:直接获取当前激活的窗口
    IntPtr targetWindowHandle = NativeMethods.GetForegroundWindow();
    Rectangle windowRect;
    NativeMethods.GetWindowRect(targetWindowHandle, out windowRect);
    
  • 方式2:实现窗口选择器,枚举所有窗口让用户手动选择(可结合EnumWindows API扩展)

拿到windowRect后,将其传入你的ScreenRecorder构造函数,替换原来的全屏bounds即可。

三、修改截图逻辑,精准捕获目标窗口

原来的CopyFromScreen会捕获屏幕指定区域,但如果窗口被遮挡会捕获到遮挡内容。更可靠的方式是用PrintWindow直接捕获窗口自身的画面:

public void RecordVideo(IntPtr targetWindowHandle)
{
    watch.Start();

    Rectangle windowRect;
    NativeMethods.GetWindowRect(targetWindowHandle, out windowRect);
    
    using (Bitmap bitmap = new Bitmap(windowRect.Width, windowRect.Height))
    {
        using (Graphics g = Graphics.FromImage(bitmap))
        {
            IntPtr hdc = g.GetHdc();
            // 捕获整个窗口(包含边框和标题栏)
            NativeMethods.PrintWindow(targetWindowHandle, hdc, 0);
            g.ReleaseHdc(hdc);
        }
        string name = tempPath + "//screenshot-" + fileCount + ".png";
        bitmap.Save(name, ImageFormat.Png);
        inputImageSequence.Add(name);
        fileCount++;
    }
}

如果只需要捕获窗口的客户区(去掉标题栏和边框),可以补充以下API并调整逻辑:

[DllImport("user32.dll")]
public static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect);

[DllImport("user32.dll")]
public static extern bool ClientToScreen(IntPtr hWnd, ref Point lpPoint);

// 获取客户区屏幕区域示例
Rectangle clientRect;
NativeMethods.GetClientRect(targetWindowHandle, out clientRect);
Point topLeft = new Point(clientRect.Left, clientRect.Top);
NativeMethods.ClientToScreen(targetWindowHandle, ref topLeft);
Rectangle clientScreenRect = new Rectangle(topLeft, clientRect.Size);

四、处理窗口状态变化

如果目标窗口被移动、缩放,需要定时更新窗口区域,比如在录制循环中每隔一段时间重新获取windowRect,保证录制区域始终匹配窗口的最新位置。

五、适配现有代码的核心修改点

  1. 调整ScreenRecorder构造函数,可接收窗口句柄参数,或在外部获取窗口Rect后传入原构造函数
  2. 替换RecordVideo方法的全屏截图逻辑为窗口专属截图逻辑
  3. 在UI上添加"选择窗口"按钮,触发窗口选择逻辑并保存目标窗口句柄

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 00:03:18