//dirtyRect是绝对坐标(在多屏的情况下) public virtual void SetHBitmap(IntPtr hBitmap, Rectangle newWindowBounds, Point drawAt, Rectangle dirtyRect,byte opacity) { // IntPtr screenDc = Win32.GDI32.GetDC(IntPtr.Zero); IntPtr memDc = Win32.GDI32.CreateCompatibleDC(IntPtr.Zero); IntPtr oldBitmap = IntPtr.Zero; try { oldBitmap = Win32.GDI32.SelectObject(memDc, hBitmap); var winSize = new Native.Size(newWindowBounds.Width, newWindowBounds.Height); var winPos = new Native.Point(newWindowBounds.X, newWindowBounds.Y); var drawBmpAt = new Native.Point(drawAt.X, drawAt.Y); var blend = new Native.BLENDFUNCTION { BlendOp = GDI32.AC_SRC_OVER, BlendFlags = 0, SourceConstantAlpha = opacity, AlphaFormat = GDI32.AC_SRC_ALPHA }; var updateInfo = new Native.UPDATELAYEREDWINDOWINFO(); updateInfo.cbSize = (uint) Marshal.SizeOf(typeof (Native.UPDATELAYEREDWINDOWINFO)); updateInfo.dwFlags = GDI32.ULW_ALPHA; updateInfo.hdcDst = IntPtr.Zero;//Native.GetDC(IntPtr.Zero);//IntPtr.Zero; //ScreenDC updateInfo.hdcSrc = memDc; // dirtyRect.X -= _bounds.X; // dirtyRect.Y -= _bounds.Y; //dirtyRect.Offset(-_bounds.X, -_bounds.Y); var dirRect = new GDI32.RECT(dirtyRect.X,dirtyRect.Y,dirtyRect.Right,dirtyRect.Bottom); unsafe { updateInfo.pblend = &blend; updateInfo.pptDst = &winPos; updateInfo.psize = &winSize; updateInfo.pptSrc = &drawBmpAt; updateInfo.prcDirty = &dirRect; } Native.UpdateLayeredWindowIndirect(Handle, ref updateInfo); // Debug.Assert(Native.GetLastError() == 0); //Native.UpdateLayeredWindow(Handle, IntPtr.Zero, ref topPos, ref size, memDc, ref pointSource, 0, ref blend, GDI32.ULW_ALPHA); } finally { //GDI32.ReleaseDC(IntPtr.Zero, screenDc); if (hBitmap != IntPtr.Zero) { GDI32.SelectObject(memDc, oldBitmap); //Windows.DeleteObject(hBitmap); // The documentation says that we have to use the Windows.DeleteObject... but since there is no such method I use the normal DeleteObject from Win32 GDI and it's working fine without any resource leak. //Win32.DeleteObject(hBitmap); } GDI32.DeleteDC(memDc); } }