You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Windows的AND/XOR掩码位图转换为QCursor?

如何将Windows的AND/XOR掩码光标位图转换为QCursor?

我正在实现远程桌面协议,需要在本地客户端显示远程桌面的光标位图,涉及单色位图设置鼠标指针类型。因为需要跨平台功能,所以选用Qt的QCursor。

Win32平台实现(已成功)

在Windows平台上,我已经能用Win32 API设置带掩码的光标并达到预期效果,核心代码示例如下:

HINSTANCE inst;
HCURSOR cursor = CreateCursor(inst,
                              pCursorData->xHotspot,
                              pCursorData->yHotspot,
                              pCursorData->width,
                              pCursorData->height,
                              (void*)pCursorData->pixelData,
                              (void*)(pCursorData->pixelData + size));

SetCursor(cursor);

初次Qt尝试(效果不符)

之后我尝试用QImage转换单色位图并配置QCursor,但结果和原生Win32 API的效果不同:

// `height` 包含两个位图(AND和XOR)
int size =  pCursorData->width * pCursorData->height / 2 / 8;
QImage     image(pCursorData->pixelData,          pCursorData->width,pCursorData->height / 2,QImage::Format_Mono);
QImage maskImage((pCursorData->pixelData + size), pCursorData->width,pCursorData->height / 2,QImage::Format_Mono);

pixmap = QPixmap::fromImage(image);
pixmap.setMask(maskBitmap);
QCursor cursor(pixmap, pCursorData->xHotspot, pCursorData->yHotspot);

renderWidget->setCursor(cursor);

修改后的代码尝试(仍未成功)

查阅文档后我调整了代码,根据Windows和QCursor的位图位组合规则做了映射,但还是没成功:

/**
 * 单色位图包含AND位图和XOR位图,1位对应1像素
 *
 * Windows 位组合规则:
 * AND位图  XOR位图  显示效果
 *   0          0           黑色
 *   0          1           白色
 *   1          0           屏幕原色
 *   1          1           反色屏幕
 *
 * QCursor 位组合规则:
 * 光标位图(B)和掩码(M)的位组合规则如下:
 *  B=1 且 M=1 显示黑色。
 *  B=0 且 M=1 显示白色。
 *  B=0 且 M=0 显示透明。
 *  B=1 且 M=0 在Windows下显示XOR结果,其他平台结果未定义。
 * 使用Qt全局颜色Qt::color0绘制位图中的0像素,Qt::color1绘制1像素。
 */

int pitch = pCursorData->dataLen / pCursorData->height;
bool andPixel;
bool xorPixel;
// `height` 包含两个位图(AND和XOR)
for(int y=0; y < pCursorData->height / 2; y++)
{
    for(int x=0; x < pCursorData->width; x++)
    {
        quint8 bitMask = 0x80 >> (x % 8);
        quint8 uint8_x = x / 8; // 宽度是位尺寸,转换为字节索引

        andPixel = pCursorData->pixelData[y * pitch + uint8_x] & bitMask;
        xorPixel = pCursorData->pixelData[(y + pCursorData->height / 2) * pitch + uint8_x] & bitMask;

        if (!andPixel && !xorPixel) {
            image.setPixelColor(x, y, QColor(Qt::color1));
            maskImage.setPixelColor(x, y, QColor(Qt::color1));
        } else if (!andPixel && xorPixel) {
            image.setPixelColor(x, y, QColor(Qt::color0));
            maskImage.setPixelColor(x, y, QColor(Qt::color1));
        } else if (andPixel && !xorPixel) {
            image.setPixelColor(x, y, QColor(Qt::color0));
            maskImage.setPixelColor(x, y, QColor(Qt::color0));
        } else if (andPixel && xorPixel) {
            image.setPixelColor(x, y, QColor(Qt::color1));
            maskImage.setPixelColor(x, y, QColor(Qt::color0));
        }
    }
}

pixmap = QPixmap::fromImage(image);
pixmap.setMask(maskBitmap);
QCursor cursor(pixmap, pCursorData->xHotspot, pCursorData->yHotspot);

renderWidget->setCursor(cursor);

我研究过QCursor的Qt源代码,但里面有大量位运算,短时间内难以完全理解。现在想请教:如何正确将Windows的AND掩码和XOR掩码位图转换为QCursor?


内容的提问来源于stack exchange,提问作者gao.xiangyang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 00:03:12