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



我正在尝试使用GetDesktopWindow()向屏幕显示Bitmap以获取桌面窗口的句柄,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资源管理器或在其上移动窗口,我需要从屏幕上删除图像

我找到了一个不使用StretchBlt()BitBlt()的解决方案(在Graphics类的底层代码之外(。 唯一的非托管代码是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);
}

最新更新