Нарисуйте изображение на экране, используя StretchBlt и GetDesktopWindow - PullRequest
0 голосов
/ 23 января 2020

Я пытаюсь отобразить 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);

Что я сделал не так?

РЕДАКТИРОВАТЬ: I необходимо, чтобы изображение было удалено с экрана, если вы измените sh Windows Explorer или переместите на него окно

1 Ответ

0 голосов
/ 24 января 2020

Я нашел решение, которое не использует 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);
    }
...