没错,这是 Windows 应用程序中相当常见的鼠标光标样式。令人费解的是,它并未作为标准光标之一包含在内,这使得应用程序开发人员的工作更加困难。
cmets 中建议您可以自己在 Paint 中创建此光标(或下载其他人创建的光标),然后将其作为资源包含在您的应用程序二进制文件中,但这有一些非常明显的缺点。它不仅使您的二进制文件膨胀,而且还意味着您的光标样式本质上是硬编码。默认箭头鼠标光标甚至在 Windows 版本中发生了多次更改,因此您需要维护和在不同版本的“翻转”光标之间动态选择,只是为了与默认光标兼容,更不用说自定义的用户了他们的光标甚至选择了不同的内置主题(如“反转”)。因此,我强烈建议不要使用这种方法。
正确的解决方案是简单地以编程方式翻转用户当前的箭头光标。这可确保翻转的光标与用户的首选光标样式相匹配。定义如下函数:
/// Creates a cursor that is based on the specified cursor resource (a la LoadCursor),
/// but has been flipped horizontally.
///
/// @param hInstance A handle to an instance of the module whose executable file
/// contains the cursor template.
/// @param pCursorName The name of the template cursor resource to be loaded, or
/// an integer resource created using the MAKEINTRESOURCE macro
/// identifying the cursor to be loaded.
/// @return
/// Returns a handle to the newly-created cursor.
/// @remark
/// Note that the returned cursor must be destroyed when you are finished with it
/// by calling @c DestroyIcon.
/// @remark
/// This function swallows errors, ensuring that some cursor is always returned,
/// even if it has not been flipped. The client could, if desired, modify the
/// implementation to throw exceptions or return NULL in response to errors.
HCURSOR CreateCursorFlipped(HINSTANCE hInstance, LPCTSTR pCursorName)
{
// Load the specified cursor to use as a template.
HCURSOR hCursor = LoadCursor(hInstance, pCursorName);
// Get the underlying bitmaps for the cursor template.
ICONINFO ii;
if (GetIconInfo(hCursor, &ii))
{
// Retrieve information about the bitmap.
BITMAP bm;
if (GetObject(ii.hbmMask, sizeof(bm), &bm) == sizeof(bm))
{
// Create a screen-compatible device context, and draw the cursor bitmaps into
// it, flipped across the X axis, in order to create the new cursor bitmap.
HDC hDC = CreateCompatibleDC(NULL);
if (hDC)
{
HBITMAP hBmpOriginal = (HBITMAP)SelectObject(hDC, ii.hbmMask);
StretchBlt(hDC,
bm.bmWidth - 1,
0,
-bm.bmWidth,
bm.bmHeight,
hDC,
0,
0,
bm.bmWidth,
bm.bmHeight,
SRCCOPY);
if (ii.hbmColor)
{
SelectObject(hDC, ii.hbmColor);
StretchBlt(hDC,
bm.bmWidth - 1,
0,
-bm.bmWidth,
bm.bmHeight,
hDC,
0,
0,
bm.bmWidth,
bm.bmHeight,
SRCCOPY);
}
SelectObject(hDC, hBmpOriginal);
DeleteDC(hDC);
}
// Flip the new cursor's hotspot horizontally.
ii.xHotspot = (bm.bmWidth - 1 - ii.xHotspot);
// Create a new cursor.
HCURSOR hCursorNew = CreateIconIndirect(&ii);
if (hCursorNew)
{
hCursor = hCursorNew;
}
}
// Delete the unneeded bitmaps.
DeleteObject(ii.hbmMask);
if (ii.hbmColor)
{
DeleteObject(ii.hbmColor);
}
}
return hCursor;
}
(如果您使用的是 MFC,那么您可以使用包装类和 RAII 进一步简化此代码。)
要得到问题中描述的水平翻转箭头光标,用法很简单:
CreateCursorFlipped(nullptr, IDC_ARROW);
但请记住,因为CreateCursorFlipped 实际上创建了一个new 光标(而不是仅仅加载一个系统光标),所以您必须在完成使用后销毁该光标调用DestroyIcon。