I'm trying to display a Bitmap
to the screen using GetDesktopWindow()
to get a handle of the desktop window, and StretchBlt
to copy an image to it.
However, this does not work. It shows either a completely blank image, or a completely white image, depending if I use SRCCOPY
or other constants.
Here's the code:
[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);
}
To call it I then use:
DrawBitmapToScreen((Bitmap)pictureBox1.Image, TernaryRasterOperations.SRCCOPY);
What have I done wrong?
EDIT: I need that the image gets deleted from the screen if you refresh Windows Explorer or move a window on it
I found a solution that not uses StretchBlt()
or BitBlt()
(outside of the underlying code of the Graphics
class).
The only unmanaged code is GetDC()
, GetDesktopWindow()
and ReleaseDC()
.
Here's the code
[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);
}
User contributions licensed under CC BY-SA 3.0