在码头下的窗口opengl游戏中的双光标

时间:2011-07-06 08:45:16

标签: macos cocoa opengl cursor dock

我在opengl中创建了游戏,我在窗口模式下遇到了双光标(我和系统)的问题。 我隐藏了系统光标,只在游戏中使用我的光标。

当窗口处于停靠状态时,我将光标移到停靠栏上(光标仍在窗口内),显示系统光标。从这一刻起,我有了双光标(我和系统)。

我尝试了三种解决方案:

  1. 当光标结束时和光标停靠时使用事件,但我没有找到这样的事件:(
  2. 系统光标取消隐藏或隐藏时使用事件,但我也没有找到此类事件:(
  3. 获取有关隐藏光标计数的信息。当我制作“CGDisplayHideCursor”时,隐藏光标计数会减少。当光标取消隐藏在Dock上时我不知道它,因为我没有任何事件,但我可以检查我的计时器是否应该隐藏光标,所以我可以隐藏它,但这样我会有很多次隐藏光标,所以我不知道光标隐藏计数,我没有正确取消隐藏:(
  4. 也许这应该以完全不同的方式解决。

2 个答案:

答案 0 :(得分:0)

你可以尝试以下任何一种方法:

  • 不要在窗口模式下显示游戏光标(虽然这可能不适合您的游戏)
  • 让游戏窗口位于最顶端,因此它位于停靠栏上方(不确定是否可以在Mac上)
  • 不允许您的游戏窗口在停靠栏下渲染任何内容,因此用户无需点击那里(或者不允许您的游戏窗口首先位于停靠栏下)。
  • 使用计时器轮询光标屏幕坐标以确定光标是否在对接

这不是一个严格的编程问题,而是一个可用性问题。您应该决定用户希望做什么并实现它。我相信可以不在窗口模式下显示游戏光标(除非您正在编写一个需要许多不同游标的策略游戏)。

答案 1 :(得分:0)

不是使用CGDisplayHideCursor,而是使用神秘的不可读的隐藏计数,解决方案是使用透明光标设置覆盖整个窗口的光标矩形。这非常强大 - 它可以在鼠标位于窗口内时可靠地隐藏光标并在其他所有时间显示它。

我最终通过查看Simple DirectMedia Layer(SDL)2源代码来解决这个问题 - 这是一个从那里提取的工作最小的例子。

覆盖NSView子类实现中的resetCursorRects:

static NSCursor* invisibleCursor()
{
    static NSCursor *invisibleCursor = NULL;
    if (!invisibleCursor) {
        /* RAW 16x16 transparent GIF */
        static unsigned char cursorBytes[] = {
            0x47, 0x49, 0x46, 0x38, 0x37, 0x61, 0x10, 0x00, 0x10, 0x00, 0x80,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04,
            0x01, 0x00, 0x00, 0x01, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x10,
            0x00, 0x10, 0x00, 0x00, 0x02, 0x0E, 0x8C, 0x8F, 0xA9, 0xCB, 0xED,
            0x0F, 0xA3, 0x9C, 0xB4, 0xDA, 0x8B, 0xB3, 0x3E, 0x05, 0x00, 0x3B
        };

        NSData *cursorData = [NSData dataWithBytesNoCopy:&cursorBytes[0]
                                                  length:sizeof(cursorBytes)
                                            freeWhenDone:NO];
        NSImage *cursorImage = [[[NSImage alloc] initWithData:cursorData] autorelease];
        invisibleCursor = [[NSCursor alloc] initWithImage:cursorImage
                                                  hotSpot:NSZeroPoint];
    }

    return invisibleCursor;
}

- (void)resetCursorRects
{
    [super resetCursorRects];

    [self addCursorRect:[self bounds] cursor:invisibleCursor()];
}