C++ 将鼠标光标更改为等待光标,然后启动工作线程,并在线程完成时更改为返回

C++ 将鼠标光标更改为等待光标,然后启动工作线程,并在线程完成时更改为返回,c++,mfc,mouse-cursor,C++,Mfc,Mouse Cursor,在旧的MFC应用程序中,我必须执行到另一台计算机的网络连接请求,如果计算机名不正确,则在请求超时之前可能需要几秒钟。因此,我启动了一个工作线程来进行初始连接,以便用户界面仍然响应 网络连接请求由用户选择菜单项触发,该菜单项将弹出一个对话框来填写目标计算机信息。当用户单击对话框上的“确定”按钮时,将使用工作线程处理网络连接请求 我想做的是将鼠标光标更改为等待指示器,然后在实际建立连接或尝试超时后删除等待指示器 我遇到的是,鼠标光标仍然是指针,而鼠标光标没有变为等待指示器 我最初的想法是,我可以使用

在旧的MFC应用程序中,我必须执行到另一台计算机的网络连接请求,如果计算机名不正确,则在请求超时之前可能需要几秒钟。因此,我启动了一个工作线程来进行初始连接,以便用户界面仍然响应

网络连接请求由用户选择菜单项触发,该菜单项将弹出一个对话框来填写目标计算机信息。当用户单击对话框上的“确定”按钮时,将使用工作线程处理网络连接请求

我想做的是将鼠标光标更改为等待指示器,然后在实际建立连接或尝试超时后删除等待指示器

我遇到的是,鼠标光标仍然是指针,而鼠标光标没有变为等待指示器

我最初的想法是,我可以使用
BeginWaitCursor()
函数更改鼠标光标。然而,我看不出这有什么影响

进一步阅读表明,我还需要重写
CScrollView
类的
afx_msg BOOL OnSetCursor(CWnd*pWnd,UINT nHitTest,UINT message)
方法,但是我似乎找不到任何有用的东西来描述我在该方法中需要做什么。调用
OnSetCursor()
方法似乎有多种原因,只要移动鼠标就会触发该方法中的断点

看起来,在
OnSetCursor()
方法中,我应该检测当前应用程序状态,并基于该状态,使用
SetCursor()
函数设置一种可能的鼠标光标样式,该样式以前已使用
LoadCursor()
加载。见识

但是,我不确定这是否是实际操作的方式,以及
OnSetCursor()
提供的参数的实际含义和使用方法


在上面两个SO公告的第二个公告中,似乎使用了一个全局变量来确定是否调用了默认的
CView::OnSetCursor()
方法。

首先声明以下全局变量:

BOOL bConnecting = FALSE; // TRUE if connecting, set by your application
HCURSOR hOldCursor = NULL; // Cursor backup
当需要显示沙漏光标调用时:

bConnecting = TRUE;
hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
一旦连接建立(或失败),调用:

您还需要覆盖
OnSetCursor()

并将
ON\u WM\u SETCURSOR()
指令添加到
CMainFrame
的消息映射中,以启用
OnSetCursor()
消息处理程序

“主框架”是MFC应用程序中所有窗口的父窗口,这就是为什么我们为其覆盖
OnSetCursor()
。它会影响所有其他窗口

在MFC环境中,您还可以使用
BeginWaitCursor()
RestoreWaitCursor()
EndWaitCursor()
函数。这些是
CCmdTarget
方法,可以使用
AfxGetApp()
以及任何
CWnd
派生类进行访问


请注意,在具有UI线程和工作线程的多线程环境中使用全局变量,这取决于线程如何使用和访问全局变量,您可以创建竞争条件。

@Constantine的OnSetCursor实现对我不起作用(VC++2013;Win 10)-启动线程后,等待光标仍返回箭头。但是我用下面的代码解决了我的问题

BOOL CMainFrame::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (bConnecting) {
          SetCursor(LoadCursor(NULL, IDC_WAIT));
          return TRUE; // Prevent MFC changing the cursor
    }
    // else call the default
    return CFrameWndEx::OnSetCursor(pWnd, nHitTest, message);
}

请注意,如果您希望在视图上悬停时显示等待光标,则所有打开的对话框或视图都应具有OnSetCursor。

您是否尝试过?@1201programalam我刚刚尝试过,我发现它确实将鼠标光标更改为等待指示。但是,有一个局部作用域要求,这意味着只要菜单处理程序启动工作线程,然后返回,
CWaitCursor
对象就会超出作用域。我发现,如果我使用
BeginWaitCursor()
,然后在启动工作线程后进入睡眠状态,冻结UI,我也会看到鼠标光标等待指示。因此,除了
BeginWaitCursor()
之外,我还需要做一些事情来保持光标作为等待光标。您可以动态创建
CWaitCursor
对象,但由于主消息线程一直在运行,因此可能会替换光标。当您尝试连接网络时,如何处理用户选择其他菜单选项(或其他交互)?您可能需要使用“连接到服务器”应用程序模式对话框。@1201程序在建立连接并启动之前,大多数菜单项将被禁用并显示为灰色。在连接存在之前,用户唯一能做的就是退出。什么是“连接到服务器”应用程序模式对话框?此应用程序使用UDP“连接”到目标计算机,这实际上涉及通知目标服务器需要创建新的通信会话,并提供使用新会话所需的令牌。所有通信都是通过UDP而不是TCP进行的。您可以创建等待光标,创建一个对话框或窗口,其中包含某种类型的应用程序模式消息(该消息保留应用程序其余部分的输入),还可以使用“取消”按钮。一旦建立连接且线程终止,请关闭对话框。设置等待游标(无论是通过BeginWaitCursor()还是通过CWaitCursor)都是不够的,因为您正在处理消息队列。当消息队列运行时,鼠标光标下方的窗口将获得一个WM_SETCURSOR事件,用于鼠标移动,使该窗口有机会控制其上方的光标。如果窗口的线程(通常是主线程)正忙,设置一次等待光标将使该光标保持可见,直到重置它或WM_SETCURSOR被处理。@Nick:Exactl
BOOL CMainFrame::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (bConnecting) return TRUE; // Prevent MFC changing the cursor

    // else call the default
    return CFrameWndEx::OnSetCursor(pWnd, nHitTest, message);
}
BOOL CMainFrame::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
    if (bConnecting) {
          SetCursor(LoadCursor(NULL, IDC_WAIT));
          return TRUE; // Prevent MFC changing the cursor
    }
    // else call the default
    return CFrameWndEx::OnSetCursor(pWnd, nHitTest, message);
}