WM_MOUSEHWHEEL wird nicht richtig empfangen

posi90

Erfahrenes Mitglied
Hallo,

In meiner win32-Anwendung wird das Mausradereignis für die Horizontale nicht richtig empfangen.

Und zwar bekomm ich sowohl das horizontale- als auch das vertikale Ereignis über WM_MOUSEWHEEL
(beachte: WM_MOUSEWHEEL vs WM_MOUSEHWHEEL).

Nun kann ich nicht unterscheiden, welches Ereignis es ist.

Verwende: g++ 4.9.1 via MinGW, Win7x64

Hier wär mein minimal Code:

Code:
#include <windows.h>
#include <iostream>

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int main()
{
  WNDCLASS wc;
  memset(&wc, 0, sizeof(WNDCLASS));
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = WndProc;
  wc.hInstance = GetModuleHandle(NULL);
  wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 3);
  wc.lpszClassName = "minimal";
  if(!RegisterClass(&wc)) return 1;
  if(!CreateWindow(wc.lpszClassName,
      "Minimal Windows Application",
      WS_OVERLAPPEDWINDOW|WS_VISIBLE,
      0,0,640,480,0,0,GetModuleHandle(NULL),NULL)) return 2;

  MSG msg;
  while(GetMessage(&msg, NULL, 0, 0) > 0)
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch (message)
  {
#ifndef WM_MOUSEHWHEEL //see: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645614(v=vs.85).aspx
#define WM_MOUSEHWHEEL 0x020E
#endif
    case WM_MOUSEHWHEEL:
      std::cout << "horizontal wheel: " << GET_WHEEL_DELTA_WPARAM(wParam)
          << std::endl;
      break;
    case WM_MOUSEWHEEL:
      std::cout << "vertical wheel: " << GET_WHEEL_DELTA_WPARAM(wParam)
          << std::endl;
      break;
    case WM_KEYDOWN:
      if(wParam == VK_ESCAPE) DestroyWindow(hWnd);
      break;
    case WM_CLOSE:
      DestroyWindow(hWnd);
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(hWnd, message, wParam, lParam);
  }
  return 0;
}

Meine Ausgabe dazu:
Code:
vertical wheel: 120
vertical wheel: -120
vertical wheel: -840 <- sollte eigentlich ein horizontales Ereignis sein

Leider fand ich im Netz auch nichts Brauchbares.
Hatte schon mal jemand dieses Problem?

mfg.
 
Hast jemand eine Maus mit horizontaler Scrollfunktion, der meinen Code testen will? :p

Hab nun alles auf RAWINPUT umgemünzt und komme auf dasselbe Ergebnis :/
 
Muss noch etwas hinzufügen: Das OS lief auf VirtualBox, welches offensichtlich dieses Feature nicht unterstützt und falsche Werte liefert (gleiches Event). Wine liefert wenigstens gar keine Werte =)

Habe nun den Code ohne Virtualisierung getestet und voila, nun funktionierts xD

Danke an alle, die sich die Zeit genommen hatten, meinen Thread durchzulesen.

Hier ist mein minimal, falls es wem hilft :)
Man sieht schön, dass sich RAWINPUT etwas anders verhält als der Input von Windows.

Code:
#include <windows.h>
#include <windowsx.h>
#include <iostream>
#include <vector>

#ifndef HID_USAGE_PAGE_GENERIC
#define HID_USAGE_PAGE_GENERIC         ((USHORT) 0x01)
#endif
#ifndef HID_USAGE_GENERIC_MOUSE
#define HID_USAGE_GENERIC_MOUSE        ((USHORT) 0x02)
#endif
#ifndef HID_USAGE_GENERIC_KEYBOARD
#define HID_USAGE_GENERIC_KEYBOARD        ((USHORT) 0x06)
#endif

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

int main()
{
  WNDCLASS wc;
  memset(&wc, 0, sizeof(WNDCLASS));
  wc.style = CS_HREDRAW | CS_VREDRAW;
  wc.lpfnWndProc = WndProc;
  wc.hInstance = GetModuleHandle(NULL);
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 3);
  wc.lpszClassName = "minimal";
  if(!RegisterClass(&wc)) return 1;
  HWND hwnd = CreateWindow(wc.lpszClassName,
      "Minimal Windows Application",
      WS_OVERLAPPEDWINDOW|WS_VISIBLE,
      0,0,640,480,0,0,GetModuleHandle(NULL),NULL);

  if(!hwnd) return 2;

  std::vector<RAWINPUTDEVICE> ri_devices;
  ri_devices.push_back(
  {HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, 0, hwnd});
  if(ri_devices.size())
  {
    RegisterRawInputDevices(&ri_devices[0], ri_devices.size(),
        sizeof(RAWINPUTDEVICE));
  }

  MSG msg;
  while(GetMessage(&msg, NULL, 0, 0) > 0)
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  for(auto &device : ri_devices)
  {
    device.hwndTarget = NULL;
    device.dwFlags = RIDEV_REMOVE;
  }
  if(ri_devices.size())
  {
    RegisterRawInputDevices(&ri_devices[0], ri_devices.size(),
        sizeof(RAWINPUTDEVICE));
  }
  return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  static bool mouse_inside = false;
  static int posx, posy;
  switch(message)
  {
#ifndef WM_MOUSEHWHEEL
#define WM_MOUSEHWHEEL 0x020E
#endif
    case WM_MOUSEWHEEL:
    {
      std::cout << "Win32 vertical mouse wheel event: "
          << GET_WHEEL_DELTA_WPARAM(wParam) << std::endl;
    }
      break;
    case WM_MOUSEHWHEEL:
      std::cout << "Win32 horizontal mouse wheel event: "
          << GET_WHEEL_DELTA_WPARAM(wParam) << std::endl;
      break;
    case WM_MOUSEMOVE:
    {
      if(!mouse_inside)
      {
        TRACKMOUSEEVENT tme =
        {sizeof(TRACKMOUSEEVENT), TME_LEAVE, hwnd, 0};
        TrackMouseEvent(&tme);
        posx = GET_X_LPARAM(lParam);
        posy = GET_Y_LPARAM(lParam);
        InvalidateRect(hwnd, NULL, TRUE);
      }
      mouse_inside = true;
    }
      break;
    case WM_MOUSELEAVE:
    {
      mouse_inside = false;
      InvalidateRect(hwnd, NULL, TRUE);
    }
      break;
    case WM_INPUT:
    {
      typedef unsigned char byte;
      unsigned int buffer_size = 0;
      unsigned int result = 0;
      static std::vector<byte> buffer;

      if(GetRawInputData((HRAWINPUT)lParam, RID_INPUT, 0, &buffer_size,
          sizeof(RAWINPUTHEADER)) == 0)
      {
        if(buffer_size > buffer.capacity()) buffer.reserve(buffer_size);
        result = GetRawInputData((HRAWINPUT)lParam, RID_INPUT, &buffer[0],
            &buffer_size, sizeof(RAWINPUTHEADER));
        if(result == buffer_size)
        {
          const RAWINPUT *raw_input =
              reinterpret_cast<const RAWINPUT*>(&buffer[0]);
          switch(raw_input->header.dwType)
          {
            case RIM_TYPEMOUSE:
            {
#ifndef RI_MOUSE_HWHEEL
#define RI_MOUSE_HWHEEL 0x0800
#endif
              const RAWMOUSE &raw_mouse = (raw_input->data.mouse);
              if(raw_mouse.usButtonFlags & RI_MOUSE_WHEEL)
              {
                std::cout << "RAW vertical mouse wheel event: "
                    << static_cast<const short>(raw_mouse.usButtonData)
                    << std::endl;
              }
              else if(raw_mouse.usButtonFlags & RI_MOUSE_HWHEEL)
              {
                std::cout << "RAW horizontal mouse wheel event: "
                    << static_cast<const short>(raw_mouse.usButtonData)
                    << std::endl;
              }
              if(!(raw_mouse.usFlags & MOUSE_MOVE_ABSOLUTE))
              {
                posx += raw_mouse.lLastX;
                posy += raw_mouse.lLastY;
                InvalidateRect(hwnd, NULL, TRUE);
              }
              //else ??
            }
              break;
          }
        }
      }
    }
      break;
    case WM_CREATE:
    {
      TRACKMOUSEEVENT tme =
      {sizeof(TRACKMOUSEEVENT), TME_LEAVE, hwnd, 0};
      TrackMouseEvent(&tme);
    }
    case WM_PAINT:
    {
      PAINTSTRUCT ps;
      HDC hdc = BeginPaint(hwnd, &ps);
      if(mouse_inside)
      {
        HBRUSH BrushYellow = CreateSolidBrush(RGB(250, 255, 5));
        POINT Pt[3];
        Pt[0].x = 0 + posx; Pt[0].y = 0 + posy;
        Pt[1].x = 15 + posx; Pt[1].y = 0 + posy;
        Pt[2].x = 0 + posx; Pt[2].y = 15 + posy;
        SelectObject(hdc, BrushYellow);
        Polygon(hdc, Pt, 3);
        DeleteObject(BrushYellow);
      }
      EndPaint(hwnd, &ps);
    }
      return 0;
    case WM_KEYDOWN:
      if(wParam == VK_ESCAPE) DestroyWindow(hwnd);
      break;
    case WM_CLOSE:
      DestroyWindow(hwnd);
      break;
    case WM_DESTROY:
      PostQuitMessage(0);
      break;
    default:
      return DefWindowProc(hwnd, message, wParam, lParam);
  }
  return 0;
}

Bei g++ das c++11 Flag nicht vergessen ;)

mfg.
 

Neue Beiträge

Zurück