How to draw mouse cursor on the given image

tonyye 21 Reputation points
2022-11-19T14:41:21.517+00:00

I used winrt to capture desktop, and I need to process the captured image, then draw the mouse curson on the processed image(rgb32),
I used to opencv to draw it , but it would cause the result image lose black pixel when the cursor only has mask image.

HICON icon = nullptr;  
	ICONINFO ii;  
  
	icon = CopyIcon(cursorInfo.hCursor);  
	if (!icon) {  
		LOG(ERROR) << "COPY ICON FAILED";  
		return;  
	}  
  
	HBITMAP cursorBitmap = IconToBitmap(icon);  
	if (cursorBitmap == nullptr)  
	{  
		LOG(ERROR) << "convert icon to bitmap failed";  
		return;  
	}  
	  
	cv::Mat cursorMat;  
	if (!HBitmap2Mat(cursorBitmap, cursorMat))  
	{  
		LOG(ERROR) << "bitmap 2 mat failed";  
		return;  
	}  
  
	cv::Point pt(std::abs(cursorInfo.ptScreenPos.x), std::abs(cursorInfo.ptScreenPos.y));  
  
	int cursorWidth = (pt.x + cursorMat.cols) > source.cols ? (source.cols - pt.x) : cursorMat.cols;  
	int cursorHeight = (pt.y + cursorMat.rows) > source.rows ? (source.rows - pt.y) : cursorMat.rows;  
	cv::Mat roi = source(cv::Rect(pt.x,pt.y, cursorWidth, cursorHeight));  
	cv::Mat cursorRoi = cursorMat(cv::Rect(0, 0, cursorWidth, cursorHeight));  
	  
	for (int i = 0; i < cursorRoi.rows; ++i)  
	{  
		for (int j = 0; j < cursorRoi.cols; ++j)  
		{  
			cv::Vec4b& rgba = cursorRoi.at<cv::Vec4b>(i, j);  
			if (rgba[0]!=0x00 ) {				  
				roi.at<cv::Vec4b>(i, j) = cursorRoi.at<cv::Vec4b>(i, j);  
			}  
			else {  
				  
			}  
		}  
	}  
Windows development Windows API - Win32
{count} votes

3 answers

Sort by: Most helpful
  1. Castorix31 90,521 Reputation points
    2022-11-19T15:01:46.277+00:00

    A way is with GetCursorInfo-DrawIcon(Ex)


  2. ADITI 1 Reputation point
    2022-11-19T15:34:14.663+00:00

    We can draw a mouse cursor in a image by just taking pencil and drawing sheet and eraser and start making the mouse cursor in paper firstly we should do by light hand the if it is perfect the we should dark it with pencil otherwise we should eraser it and make it again perfect after that we should shade it to give a look for more better image

    0 comments No comments

  3. tonyye 21 Reputation points
    2022-11-24T08:29:29.77+00:00

    @Jeanine Zhang-MSFT

    I use the following code to draw it , and get the result image is 263826-cursor.png
    As you see , the edge of cursor should be black, but it lost.
    I use the Winrt::Capture to capture the desktop, and I found no way to get HDC.
    So I build Gdiplus::Graphics with Bitmap, not HDC.

    void Draw(unsigned char* buf, int width, int height)
    {
    Gdiplus::Bitmap bitmap(width, height, width * 4, PixelFormat32bppARGB, buf);

    Bitmap dstImg(width,height);  
    Gdiplus::Graphics gps(&dstImg);  
    gps.DrawImage(&bitmap, 0, 0);  
    
      
    CURSORINFO cursor_info = {};  
    cursor_info.cbSize = sizeof(CURSORINFO);  
    
    auto ret = ::GetCursorInfo(&cursor_info);  
    if (!ret)  
    	return;  
    
    if (!(cursor_info.flags & CURSOR_SHOWING))  
    	return;  
    
    ICONINFO icon_info;  
    ret = ::GetIconInfo(cursor_info.hCursor, &icon_info);  
    if (!ret)  
    	return;  
    
    auto cursor_x = cursor_info.ptScreenPos.x;  
    auto cursor_y = cursor_info.ptScreenPos.y;  
    
    Gdiplus::SolidBrush brush(Gdiplus::Color(255, 0, 0));;  
    gps.FillEllipse(&brush, cursor_x, cursor_y, 32, 32);  
    
    HICON icon = CopyIcon(cursor_info.hCursor);  
    
     HDC hmDC = gps.GetHDC();  
    ::DrawIconEx(hmDC, cursor_x, cursor_y, icon, 0,0, 0, NULL, DI_NORMAL);  
    gps.ReleaseHDC(hmDC);  
    
    BITMAPINFOHEADER   bi;  
    bi.biSize = sizeof(BITMAPINFOHEADER);  
    bi.biWidth = width;  
    bi.biHeight = height * (-1);  
    bi.biPlanes = 1;  
    bi.biBitCount = 32;//should get from system color bits  
    bi.biCompression = BI_RGB;  
    bi.biSizeImage = 0;  
    bi.biXPelsPerMeter = 0;  
    bi.biYPelsPerMeter = 0;  
    bi.biClrUsed = 0;  
    bi.biClrImportant = 0;  
    
    
    CLSID pngClsid;  
    GetEncoderClsid(L"image/png", &pngClsid);  
    
    dstImg.Save(L"D:\\XXXXXEEEffff.png", &pngClsid, NULL);  
    

    }


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.