2011-05-05 14 views
7

Estoy desarrollando un Word addin for MS Word en Windows, y este complemento tiene como 'panel de tareas avanzadas' mostrando y atracando en el lado izquierdo de la ventana del documento de Word (es treeview (contorno) mostrando una lista de documentos de Word para editar rápidamente varios documentos en un proyecto).Cómo redirigir el mensaje de la rueda del mouse a otras ventanas?

Mi pregunta es, la ventana de documento de Word responde al ratón mensaje rueda sólo cuando está concentrado, pero yo quiero ser capaz de desplazarse por el documento con la rueda del ratón cada vez que el cursor del ratón se cierne sobre ella incluso la palabra la ventana del documento no tiene un foco de entrada.

Cualquier sugerencia en este caso particular? ¡Gracias!

Respuesta

7

No estoy seguro de que va a funcionar, pero me gustaría probar el siguiente:

Implementar un enlace global de ratón de bajo nivel usando la función SetWindowsHookEx. En el procedimiento de enlace, que debe invocarse en los eventos de desplazamiento de la rueda del mouse, compruebe si la ventana debajo del cursor del mouse es la ventana del documento de Word. Si es así, establezca un indicador compartido que indique la acción de desplazamiento necesaria. ¡No envíe WM_VSCROLL directamente desde el procedimiento de enlace! Este procedimiento tiene que ser realmente rápido y simple.

Ahora, en el bucle de mensajes de su complemento, marque la bandera y, si está configurada, envíe WM_VSCROLL a la ventana del documento de Word.

+0

Gracias por la idea, Alex! Parece un método viable. –

+0

+1 para la advertencia, que de hecho es muy importante. – 0xC0000022L

+0

@Alex, lamento no haber aceptado la respuesta antes, porque me di por vencido para implementar esta función en ese momento y luego olvidé esta pregunta ... Solo revisé todas las respuestas, y creo que la suya funcionaría. Lo siento por la recompensa ... –

2

Quizás pueda hacer uso de la función de API de Windows SetCapture(hWnd). Esto hará que todos los eventos del mouse vayan a su hWnd en lugar de a lo que hWnd normalmente esperaría recibirlos. Si captura cuando el mouse entra en la ventana del documento de Word y ReleaseCapture() cuando el mouse se va o Word gana el foco, debería funcionar correctamente.

Descargo de responsabilidad: He utilizado la captura del mouse en C# antes, pero nunca lo he hecho en C++. No sé si se comporta exactamente de la misma manera.

0

Intente lo siguiente, esto podría ayudarlo.

1) Manejar WM_MOUSEHOVER mensaje.

2) En el controlador, use SendMessage, con WM_VSCROLL como parámetro del mensaje.

0

Usando Spy ++ Vi que la ventana que recibe los mensajes es de la clase _Wwg (al menos 2003 es) y está respondiendo al mensaje WM_MOUSEWHEEL. Entonces enviaría a esa ventana un mensaje WM_MOUSEWHELL cuando quiera que se desplace.

0

Tengo el código C++ cortado con tijeras debajo de un comentario en https://msdn.microsoft.com/en-us/library/windows/desktop/ms645617(v=vs.85).aspx

Y lo usaron (y variaciones sobre la misma) con éxito.

El usuario que lo escribió alega que se inspiró en una recomendación de ms sobre una guía de prácticas recomendadas de Windows Vista, para reenviar el evento de la rueda del mouse a la ventana que esté rodeada por el cursor del mouse. La virtud de su implementación es que no es muy intrusivo, simplemente lo suelta y establece los ganchos, haciendo referencia a su hilo principal. Evita reenviar el evento a ventanas que pertenecen a otros procesos, pero tal vez eso realmente podría ser algo bueno.

namespace { 
     LRESULT CALLBACK mouseInputHook(int nCode, WPARAM wParam, LPARAM lParam) { 
    //"if nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function 
    //without further processing and should return the value returned by CallNextHookEx" 
    if (nCode >= 0) { 
     MSG& msgInfo = *reinterpret_cast<MSG*>(lParam); 

     if (msgInfo.message == WM_MOUSEWHEEL || 
      msgInfo.message == WM_MOUSEHWHEEL) { 
     POINT pt = {}; 
     pt.x = ((int)(short)LOWORD(msgInfo.lParam)); //yes, there's also msgInfo.pt, but let's not take chances 
     pt.y = ((int)(short)HIWORD(msgInfo.lParam)); // 

     //visible child window directly under cursor; attention: not necessarily from our process! 
     //http://blogs.msdn.com/b/oldnewthing/archive/2010/12/30/10110077.aspx 
     if (HWND hWin = ::WindowFromPoint(pt)) 
      if (msgInfo.hwnd != hWin && ::GetCapture() == nullptr) { 
      DWORD winProcessId = 0; 
      ::GetWindowThreadProcessId(//no-fail! 
       hWin, //_In_ HWND hWnd, 
       &winProcessId); //_Out_opt_ LPDWORD lpdwProcessId 
      if (winProcessId == ::GetCurrentProcessId()) //no-fail! 
       msgInfo.hwnd = hWin; //it would be a bug to set handle from another process here 
      } 
     } 
    } 

    return ::CallNextHookEx(nullptr, nCode, wParam, lParam); 
    } 

    struct Dummy { 

    Dummy() { 
     hHook = ::SetWindowsHookEx(WH_GETMESSAGE, //__in int idHook, 
      mouseInputHook, //__in HOOKPROC lpfn, 
      nullptr, //__in HINSTANCE hMod, 
      ::GetCurrentThreadId()); //__in DWORD dwThreadId 
     assert(hHook); 
    } 

    ~Dummy() { 
     if (hHook) 
     ::UnhookWindowsHookEx(hHook); 
    } 

    private: 
    HHOOK hHook; 
    } dummy; 
} 
Cuestiones relacionadas