C#制作截图软件时,怎样不截取软件窗口本身? 看下图:软件自身也被截下来了

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#制作截图软件时,怎样不截取软件窗口本身? 看下图:软件自身也被截下来了相关的知识,希望对你有一定的参考价值。

一般的软件做法(比如象hypersnap)是当你点击截图的时候,隐藏这个窗体,然后在比如0.5秒之后对屏幕截图(这个延时最好用户可以自己调整),然后恢复你的窗体 参考技术A 思路:
1、this.Hide(); 隐藏窗口
2、Graphics.CopyFromScreen 获取全屏幕图像
3、允许用户拖动鼠标选取截图区域
4、根据用户选取的区域保存图片

通过屏幕截图分析检测游戏黑客C#

【中文标题】通过屏幕截图分析检测游戏黑客C#【英文标题】:Detect game hack through screenshot analysis C# 【发布时间】:2013-08-14 23:52:11 【问题描述】:

我正在尝试编写一些代码来检测游戏的壁挂。 基本上,存在一些创建 windows aero 透明窗口的 hack,他们将 hack 绘制到这个外部窗口上,因此无法通过截取游戏本身的屏幕截图来检测它。

我目前的做法是—— 1.对游戏窗口进行截图。 2. 对相同坐标的windows桌面进行截图。 3. 进行图像分析,对比截图1和截图2,看看是否有差异。

我的问题是屏幕截图 1 和屏幕截图 2 没有同时执行,因此可以在两个屏幕截图之间绘制新的游戏帧,导致比较图像时出现误报。

我想知道是否有办法协调屏幕截图,使它们同时出现?或者以某种方式停止屏幕绘制任何新帧,直到我的屏幕截图完成?

这是我用来截屏的代码。 请注意,我什至尝试通过将两个工作项排队来并行截取 2 个屏幕截图。 但是,即使这样也不会导致屏幕截图同时发生。 所以我想知道是否有某种方法可以停止从显卡对屏幕的任何进一步更新,直到我的屏幕截图完成?或者有什么其他方法可以做到这一点?

    public void DoBitBlt(IntPtr dest, int width, int height, IntPtr src)
    
        GDI32.BitBlt(dest, 0, 0, width, height, src, 0, 0, GDI32.SRCCOPY);
    

    public struct Windows
    
        public Bitmap window;
        public Bitmap desktop;
    
    public Windows CaptureWindows(IntPtr window, IntPtr desktop, User32.RECT coords)
    
        Windows rslt = new Windows();
        // get te hDC of the target window
        IntPtr hdcSrcWindow = User32.GetWindowDC(window);
        IntPtr hdcSrcDesktop = User32.GetWindowDC(desktop);

        // get the size
        int width = coords.right - coords.left;
        int height = coords.bottom - coords.top;

        // create a device context we can copy to
        IntPtr hdcDestWindow = GDI32.CreateCompatibleDC(hdcSrcWindow);
        IntPtr hdcDestDesktop = GDI32.CreateCompatibleDC(hdcSrcDesktop);
        // create a bitmap we can copy it to,
        // using GetDeviceCaps to get the width/height
        IntPtr hBitmapWindow = GDI32.CreateCompatibleBitmap(hdcSrcWindow, width, height);
        IntPtr hBitmapDesktop = GDI32.CreateCompatibleBitmap(hdcSrcDesktop, width, height);
        // select the bitmap object
        IntPtr hOldWindow = GDI32.SelectObject(hdcDestWindow, hBitmapWindow);
        IntPtr hOldDesktop = GDI32.SelectObject(hdcDestDesktop, hBitmapDesktop);
        // bitblt over
        var handle1 = new ManualResetEvent(false);
        var handle2 = new ManualResetEvent(false);
        Action actionWindow = () =>  try  DoBitBlt(hdcDestWindow, width, height, hdcSrcWindow);  finally  handle1.Set();  ;
        Action actionDesktop = () =>  try  DoBitBlt(hdcDestDesktop, width, height, hdcSrcDesktop);  finally  handle2.Set();  ;
        ThreadPool.QueueUserWorkItem(x => actionWindow());
        ThreadPool.QueueUserWorkItem(x => actionDesktop());
        WaitHandle.WaitAll(new WaitHandle[]  handle1, handle2 );

        rslt.window = Bitmap.FromHbitmap(hBitmapWindow);
        rslt.desktop = Bitmap.FromHbitmap(hBitmapDesktop);

        // restore selection
        GDI32.SelectObject(hdcDestWindow, hOldWindow);
        GDI32.SelectObject(hdcDestDesktop, hOldDesktop);
        // clean up
        GDI32.DeleteDC(hdcDestWindow);
        GDI32.DeleteDC(hdcDestDesktop);
        User32.ReleaseDC(window, hdcSrcWindow);
        User32.ReleaseDC(desktop, hdcSrcDesktop);
        // free up the Bitmap object
        GDI32.DeleteObject(hBitmapWindow);
        GDI32.DeleteObject(hBitmapDesktop);
        return rslt;
    

【问题讨论】:

我不相信你的所作所为是合乎道德的。您的“wallhack”检测器正在收集用户可能不希望泄露的信息。为什么用户会同意你在玩游戏时截取他们的桌面?您尝试实施的行为属于特洛伊木马的分类。当然,前提是您没有对程序的目的撒谎。 这可能是Parallel.Foreach 的适当用法。 ThreadPool 不保证并行性。 假设我在一个窗口中打开了你的游戏,然后在该窗口上打开一个网络浏览器(谷歌搜索|检查我的银行账户|浏览 Facebook|做一些非法的事情)然后你截取了那。你会记录一个误报——我在作弊,而我没有作弊,如果你决定上传“伪造”的屏幕截图以进行证明/验证,你可能会意外捕获我的私人详细信息。 Tim S. 不,这不会发生,只有当游戏窗口是活动窗口时才会运行检查。所以如果你打开浏览器,什么都不会发生。 PunkBuster 在用户同意的情况下这样做。因此,如果你们抱怨它不道德,那么其他人已经这样做了,原因与 DaManJ 声称他这样做的原因相同。 【参考方案1】:

您将无法同时拥有两个屏幕截图,除非您使用一些图形加速器,这意味着这不适用于每台计算机...

关于停止渲染,因为它是一个游戏,我认为这不是一个好主意......你希望你的游戏运行流畅。

相反,我建议将最近渲染的游戏图像存储在内存中,并在截取屏幕截图时与它们进行比较。如果您可以添加一些视觉线索来决定与哪些最近的帧进行比较,那么它会更好地工作,因为否则您将不得不将屏幕截图与所有这些帧进行比较,这肯定会占用一些 CPU/GPU 时间。

您是否使用 GDI 进行渲染?如果是这样,您需要将游戏的帧存储在 DIB(设备独立位图)中,以便能够比较它们。

至于决定使用哪个图像的线索,我会在屏幕上寻找某种时间表示,也许是一个改变颜色的像素。如果是这样,您将读取该像素的颜色,使用它来找到正确的帧,然后它们会比较整个图片。

【讨论】:

如果有游戏的配合,其实不需要保存旧帧。旧帧的强校验和,或使用隐写术隐藏在低颜色位中的数据,将完全足以确定屏幕上的图像捕获是否已被修改。

以上是关于C#制作截图软件时,怎样不截取软件窗口本身? 看下图:软件自身也被截下来了的主要内容,如果未能解决你的问题,请参考以下文章

mac上 类似 截图在浮动窗口好工具的软件有没有?

c#利用bitblt如何获取最小化后的窗口截图

C#软件开发实例.私人订制自己的屏幕截图工具在截图中包括鼠标指针形状

C# winform 怎样使制作的卸载程序不删除某些文件,比如access数据库文件

html网页中图片横向滚动

如何用nodejs去做网页截图