光标(cursor)是用来显示你鼠标或者其它指示设备的小图像。许多应用都通过不同的光标来向用户展示程序的不同状态。虽然这不是必须的,但是它会让应用程序看起来更加友好。

Windows 默认提供了一些光标图像,它们被称为系统光标(system cursor)。包括箭头光标、手形光标、I形光标、沙漏光标(现在是旋转的圆圈)等等。本节内容主要是讲解如何使用系统光标。对于更高级的用法,如自定义光标等内容,可以查看 Cursors。

在前面 如何创建窗口 的章节里介绍过,程序可以在 WNDCLASS 或 WNDCLASSEX 结构体中的 hCursor 成员指定使用哪种光标,如果不指定默认则是箭头光标。当鼠标移到窗口时,窗口会收到 WM_SETCURSOR 消息,有两种逻辑供你选择:

  • 应用程序设置光标,并在窗口处理函数中返回 TRUE。

  • 应用程序忽略该消息,直接调用 DefWindowProc 处理。

对于光标设置,程序中需要执行下面的步骤:

  1. 调用 LoadCursor 函数从内存中加载光标。这个函数会返回光标句柄。

  2. 调用 SetCursor 设置程序光标,参数为 LoadCursor 返回的光标句柄。

如果不做任何操作,执行默认的 DefWindowProc 函数,则会执行下面的逻辑:

  1. 如果窗口有一个父窗口,将 WM_SETCURSOR 消息发送给它处理。

  2. 否则如果窗口在窗口类中指定了光标,则设置这个光标。

  3. 如果窗口类没有设置光标,则将光标设置为箭头。

LoadCursor 函数能加载自定义光标资源,也可以加载系统光标,下面的代码展示如何设置系统光标。

hCursor = LoadCursor(NULL, cursor);
SetCursor(hCursor);

如果你改变这个光标,光标将在下次移动的时候重置,除非你拦截 WM_SETCURSOR 消息再次设置。下面代码展示如果处理 WM_SETCURSOR 消息:

case WM_SETCURSOR:
    if (LOWORD(lParam) == HTCLIENT)
    {
        SetCursor(hCursor);
        return TRUE;
    }
    break;

这段代码首先检测了 lParam 参数的低16位,如果 LOWORD(lParam) 等于 HTCLIENT,它的含义是光标在窗口的客户区,否则代表光标在非客户区。正常情况下,应用程序仅仅负责客户区光标的设置工作,而在非客户区应该交由操作系统来负责。

求关注