/// <devdoc> /// Draws this image to a graphics object. The drawing command originates on the graphics /// object, but a graphics object generally has no idea how to render a given image. So, /// it passes the call to the actual image. This version crops the image to the given /// dimensions and allows the user to specify a rectangle within the image to draw. /// </devdoc> // This method is way more powerful than what we expose, but I'll leave it in place. private void DrawImageCore(Graphics graphics, Rectangle imageRect, Rectangle targetRect, bool stretch) { // Support GDI+ Translate method targetRect.X += (int)graphics.Transform.OffsetX; targetRect.Y += (int)graphics.Transform.OffsetY; int rop = 0xcc0020; // RasterOp.SOURCE.GetRop(); IntPtr dc = graphics.GetHdc(); try { // want finally clause to release dc int imageX = 0; int imageY = 0; int imageWidth; int imageHeight; int targetX = 0; int targetY = 0; int targetWidth = 0; int targetHeight = 0; Size cursorSize = Size; // compute the dimensions of the icon, if needed // if (!imageRect.IsEmpty) { imageX = imageRect.X; imageY = imageRect.Y; imageWidth = imageRect.Width; imageHeight = imageRect.Height; } else { imageWidth = cursorSize.Width; imageHeight = cursorSize.Height; } if (!targetRect.IsEmpty) { targetX = targetRect.X; targetY = targetRect.Y; targetWidth = targetRect.Width; targetHeight = targetRect.Height; } else { targetWidth = cursorSize.Width; targetHeight = cursorSize.Height; } int drawWidth, drawHeight; int clipWidth, clipHeight; if (stretch) { // Short circuit the simple case of blasting an icon to the // screen // if (targetWidth == imageWidth && targetHeight == imageHeight && imageX == 0 && imageY == 0 && rop == NativeMethods.SRCCOPY && imageWidth == cursorSize.Width && imageHeight == cursorSize.Height) { SafeNativeMethods.DrawIcon(new HandleRef(graphics, dc), targetX, targetY, new HandleRef(this, handle)); return; } drawWidth = cursorSize.Width * targetWidth / imageWidth; drawHeight = cursorSize.Height * targetHeight / imageHeight; clipWidth = targetWidth; clipHeight = targetHeight; } else { // Short circuit the simple case of blasting an icon to the // screen // if (imageX == 0 && imageY == 0 && rop == NativeMethods.SRCCOPY && cursorSize.Width <= targetWidth && cursorSize.Height <= targetHeight && cursorSize.Width == imageWidth && cursorSize.Height == imageHeight) { SafeNativeMethods.DrawIcon(new HandleRef(graphics, dc), targetX, targetY, new HandleRef(this, handle)); return; } drawWidth = cursorSize.Width; drawHeight = cursorSize.Height; clipWidth = targetWidth < imageWidth ? targetWidth : imageWidth; clipHeight = targetHeight < imageHeight ? targetHeight : imageHeight; } if (rop == NativeMethods.SRCCOPY) { // The ROP is SRCCOPY, so we can be simple here and take // advantage of clipping regions. Drawing the cursor // is merely a matter of offsetting and clipping. // SafeNativeMethods.IntersectClipRect(new HandleRef(this, Handle), targetX, targetY, targetX + clipWidth, targetY + clipHeight); SafeNativeMethods.DrawIconEx(new HandleRef(graphics, dc), targetX - imageX, targetY - imageY, new HandleRef(this, handle), drawWidth, drawHeight, 0, NativeMethods.NullHandleRef, NativeMethods.DI_NORMAL); // Let GDI+ restore clipping return; } Debug.Fail("Cursor.Draw does not support raster ops. How did you even pass one in?"); } finally { graphics.ReleaseHdcInternal(dc); } }