4

If i use DrawIcon when taking a screenshot, it can draw I-beam cursor with mask properly but if I want to use DrawIcon on any image then masking does not work.

This DrawIcon example works properly:

    public static Image CaptureRectangleNative(IntPtr handle, Rectangle rect, bool captureCursor = false)
    {
        if (rect.Width == 0 || rect.Height == 0)
        {
            return null;
        }

        IntPtr hdcSrc = NativeMethods.GetWindowDC(handle);
        IntPtr hdcDest = NativeMethods.CreateCompatibleDC(hdcSrc);
        IntPtr hBitmap = NativeMethods.CreateCompatibleBitmap(hdcSrc, rect.Width, rect.Height);
        IntPtr hOld = NativeMethods.SelectObject(hdcDest, hBitmap);
        NativeMethods.BitBlt(hdcDest, 0, 0, rect.Width, rect.Height, hdcSrc, rect.X, rect.Y, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);

        if (captureCursor)
        {
            Point cursorOffset = CaptureHelpers.ScreenToClient(rect.Location);

            try
            {
                using (CursorData cursorData = new CursorData())
                {
                    cursorData.DrawCursorToHandle(hdcDest, cursorOffset);
                }
            }
            catch (Exception e)
            {
                DebugHelper.WriteException(e, "Cursor capture failed.");
            }
        }

        NativeMethods.SelectObject(hdcDest, hOld);
        NativeMethods.DeleteDC(hdcDest);
        NativeMethods.ReleaseDC(handle, hdcSrc);
        Image img = Image.FromHbitmap(hBitmap);
        NativeMethods.DeleteObject(hBitmap);

        return img;
    }

    // This function inside CursorData class
    public void DrawCursorToHandle(IntPtr hdcDest, Point cursorOffset)
    {
        if (IconHandle != IntPtr.Zero)
        {
            Point drawPosition = new Point(Position.X - cursorOffset.X, Position.Y - cursorOffset.Y);
            NativeMethods.DrawIcon(hdcDest, drawPosition.X, drawPosition.Y, IconHandle);
        }
    }

But this DrawIcon example is not using a mask, so I-beam icon becomes white and in a white background it's not visible:

    public void DrawCursorToImage(Image img, Point cursorOffset)
    {
        if (IconHandle != IntPtr.Zero)
        {
            Point drawPosition = new Point(Position.X - cursorOffset.X, Position.Y - cursorOffset.Y);

            using (Graphics g = Graphics.FromImage(img))
            {
                g.DrawIcon(Icon.FromHandle(IconHandle), drawPosition.X, drawPosition.Y);
            }
        }
    }

I think if I don't use desktop hdc then DrawIcon is not using a mask. How can I fix DrawCursorToImage method so it can use cursor mask properly? By the way, i read this post: C# - Capturing the Mouse cursor image and it don't have a solution to my problem too. Thanks for reading this.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
Jaex
  • 4,204
  • 2
  • 34
  • 56

1 Answers1

0

This modification to DrawCursorToImage should make it work, but I cannot really explain why it works:

public void DrawCursorToImage(Image img, Point cursorOffset)
{
    if (IconHandle != IntPtr.Zero)
    {
        Point drawPosition = new Point(Position.X - cursorOffset.X, Position.Y - cursorOffset.Y);

        using (Graphics g = Graphics.FromImage(img))
        {
            IntPtr hdc = g.GetHdc();
            using (Graphics gfx = Graphics.FromHdc(hdc))
            {
                // For some reason it is necessary to redraw the image here
                gfx.DrawImage(img, 0, 0);
                gfx.DrawIcon(Icon.FromHandle(IconHandle), drawPosition.X, drawPosition.Y);
            }
            g.ReleaseHdc();
        }
    }
}
Xrio
  • 155
  • 2
  • 9