使用 Visual C++ 在 MFC 中更改窗口的鼠标指针

本文介绍如何使用 Visual C++ 在 MFC 中更改窗口的鼠标指针。 本文中的信息仅适用于非托管 Visual C++ 代码。

原始产品版本: Visual C++
原始 KB 编号: 131991

摘要

在基于 Windows 的应用程序中,始终基于窗口类创建窗口。 窗口类基于窗口标识多个特征,包括默认鼠标指针 (光标) 。 在某些情况下,应用程序可能需要更改与它创建的某些窗口关联的指针。 本文介绍 MFC 应用程序可用于在不同时间显示不同指针的三种方法。

MFC 应用程序显示不同指针的情况

在某些情况下,你可能希望 MFC 应用程序在不同时间显示不同的指针:

  • 当默认指针不是特定应用程序的良好用户界面对象时。 例如,I 型指针比记事本中文本编辑器窗口的箭头更合适。 这可能涉及更改整个应用程序运行的指针。
  • 当应用程序执行长时间的操作(如磁盘 I/O)时,沙漏指针比箭头更合适。 通过更改指向沙漏的指针,可以向用户提供良好的视觉反馈。 这可能涉及在有限时间内更改指针。

更改窗口中鼠标指针的三种方法

下面是应用程序在窗口中更改鼠标指针的三种方法:

  • 方法 1:重写 CWnd::OnSetCursor() 函数。 调用 Windows API SetCursor() 函数以更改指针。
  • 方法 2:使用所需的鼠标指针注册自己的窗口类,重写 CWnd::PreCreateWindow() 函数,并使用新注册的窗口类创建窗口。
  • 方法 3:若要显示标准沙漏指针,应用程序可以调用 CCmdTarget::BeginWaitCursor(),它显示沙漏,并调用 CmdTarget::EndWaitCursor() 还原返回到默认指针。 此方案仅适用于单个消息的持续时间。 如果在调用 EndWaitCursor 之前移动了鼠标,Windows 会将一 WM_SETCURSOR 条消息发送到指针下方的窗口。 此消息的默认处理会重置指向默认类型的指针(向 类注册的类型),因此你需要重写 CWnd::OnSetCursor() 该窗口,并将指针重置回沙漏。

下面的代码示例按示例演示如何使用这三种方法 CView 更改派生类窗口的鼠标指针。

m_ChangeCursor 是 类的成员 CMyView 变量,类型为 BOOL。 它指示是否需要显示其他指针类型。

方法 1 的代码

通过重写CWnd::OnSetCursor()函数更改CMyView对象的鼠标指针。 使用类向导为 Windows 消息WM_SETCURSOR建立消息映射函数CMyView::OnSetCursor(),并提供函数的正文,如下所示:

BOOL CMyView::OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message)
{
    if (m_ChangeCursor)
    {
        ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
        return TRUE;
    }
    return CView::OnSetCursor(pWnd, nHitTest, message);
}

方法 2 的代码

使用 或 AfxRegisterWndClass() 函数注册自己的包含所需鼠标指针的AfxRegisterClass()窗口类。 然后基于已注册的窗口类创建视图窗口。 有关在 MFC 中注册窗口类的详细信息,请参阅 MFC 技术说明 1 中的 窗口类注册

BOOL CMyView::PreCreateWindow(CREATESTRUCT &cs)
{
    cs.lpszClass = AfxRegisterWndClass(
        CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW, // use any window styles
        AfxGetApp()->LoadStandardCursor(IDC_WAIT),
        (HBRUSH)(COLOR_WINDOW + 1)); // background brush
    return CView::PreCreateWindow(cs)
}

方法 3 的代码

BeginWaitCursor()调用 和 EndWaitCursor() 函数以更改鼠标指针。

注意

CWinApp::DoWaitCursor(1)CWinApp::DoWaitCursor(-1) 分别与 BeginWaitCursor()EndWaitCursor()类似。

void CMyView::PerformLengthyOperation()
{
    BeginWaitCursor(); // or AfxGetApp()->DoWaitCursor(1)
    //...
    EndWaitCursor(); // or AfxGetApp()->DoWaitCursor(-1)
}

如果对 BeginWaitCursor()EndWaitCursor() 的调用不在同一处理程序中,则必须 OnSetCursor 重写,如下所示:

BOOL CMyView::OnSetCursor(CWnd *pWnd, UINT nHitTest, UINT message)
{
    if (m_ChangeCursor)
    {
        RestoreWaitCursor();
        return TRUE;
    }
    return CView::OnSetCursor(pWnd, nHitTest, message);
}

在此示例中,在调用 BeginWaitCursor()之前将 设置为 m_ChangeCursorTRUE,并在调用 EndWaitCursor()后将其重新设置为 FALSE