VC ++ solves the problem of blinking the cursor when moving the mouse. In fact, the essence is the usage of ON_SETCURSOR, vcon_setcursor

Source: Internet
Author: User

VC ++ solves the problem of blinking the cursor when moving the mouse. In fact, the essence is the usage of ON_SETCURSOR, vcon_setcursor

When you call the Windows API function SetCursor to set the Cursor, you may encounter a flickering problem: move the mouse, and the Cursor flashes between the Class Cursor (that is, the Cursor specified when the window Class is registered) and the preset Cursor.

In the remarks on the SetCursor function on MSDN, if the Class Cursor is not empty, the system restores the Cursor to Class Cursor whenever the mouse moves. To avoid blinking the cursor, you must process the WM_SETCURSOR message. (MSDN instructions)

The following is an example: The program draws an RGB strip in the middle of the main window view. When the mouse moves within the Strip range, the cursor is set to Cross. In addition, based on the cursor position, the color of the stripe is displayed at 30 PX above the RGB strip. The program runs like this:

If you determine the cursor position in the message processing of WM_MOUSEMOVE and set the cursor, you will encounter the cursor blinking problem. The following code processes the message of WM_MOUSEMOVE:

 

01.LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)  02.{  03.    POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };  04.    RECT rect, rectText;  05.    get_rects(&rect, &rectText);  06.    InvalidateRect(&rectText);  07.    UpdateWindow();  08.    if (::PtInRect(&rect, ptCursor)) {  09.        ::SetCursor(m_cursor); 10.        int dx = (rect.right - rect.left) / 3;  11.        LPTSTR ppsz[] = { _T("Red"), _T("Green"), _T("Blue") };  12.        int index;  13.        if (ptCursor.x - rect.left < dx)  14.            index = 0;  15.        else if (ptCursor.x - rect.left < 2 * dx)  16.            index = 1;  17.        else index = 2;  18.        WTL::CString str;  19.        str.Format(_T("Cursor on %s part"), ppsz[index]);  20.        CClientDC dc(m_hWnd);  21.        dc.DrawText(str, -1, &rectText, DT_CENTER | DT_VCENTER);  22.    }  23.    else ::SetCursor(CCursor().LoadSysCursor(IDC_ARROW));  24.    return 0;  25.}  

 

The cause of blinking is that the system restores the cursor to Arrow every time before entering OnMouseMove. After Entering OnMouseMove, the cursor is immediately set to Cross if it is within the RGB strip range.

The solution is to put the above judgment logic in the message processing of WM_SETCURSOR. Of course, the way to get the client coordinates of the cursor is different. The Code is as follows:

[cpp] view plaincopyprint?1.LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/)  2.{  3.    POINT point;  4.    ::GetCursorPos(&point);  5.    ScreenToClient(&point);  6.    set_cursor(point);  7.    return 0;  8.}  
LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/){POINT point;::GetCursorPos(&point);ScreenToClient(&point);set_cursor(point);return 0;}

The set_cursor private method in the Code is actually the above judgment logic, namely:

[cpp] view plaincopyprint?1.// ptCursor: in client coordinate  2.void set_cursor(POINT& ptCursor) throw()  3.{  4.    RECT rect, rectText;  5.    get_rects(&rect, &rectText);  6.    InvalidateRect(&rectText);  7.    UpdateWindow();  8.    if (::PtInRect(&rect, ptCursor)) {  9.        ::SetCursor(m_cursor);  10.        int dx = (rect.right - rect.left) / 3;  11.        LPTSTR ppsz[] = { _T("Red"), _T("Green"), _T("Blue") };  12.        int index;  13.        if (ptCursor.x - rect.left < dx)  14.            index = 0;  15.        else if (ptCursor.x - rect.left < 2 * dx)  16.            index = 1;  17.        else index = 2;  18.        WTL::CString str;  19.        str.Format(_T("Cursor on %s part"), ppsz[index]);  20.        CClientDC dc(m_hWnd);  21.        dc.DrawText(str, -1, &rectText, DT_CENTER | DT_VCENTER);  22.    }  23.    else ::SetCursor(CCursor().LoadSysCursor(IDC_ARROW));  24.}  

 

// ptCursor: in client coordinatevoid set_cursor(POINT& ptCursor) throw(){RECT rect, rectText;get_rects(&rect, &rectText);InvalidateRect(&rectText);UpdateWindow();if (::PtInRect(&rect, ptCursor)) {::SetCursor(m_cursor);int dx = (rect.right - rect.left) / 3;LPTSTR ppsz[] = { _T("Red"), _T("Green"), _T("Blue") };int index;if (ptCursor.x - rect.left < dx)index = 0;else if (ptCursor.x - rect.left < 2 * dx)index = 1;else index = 2;WTL::CString str;str.Format(_T("Cursor on %s part"), ppsz[index]);CClientDC dc(m_hWnd);dc.DrawText(str, -1, &rectText, DT_CENTER | DT_VCENTER);}else ::SetCursor(CCursor().LoadSysCursor(IDC_ARROW));}

This solves the problem of blinking the cursor.

 

When you call the Windows API function SetCursor to set the Cursor, you may encounter a flickering problem: move the mouse, and the Cursor flashes between the Class Cursor (that is, the Cursor specified when the window Class is registered) and the preset Cursor.

In the remarks on the SetCursor function on MSDN, if the Class Cursor is not empty, the system restores the Cursor to Class Cursor whenever the mouse moves. To avoid blinking the cursor, you must process the WM_SETCURSOR message. (MSDN instructions)

The following is an example: The program draws an RGB strip in the middle of the main window view. When the mouse moves within the Strip range, the cursor is set to Cross. In addition, based on the cursor position, the color of the stripe is displayed at 30 PX above the RGB strip. The program runs like this:

If you determine the cursor position in the message processing of WM_MOUSEMOVE and set the cursor, you will encounter the cursor blinking problem. The following code processes the message of WM_MOUSEMOVE:

[Cpp]View plaincopyprint?
  1. LRESULT OnMouseMove (UINT/* uMsg */, WPARAM/* wParam */, LPARAM lParam, BOOL &/* bHandled */)
  2. {
  3. POINT ptCursor = {GET_X_LPARAM (lParam), GET_Y_LPARAM (lParam )};
  4. RECT rect, rectText;
  5. Get_rects (& rect, & rectText );
  6. InvalidateRect (& rectText );
  7. UpdateWindow ();
  8. If (: PtInRect (& rect, ptCursor )){
  9. : SetCursor (m_cursor );
  10. Int dx = (rect. right-rect. left)/3;
  11. LPTSTR ppsz [] = {_ T ("Red"), _ T ("Green"), _ T ("Blue ")};
  12. Int index;
  13. If (ptCursor. x-rect. left <dx)
  14. Index = 0;
  15. Else if (ptCursor. x-rect. left <2 * dx)
  16. Index = 1;
  17. Else index = 2;
  18. WTL: CString str;
  19. Str. Format (_ T ("Cursor on % s part"), ppsz [index]);
  20. CClientDC dc (m_hWnd );
  21. Dc. DrawText (str,-1, & rectText, DT_CENTER | DT_VCENTER );
  22. }
  23. Else: SetCursor (CCursor (). LoadSysCursor (IDC_ARROW ));
  24. Return 0;
  25. }
LRESULT OnMouseMove(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/){POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };RECT rect, rectText;get_rects(&rect, &rectText);InvalidateRect(&rectText);UpdateWindow();if (::PtInRect(&rect, ptCursor)) {::SetCursor(m_cursor);int dx = (rect.right - rect.left) / 3;LPTSTR ppsz[] = { _T("Red"), _T("Green"), _T("Blue") };int index;if (ptCursor.x - rect.left < dx)index = 0;else if (ptCursor.x - rect.left < 2 * dx)index = 1;else index = 2;WTL::CString str;str.Format(_T("Cursor on %s part"), ppsz[index]);CClientDC dc(m_hWnd);dc.DrawText(str, -1, &rectText, DT_CENTER | DT_VCENTER);}else ::SetCursor(CCursor().LoadSysCursor(IDC_ARROW));return 0;}

The cause of blinking is that the system restores the cursor to Arrow every time before entering OnMouseMove. After Entering OnMouseMove, the cursor is immediately set to Cross if it is within the RGB strip range.

The solution is to put the above judgment logic in the message processing of WM_SETCURSOR. Of course, the way to get the client coordinates of the cursor is different. The Code is as follows:

[Cpp]View plaincopyprint?
  1. LRESULT OnSetCursor (UINT/* uMsg */, WPARAM/* wParam */, LPARAM lParam, BOOL &/* bHandled */)
  2. {
  3. POINT point;
  4. : GetCursorPos (& point );
  5. ScreenToClient (& point );
  6. Set_cursor (point );
  7. Return 0;
  8. }
LRESULT OnSetCursor(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/){POINT point;::GetCursorPos(&point);ScreenToClient(&point);set_cursor(point);return 0;}

The set_cursor private method in the Code is actually the above judgment logic, namely:

[Cpp]View plaincopyprint?
  1. // PtCursor: in client coordinate
  2. Void set_cursor (POINT & ptCursor) throw ()
  3. {
  4. RECT rect, rectText;
  5. Get_rects (& rect, & rectText );
  6. InvalidateRect (& rectText );
  7. UpdateWindow ();
  8. If (: PtInRect (& rect, ptCursor )){
  9. : SetCursor (m_cursor );
  10. Int dx = (rect. right-rect. left)/3;
  11. LPTSTR ppsz [] = {_ T ("Red"), _ T ("Green"), _ T ("Blue ")};
  12. Int index;
  13. If (ptCursor. x-rect. left <dx)
  14. Index = 0;
  15. Else if (ptCursor. x-rect. left <2 * dx)
  16. Index = 1;
  17. Else index = 2;
  18. WTL: CString str;
  19. Str. Format (_ T ("Cursor on % s part"), ppsz [index]);
  20. CClientDC dc (m_hWnd );
  21. Dc. DrawText (str,-1, & rectText, DT_CENTER | DT_VCENTER );
  22. }
  23. Else: SetCursor (CCursor (). LoadSysCursor (IDC_ARROW ));
  24. }
// ptCursor: in client coordinatevoid set_cursor(POINT& ptCursor) throw(){RECT rect, rectText;get_rects(&rect, &rectText);InvalidateRect(&rectText);UpdateWindow();if (::PtInRect(&rect, ptCursor)) {::SetCursor(m_cursor);int dx = (rect.right - rect.left) / 3;LPTSTR ppsz[] = { _T("Red"), _T("Green"), _T("Blue") };int index;if (ptCursor.x - rect.left < dx)index = 0;else if (ptCursor.x - rect.left < 2 * dx)index = 1;else index = 2;WTL::CString str;str.Format(_T("Cursor on %s part"), ppsz[index]);CClientDC dc(m_hWnd);dc.DrawText(str, -1, &rectText, DT_CENTER | DT_VCENTER);}else ::SetCursor(CCursor().LoadSysCursor(IDC_ARROW));}

This solves the problem of blinking the cursor.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.