Recently, I need to capture the mouse cursor in my homebrew screen capture application, so my search sent me to StackOverflow’s Capture screen shot with mouse cursor. Out of curiosity, I ran Deleaker on it and it finds 2 HBITMAP leaks with every capture. My application captures mouse cursor 30 times per second, so the number of resource leaks are huge and can crash the application if running for more than 3 minutes.
CURSORINFO cursor = { sizeof(cursor) }; ::GetCursorInfo(&cursor); if (cursor.flags == CURSOR_SHOWING) { RECT rcWnd; ::GetWindowRect(hwnd, &rcWnd); ICONINFOEXW info = { sizeof(info) }; ::GetIconInfoExW(cursor.hCursor, &info); const int x = cursor.ptScreenPos.x - rcWnd.left - rc.left - info.xHotspot; const int y = cursor.ptScreenPos.y - rcWnd.top - rc.top - info.yHotspot; BITMAP bmpCursor = {0}; ::GetObject(info.hbmColor, sizeof(bmpCursor), &bmpCursor); ::DrawIconEx(hdcMem, x, y, cursor.hCursor, bmpCursor.bmWidth, bmpCursor.bmHeight, 0, NULL, DI_NORMAL); }
MSDN of GetIconInfoExW specifically notes GetIconInfoEx creates bitmaps for the hbmMask and hbmColor or members of ICONINFOEX. The calling application must manage these bitmaps and delete them when they are no longer necessary.
typedef struct _ICONINFOEXW { DWORD cbSize; BOOL fIcon; DWORD xHotspot; DWORD yHotspot; HBITMAP hbmMask; HBITMAP hbmColor; WORD wResID; WCHAR szModName[MAX_PATH]; WCHAR szResName[MAX_PATH]; } ICONINFOEXW, *PICONINFOEXW;
So DeleteObject have to be called on these 2 members, as suggested by Deleaker.
DeleteObject(info.hbmMask); DeleteObject(info.hbmColor);
Leave a Reply