使用StretchBlt和GetDesktopWindow将图像绘制到屏幕上

问题描述 投票:-1回答:1

我正在尝试使用Bitmap在屏幕上显示GetDesktopWindow()以获取桌面窗口的句柄,并使用StretchBlt将图像复制到其中。但是,这不起作用。它显示完全空白的图像还是完全白色的图像,具体取决于我使用的是SRCCOPY还是其他常数。

这里是代码:

[DllImport("GDI32.DLL", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
    private static extern bool StretchBlt(IntPtr hdcDest, int nXDest, int nYDest, int nDestWidth, int nDestHeight,
        IntPtr hdcSrc, int nXSrc, int nYSrc, int nSrcWidth, int nSrcHeight, TernaryRasterOperations dwRop);

    [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll", ExactSpelling = true)]
    private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("gdi32.dll", ExactSpelling = true)]
    private static extern IntPtr BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);

    [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
    private static extern IntPtr GetDesktopWindow();

    public enum TernaryRasterOperations
    {
        SRCCOPY = 0x00CC0020, /* dest = source*/
        SRCPAINT = 0x00EE0086, /* dest = source OR dest*/
        SRCAND = 0x008800C6, /* dest = source AND dest*/
        SRCINVERT = 0x00660046, /* dest = source XOR dest*/
        SRCERASE = 0x00440328, /* dest = source AND (NOT dest )*/
        NOTSRCCOPY = 0x00330008, /* dest = (NOT source)*/
        NOTSRCERASE = 0x001100A6, /* dest = (NOT src) AND (NOT dest) */
        MERGECOPY = 0x00C000CA, /* dest = (source AND pattern)*/
        MERGEPAINT = 0x00BB0226, /* dest = (NOT source) OR dest*/
        PATCOPY = 0x00F00021, /* dest = pattern*/
        PATPAINT = 0x00FB0A09, /* dest = DPSnoo*/
        PATINVERT = 0x005A0049, /* dest = pattern XOR dest*/
        DSTINVERT = 0x00550009, /* dest = (NOT dest)*/
        BLACKNESS = 0x00000042, /* dest = BLACK*/
        WHITENESS = 0x00FF0062, /* dest = WHITE*/
    };
    public static void DrawBitmapToScreen(Bitmap bmp, TernaryRasterOperations operations)
    {
        int width = bmp.Width;
        int height = bmp.Height;

        IntPtr hwnd = GetDesktopWindow();
        IntPtr hdc = GetDC(hwnd);

        //create Graphic from source bitmap

        Graphics bmpGraphic = Graphics.FromImage(bmp);
        //because (when uncommented) the following line works for coping a block from the form???
        //Graphics bmpGraphic = this.CreateGraphics();

        //get handle to source graphic
        IntPtr srcHdc = bmpGraphic.GetHdc();

        //copy it
        bool res = StretchBlt(hdc, 20, 20, width, height,
            srcHdc, 0, 0, width, height, operations);

        //release handles
        bmpGraphic.ReleaseHdc();
        ReleaseDC(hwnd, hdc);
    }

要称呼它,然后使用:

DrawBitmapToScreen((Bitmap)pictureBox1.Image, TernaryRasterOperations.SRCCOPY);

我做错了什么?

编辑:如果您刷新Windows资源管理器或在其上移动一个窗口,则需要从屏幕上删除该图像

c# dll handle
1个回答
0
投票

我找到了不使用StretchBlt()BitBlt()的解决方案。唯一不受管理的代码是GetDC()GetDesktopWindow()ReleaseDC()。这是代码

[DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
    private static extern IntPtr GetDC(IntPtr hWnd);

    [DllImport("user32.dll", ExactSpelling = true)]
    private static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

    [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
    private static extern IntPtr GetDesktopWindow();

    public static void DrawBitmapToScreen(Bitmap bmp)
    {
        int width = bmp.Width;
        int height = bmp.Height;

        IntPtr hwnd = GetDesktopWindow();
        IntPtr hdc = GetDC(hwnd);
        using (Graphics g = Graphics.FromHdc(hdc))
        {
            g.DrawImage(bmp, new Point(0, 0));
        }

        ReleaseDC(hwnd, hdc);
    }
© www.soinside.com 2019 - 2024. All rights reserved.