如何在C#中捕获Windows Store应用程序窗口内容

26
我有一些代码,用于捕获Windows桌面应用程序的内容并保存到.NET中的位图对象。 它使用User32.dll和Gdi32.dll(BitBlt)并且运行良好。 然而,当我给代码一个持有Windows Store应用程序的窗口句柄时,该代码会产生全黑色位图。 我不确定这是否是安全功能。 由于窗口的内容在调整大小后几乎总是比屏幕更高/更大,因此我无法使用ScreenCapture API。 是否有人尝试过在Windows Store应用程序中捕获窗口内容,即使它们比屏幕更大?
编辑:请注意,我正在尝试捕获不同程序的窗口,而不是我的程序。 可以假定我的程序是.NET 4.6.1 / C#中的Windows控制台应用程序。
此外,我知道这必须在Windows API中以某种方式实现,因为Aero Peek功能(如果你将鼠标悬停在任务栏上运行的程序图标上,则显示窗口的完整高度,包括屏幕外组件。 (请参见右侧的高窗口,设置为6000px,比我的显示器高得多)。

see tall window on right, set to 6000px much higher than my display


我无法将其标记为重复问题,因为有悬赏,但你是否看过:如何捕获Windows商店应用程序的屏幕截图 - chue x
你拥有那个应用吗?因为通常情况下,如果一个应用程序有部分在屏幕外,没有什么可以保证屏幕外的内容能够被物理渲染。一般情况下,你只能捕获屏幕上显示的内容(例如使用graphics.CopyFromScreen)。 - Simon Mourier
不,我没有拥有这个应用程序。我正在尝试从一个使用.NET 4.6.1编写的控制台应用程序中捕获Windows Store应用程序。 - Richthofen
请查看下面提供的解决方案。 - Mavi Domates
@Richtofen:有什么进展吗?我正在尝试从另一个应用程序中获取运行Windows商店应用程序的屏幕截图。 - JD.
2个回答

3

很遗憾,我无法使用RenderTargetBitmap,因为我无法访问应用程序的XAML树。我正在从与我尝试捕获的应用程序不同的应用程序中运行捕获。 - Richthofen
啊.. 就我所知,没有办法做到这一点。我建议你澄清你的问题,明确你正在尝试从另一个应用程序中捕获窗口内容。祝好运 - 如果可能的话,这对我来说也会很有趣。 - Daniel A. Thompson

3

这可能会有帮助。基本上,获取应用程序窗口句柄,调用其原生函数来确定应用程序窗口位置,将其提供给图形类并从屏幕复制。

class Program
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr FindWindow(string strClassName, string strWindowName);

    [DllImport("user32.dll")]
    public static extern bool GetWindowRect(IntPtr hwnd, ref Rect rectangle);

    public struct Rect
    {
        public int Left { get; set; }
        public int Top { get; set; }
        public int Right { get; set; }
        public int Bottom { get; set; }
    }


    static void Main(string[] args)
    {
        /// Give this your app's process name.
        Process[] processes = Process.GetProcessesByName("yourapp");
        Process lol = processes[0];
        IntPtr ptr = lol.MainWindowHandle;
        Rect AppRect = new Rect();
        GetWindowRect(ptr, ref AppRect);
        Rectangle rect = new Rectangle(AppRect.Left, AppRect.Top, (AppRect.Right - AppRect.Left), (AppRect.Bottom - AppRect.Top));
        Bitmap bmp = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb);
        Graphics g = Graphics.FromImage(bmp);
        g.CopyFromScreen(rect.Left, rect.Top, 0, 0, bmp.Size, CopyPixelOperation.SourceCopy);

        // make sure temp directory is there or it will throw.
        bmp.Save(@"c:\temp\test.jpg", ImageFormat.Jpeg);
    }
}

所以,这可能适用于您只需要屏幕内容的情况。然而,在我的情况下,我的窗口比屏幕更大(屏幕高度为2000像素,但窗口高度/内容约为6000像素)。 - Richthofen
类似于Selenium的截屏功能(尽管我要捕获的窗口不是Web浏览器),我想一次性捕获整个窗口内容缓冲区。 - Richthofen
啊,我明白了。所以你实际上需要应用程序的内部内容,通常需要滚动,你想将其提取为图像。 - Mavi Domates

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接