我想在Windows中获取光标图标。 我认为我使用的语言在这里不是很重要,所以我只是用我尝试使用的WinAPI函数编写伪代码:
c = CURSORINFO.new(20, 1, 1, POINT.new(1,1)); GetCursorInfo(c); #provides correctly filled structure with hCursor DrawIcon(GetWindowDC(GetForegroundWindow()), 1, 1, c.hCursor);
所以这部分工作正常,它在活动窗口上绘制当前光标。 但那不是我想要的。 我想获得一个像素数组,所以我应该把它绘制在内存中。
我试图这样做:
hdc = CreateCompatibleDC(GetDC(0)); #returns non-zero int canvas = CreateCompatibleBitmap(hdc, 256, 256); #returns non-zero int too c = CURSORINFO.new(20, 1, 1, POINT.new(1,1)); GetCursorInfo(c); DrawIcon(hdc, 1, 1, c.hCursor); #returns 1 GetPixel(hdc, 1, 1); #returns -1
为什么不GetPixel()返回COLORREF? 我错过了什么?
我对WinAPI不是很有经验,所以我可能会犯一些愚蠢的错误。
您必须选择您在设备上下文中创建的位图。 如果没有, GetPixel
函数将返回CLR_INVALID
(0xFFFFFFFF):
必须在设备上下文中选择一个位图,否则,将在所有像素上返回
CLR_INVALID
。
此外,你所显示的伪代码是严重泄漏对象。 每当你调用GetDC
,当你完成使用时,你必须调用ReleaseDC
。 而且每当你创建一个GDI对象时,你必须在完成使用后才能销毁它。
最后,你似乎假设原点的坐标 – 即左上角的点 – 是(1,1)。 他们实际上是(0,0)。
这里是我会写的代码(为简洁起见省略了错误检查):
// Get your device contexts. HDC hdcScreen = GetDC(NULL); HDC hdcMem = CreateCompatibleDC(hdcScreen); // Create the bitmap to use as a canvas. HBITMAP hbmCanvas = CreateCompatibleBitmap(hdcScreen, 256, 256); // Select the bitmap into the device context. HGDIOBJ hbmOld = SelectObject(hdcMem, hbmCanvas); // Get information about the global cursor. CURSORINFO ci; ci.cbSize = sizeof(ci); GetCursorInfo(&ci); // Draw the cursor into the canvas. DrawIcon(hdcMem, 0, 0, ci.hCursor); // Get the color of the pixel you're interested in. COLORREF clr = GetPixel(hdcMem, 0, 0); // Clean up after yourself. SelectObject(hdcMem, hbmOld); DeleteObject(hbmCanvas); DeleteDC(hdcMem); ReleaseDC(hdcScreen);
但最后一个警告 – DrawIcon
函数 可能无法按照您的预期工作。 它仅限于以默认大小绘制图标或光标。 在大多数系统上,这将是32×32。 从文档:
DrawIcon
使用图标的系统度量值指定的宽度和高度绘制图标或光标; 有关更多信息,请参阅GetSystemMetrics
。
相反,你可能想使用DrawIconEx
函数 。 下面的代码将以资源的实际大小绘制游标:
DrawIconEx(hdcMem, 0, 0, ci.hCursor, 0, 0, 0, NULL, DI_NORMAL);