我们老五今天破天荒地问了我一个问题:
在一个 MFC 对话框中,点击一个按钮,要创建现程执行一个长时间的操作,于是自然而然地想到使用 BeginWaitCursor() 函数将鼠标光标形状改变为沙漏,当操作结束时,向对话框发送一个消息通知其调用 EndWaitCursor() 函数恢复光标为正常形状。
可是他说沙漏根本显示不出来。
我写了一个很小的测试程序来重现此问题,果然存在。但怎么也想不通原因在哪里,后来突然想到 MFC 默认对 WM_SETCURSOR 消息进行了处理,很可能问题出在这里,略加修改后问题解决。示例代码如下(假定对话框类名为 CTestCursorDlg):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
// 步骤: // 1、往对话框上添加一个按钮,ID 设置为 IDC_BTN_TEST // 2、向 CTestCursorDlg 类中添加成员变量 BOOL m_bBusy,并在 CTestCursorDlg 的构造函数中初始化为 FALSE // 3、写现程函数 // 4、为 IDC_BTN_TEST 按钮添加点击处理函数 // 5、重载 WindowProc() 函数 // 6、为 WM_SETCURSOR 消息添加处理函数 // 注意: // 以下代码最好在 Debug 下运行,否则 TRACE 语句不执行会大大缩短线程执行时间,有可能导致不能观察到鼠标光标的变化 DWORD WINAPI AddProc(PVOID pvParam) { int j=0; for(int i=0; i<50000; i++) { j += i; TRACE(TEXT("%d\n"), j); } PostMessage((HWND)pvParam, WM_APP + 1, 0, 0); return j; } void CTestCursorDlg::OnBtnTest() { m_bBusy = TRUE; BeginWaitCursor(); HANDLE hThread = CreateThread(NULL, 0, AddProc, (PVOID)(HWND)*this, 0, NULL); CloseHandle(hThread); } LRESULT CTestCursorDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { if(message == (WM_APP + 1)) { m_bBusy = FALSE; EndWaitCursor(); } return CDialog::WindowProc(message, wParam, lParam); } BOOL CTestCursorDlg::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { if(m_bBusy) return TRUE; return CDialog::OnSetCursor(pWnd, nHitTest, message); } |