在 c# 中使用 win32 从窗口获取位图:我哪里出错了?

Posted

技术标签:

【中文标题】在 c# 中使用 win32 从窗口获取位图:我哪里出错了?【英文标题】:Getting Bitmap from a window using win32 in c#: Where am I going wrong? 【发布时间】:2014-06-19 08:06:15 【问题描述】:

我需要检索与某个程序关联的所有窗口的屏幕截图。现在我只是想让它在主窗口中工作。

image = Image.FromHbitmap(mem); 之后,我得到的错误是“GDI+ 中发生一般错误”。我正在尝试按照本教程进行操作

http://www.dreamincode.net/forums/topic/34831-taking-a-screen-shot-in-c%23/

我认为我的指针搞砸了,特别是在这三行:

        IntPtr oldBmp = (IntPtr)Win32Stuff.SelectObject(mem, windowImage);
        Win32Stuff.BitBlt(mem, 0, 0, windowwidth, windowheight, windowDC, 0, 0, 13369376);
        Win32Stuff.SelectObject(mem, oldBmp);

如果我理解正确,oldBmp 和 mem 指向 windowImage,然后 mem 指向 BitBlt 的输出,那么我没有得到现在 mem 指向 oldBmp 的这一行。我尝试将其注释掉,看看这是不是搞砸了,但我得到了同样的一般错误。

这里是完整的代码:

public static class Win32Stuff

    [DllImport("user32.dll", EntryPoint = "ReleaseDC")]
    public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDc);
    [DllImport("user32.dll", EntryPoint = "GetWindowDC")]
    public static extern IntPtr GetWindowDC(IntPtr hWnd);

    [DllImport("gdi32", EntryPoint = "CreateCompatibleDC")]
    public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
    [DllImport("gdi32", EntryPoint = "CreateCompatibleBitmap")]
    public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
    [DllImport("gdi32", EntryPoint = "SelectObject")]
    public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    [DllImport("gdi32", EntryPoint = "BitBlt")]
    public static extern bool BitBlt(IntPtr hDestDC, int X, int Y, int nWidth, int nHeight, IntPtr hSrcDC, int SrcX, int SrcY, int Rop);
    [DllImport("gdi32", EntryPoint = "DeleteDC")]
    public static extern IntPtr DeleteDC(IntPtr hDC);


    public static void getScreenShot()
    
        int windowwidth;
        int windowheight;
        Bitmap image;

        IntPtr windowHandle = Process.GetProcessesByName("firefox")[0].MainWindowHandle;
        IntPtr windowDC = Win32Stuff.GetWindowDC(windowHandle);
        IntPtr mem = Win32Stuff.CreateCompatibleDC(windowDC);

        //need to change this
        windowheight = 1920;
        windowwidth = 1920;

        IntPtr windowImage = Win32Stuff.CreateCompatibleBitmap(windowDC, windowwidth, windowheight);
        IntPtr oldBmp = (IntPtr)Win32Stuff.SelectObject(mem, windowImage);
        Win32Stuff.BitBlt(mem, 0, 0, windowwidth, windowheight, windowDC, 0, 0, 13369376);
        //Win32Stuff.SelectObject(mem, oldBmp);
        image = Image.FromHbitmap(mem);

        Win32Stuff.DeleteDC(mem);
        Win32Stuff.ReleaseDC(windowHandle, mem);
    

我怎样才能看到具体的错误是什么,为什么Image.FromHbitmap() 不能从我的指针输出 GDI 位图?

【问题讨论】:

调用API GetLastError() 看看是什么错误 所以我像这样调用 GetLastError() `try image = Image.FromHbitmap(mem); 捕捉(异常) uint 错误 = Win32Stuff.GetLastError(); `,我得到的错误是 5,我认为缓冲区不足。 5 被拒绝访问。您正在编写 GUI 应用程序吗?还是后端服务? 它将进入一个 GUI 应用程序的客户端。尽管在我为测试而制作的独立控制台应用程序中运行此代码,但我得到了该错误。我还没有在程序中测试过 这篇文章展示了如何获取整个屏幕,或者任何窗口。 developerfusion.com/code/4630/capture-a-screen-shot。有关使用示例,请参阅 ***.com/a/1163781/56778。 【参考方案1】:

改变

image = Image.FromHbitmap(mem);

image = Image.FromHbitmap(windowImage);

【讨论】:

以上是关于在 c# 中使用 win32 从窗口获取位图:我哪里出错了?的主要内容,如果未能解决你的问题,请参考以下文章

win32api:在文本行中合并位图

位图未在 Win32 C++ 中绘制

VC++ win32 API 编程:如何将图像从剪贴板中取出并显示在窗口中?

在C#中如何实现winform窗体的全屏截图功能

C#调用win32 api 操作其它窗口

在 Win32 中显示带 alpha 通道的 32 位图像