2008-10-03 9 views
7

Estoy usando SetCursor para establecer el cursor del sistema en mi propia imagen. El código es como la siguiente:SetCursor revierte después de mover un mouse

// member on some class 
HCURSOR _cursor; 

// at init time 
_cursor = LoadCursorFromFile("somefilename.cur"); 

// in some function 
SetCursor(_cursor); 

Cuando hago este cambio el cursor hace, pero en el primer mensaje de movimiento del ratón se convierte nuevamente al cursor del sistema por defecto flecha. Este es el único código en el proyecto que está configurando el cursor. ¿Qué debo hacer para que el cursor se mantenga como lo configuré?

Respuesta

9

Parece que tengo dos opciones. El primero es el que Mark Ransom sugirió aquí, que es para responder al mensaje de Windows WM_SETCURSOR y llamar a SetCursor en ese momento en función de dónde está el mouse. Normalmente Windows solo te enviará WM_SETCURSOR cuando el cursor esté sobre tu ventana, por lo que solo pondrás el cursor en tu ventana.

La otra opción es establecer el cursor predeterminado para el identificador de ventana al mismo tiempo que llamo al SetCursor. Esto cambia el cursor establecido por el controlador predeterminado a WM_SETCURSOR. Ese código sería algo como esto:

// defined somewhere 
HWND windowHandle; 
HCURSOR cursor; 

SetCursor(cursor); 
SetClassLong(windowHandle, GCL_HCURSOR, (DWORD)cursor); 

Si se utiliza el segundo método tiene que llamar tanto SetCursor y SetClassLong o el cursor no se actualizará hasta que el próximo movimiento del ratón.

2

Debe hacer que su mango HCURSOR no salga del alcance. Cuando el mouse se mueve, los mensajes de Windows comienzan a volar por todos lados, y borrará su identificador (en el ejemplo anterior).

Haga que un HCURSOR sea un miembro privado de la clase, y use ese identificador cuando llame a LoadCursor ...() y SetCursor(). Cuando haya terminado, no olvide liberarlo y limpiarlo, o terminará con una fuga de recursos.

1

Este comportamiento está destinado a ser así. Creo que la solución más simple es: al crear su clase de ventana (RegisterClass || RegisterClassEx), establezca el miembro WNDCLASS.hCursor || WNDCLASSEX.hCursor en NULL.

+0

Cambiar a NULL no resolvió el problema. En lugar de permitir que el cursor cambie, el cursor siempre fue <-> en lugar de la flecha normal. Y los mensajes de los mensajes WM_SETCURSOR siempre se estaban enviando, ya que pude verificar el uso de Spy ++ de 64 bits. Sin embargo, subí porque me hiciste aprender algo nuevo. – sergiol

0

Como @Heinz Traub dijo que el problema proviene del cursor definido en la llamada RegisterClass o RegisterClassEx. Es probable que tenga un código como:

BOOL CMyWnd::RegisterWindowClass() 
{ 
    WNDCLASS wndcls; 
    // HINSTANCE hInst = AfxGetInstanceHandle(); 
    HINSTANCE hInst = AfxGetResourceHandle(); 

    if (!(::GetClassInfo(hInst, _T("MyCtrl"), &wndcls))) 
    { 
     // otherwise we need to register a new class 
     wndcls.style   = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; 
     wndcls.lpfnWndProc  = ::DefWindowProc; 
     wndcls.cbClsExtra  = wndcls.cbWndExtra = 0; 
     wndcls.hInstance  = hInst; 
     wndcls.hIcon   = NULL; 
     wndcls.hCursor   = AfxGetApp()->LoadStandardCursor(IDC_ARROW); 
     wndcls.hbrBackground = (HBRUSH) (COLOR_3DFACE + 1); 
     wndcls.lpszMenuName  = NULL; 
     wndcls.lpszClassName = _T("MyCtrl"); 

     if (!AfxRegisterClass(&wndcls)) 
     { 
      AfxThrowResourceException(); 
      return FALSE; 
     } 
    } 

    return TRUE; 
} 

donde el wndcls.hCursor dice lo que va a ser utilizado cursor cuando se lanza WM_SETCURSOR mensaje; sucede cada vez que ocurre un movimiento del mouse y no solo.

He resuelto un problema similar de esta manera:

En la clase mapa de mensajes añadir una entrada para el mensaje WM_SETCURSOR:

BEGIN_MESSAGE_MAP(CMyWnd, CWnd) 
    //... other messages 
    ON_WM_SETCURSOR() 
END_MESSAGE_MAP() 

Añadir el método OnSetCursor, lo que cancelaría la clase padre aplicación :

BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{ 
    if (SomeCondition()) 
     return FALSE; 

    return __super::OnSetCursor(pWnd, nHitTest, message); 
} 

Explicación: cuando SomeCondition() es cierto, no se llama a la implementación de los padres.Puede ser que usted desee tener siempre un cursor no son anulados con el comportamiento de la clase padre, por lo que sólo necesita un método aún más corto:

BOOL CMyWnd::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{ 
    return FALSE; 
} 

y la declaración del método en el archivo de cabecera es:

afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message); 
Cuestiones relacionadas