Erkennen mehrer Mäuse und Event triggern



  • Leute, ihr seid mir eine grosse Hilfe. Tut mir leid wenn ich eure Nerven strapaziere. 😉

    Ich werde das nochmal ausarbeiten und melde mich dann nochmal.

    Danke vielmals.



  • Habs aus Neugier gerade mal ausprobiert. Ich verwende ein leicht vereinfachtes Win32 Gerüst aus VisualStudio.

    // Globale Variablen:
    HINSTANCE hInst;                                  // Aktuelle Instanz
    TCHAR *szTitle = TEXT("Direktmouse");             // Titelleistentext
    TCHAR *szWindowClass = TEXT("DirektmouseClass");  // Klassenname des Hauptfensters
    
    //  -------------------------------------------------------------------------
    //   FUNKTION: InitInstance(HINSTANCE, int)
    //   ZWECK: Speichert das Instanzenhandle und erstellt das Hauptfenster.
    //  -------------------------------------------------------------------------
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
      HWND hWnd;
    
      hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern
    
      hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 50, 50,
                            450, 200, NULL, NULL, hInstance, NULL);
      if(!hWnd) {
         return FALSE;
      }
    
      RAWINPUTDEVICE Rid[1];
    
      Rid[0].usUsagePage = 0x01;      // 1 stands for "generic desktop controls" 
      Rid[0].usUsage = 0x02;          // 2 is mouse, 4 is joystick, 6 is keyboard 
      Rid[0].dwFlags = 0; 
      Rid[0].hwndTarget = hWnd;       // handle to the target window. If NULL it follows the keyboard focus
    
      if(RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) {
         //registration failed. Call GetLastError for the cause of the error
      }
    
      ShowWindow(hWnd, nCmdShow);
      UpdateWindow(hWnd);
    
      return TRUE;
    }
    

    Hatte zunächst etwas geflucht, da das Fenster ziemlich tot war und nicht mehr auf die Maus reagierte. (Lösung dwFlags = 0)

    Das Microsoft Beispiel scheint etwas unvollständig zu sein. Wenn ich die Doku richtig verstanden habe fehlt z.b. der Aufruf von DefWindowProc().

    case WM_INPUT: 
       {
       WPARAM code = GET_RAWINPUT_CODE_WPARAM(wParam);  // Retrieve input code from wParam in WM_INPUT
    
       ...
    
       if(code == RIM_INPUT)
          return DefWindowProc(hWnd, message, wParam, lParam);
       else
          return 0;
       }
    

    Ob oder wie das mit mehreren Mäusen läuft habe ich nicht untersucht.



  • Ok, danke, das sieht spannend aus.

    Ich habe mir jetzt Visual Studio 12 installiert und den Code eingepflegt. Leider bekomme ich nur ein leeres Fenster zu sehen und Meldungen über fehlende PDB Dateien.

    So sieht das Fenster aus: http://imgur.com/FsGKq71

    Das sind die Meldungen die VS ausspuckt:

    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\ntdll.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\kernel32.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\KernelBase.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\user32.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\msvcr110d.dll" geladen. Symbole wurden geladen.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\gdi32.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\imm32.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\msctf.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\msvcrt.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\uxtheme.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\dwmapi.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\ole32.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\combase.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\rpcrt4.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\sechost.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\sspicli.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\cryptbase.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    "Win32Project3.exe" (Win32): "C:\Windows\SysWOW64\bcryptprimitives.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.
    Das Programm "[6760] Win32Project3.exe" wurde mit Code 0 (0x0) beendet.
    

    Code 1-zu-1 aus VS 12 übernommen:

    // Win32Project3.cpp : Definiert den Einstiegspunkt für die Anwendung.
    //
    
    #include "stdafx.h"
    #include "Win32Project3.h"
    
    #define MAX_LOADSTRING 100
    
    // Globale Variablen:
    HINSTANCE hInst;								// Aktuelle Instanz
    TCHAR szTitle[MAX_LOADSTRING];					// Titelleistentext
    TCHAR szWindowClass[MAX_LOADSTRING];			// Klassenname des Hauptfensters
    
    // Vorwärtsdeklarationen der in diesem Codemodul enthaltenen Funktionen:
    ATOM				MyRegisterClass(HINSTANCE hInstance);
    BOOL				InitInstance(HINSTANCE, int);
    LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
    INT_PTR CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
                         _In_opt_ HINSTANCE hPrevInstance,
                         _In_ LPTSTR    lpCmdLine,
                         _In_ int       nCmdShow)
    {
    	UNREFERENCED_PARAMETER(hPrevInstance);
    	UNREFERENCED_PARAMETER(lpCmdLine);
    
     	// TODO: Hier Code einfügen.
    	MSG msg;
    	HACCEL hAccelTable;
    
    	// Globale Zeichenfolgen initialisieren
    	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    	LoadString(hInstance, IDC_WIN32PROJECT3, szWindowClass, MAX_LOADSTRING);
    	MyRegisterClass(hInstance);
    
    	// Anwendungsinitialisierung ausführen:
    	if (!InitInstance (hInstance, nCmdShow))
    	{
    		return FALSE;
    	}
    
    	hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_WIN32PROJECT3));
    
    	// Hauptnachrichtenschleife:
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}
    
    	return (int) msg.wParam;
    }
    
    //
    //  FUNKTION: MyRegisterClass()
    //
    //  ZWECK: Registriert die Fensterklasse.
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
    	WNDCLASSEX wcex;
    
    	wcex.cbSize = sizeof(WNDCLASSEX);
    
    	wcex.style			= CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc	= WndProc;
    	wcex.cbClsExtra		= 0;
    	wcex.cbWndExtra		= 0;
    	wcex.hInstance		= hInstance;
    	wcex.hIcon			= LoadIcon(hInstance, MAKEINTRESOURCE(IDI_WIN32PROJECT3));
    	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
    	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
    	wcex.lpszMenuName	= MAKEINTRESOURCE(IDC_WIN32PROJECT3);
    	wcex.lpszClassName	= szWindowClass;
    	wcex.hIconSm		= LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    
    	return RegisterClassEx(&wcex);
    }
    
    //
    //   FUNKTION: InitInstance(HINSTANCE, int)
    //
    //   ZWECK: Speichert das Instanzenhandle und erstellt das Hauptfenster.
    //
    //   KOMMENTARE:
    //
    //        In dieser Funktion wird das Instanzenhandle in einer globalen Variablen gespeichert, und das
    //        Hauptprogrammfenster wird erstellt und angezeigt.
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
    { 
      HWND hWnd; 
    
      hInst = hInstance; // Instanzenhandle in der globalen Variablen speichern 
    
      hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, 50, 50, 
                            450, 200, NULL, NULL, hInstance, NULL); 
      if(!hWnd) { 
         return FALSE; 
      } 
    
      RAWINPUTDEVICE Rid[1]; 
    
      Rid[0].usUsagePage = 0x01;      // 1 stands for "generic desktop controls" 
      Rid[0].usUsage = 0x02;          // 2 is mouse, 4 is joystick, 6 is keyboard 
      Rid[0].dwFlags = 0; 
      Rid[0].hwndTarget = hWnd;       // handle to the target window. If NULL it follows the keyboard focus 
    
      if(RegisterRawInputDevices(Rid, 1, sizeof(Rid[0])) == FALSE) { 
         //registration failed. Call GetLastError for the cause of the error 
      } 
    
      ShowWindow(hWnd, nCmdShow); 
      UpdateWindow(hWnd); 
    
      return TRUE; 
    }
    
    //
    //  FUNKTION: WndProc(HWND, UINT, WPARAM, LPARAM)
    //
    //  ZWECK:  Verarbeitet Meldungen vom Hauptfenster.
    //
    //  WM_COMMAND	- Verarbeiten des Anwendungsmenüs
    //  WM_PAINT	- Zeichnen des Hauptfensters
    //  WM_DESTROY	- Beenden-Meldung anzeigen und zurückgeben
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	int wmId, wmEvent;
    	PAINTSTRUCT ps;
    	HDC hdc;
    
    	switch (message)
    	{
    	case WM_COMMAND:
    		wmId    = LOWORD(wParam);
    		wmEvent = HIWORD(wParam);
    		// Menüauswahl bearbeiten:
    		switch (wmId)
    		{
    		case IDM_\1:
    			DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
    			break;
    		case IDM_EXIT:
    			DestroyWindow(hWnd);
    			break;
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);
    		}
    		break;
    	case WM_PAINT:
    		hdc = BeginPaint(hWnd, &ps);
    		// TODO: Hier den Zeichnungscode hinzufügen.
    		EndPaint(hWnd, &ps);
    		break;
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProc(hWnd, message, wParam, lParam);
    	}
    	return 0;
    }
    
    // Meldungshandler für Infofeld.
    INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	UNREFERENCED_PARAMETER(lParam);
    	switch (message)
    	{
    	case WM_INITDIALOG:
    		return (INT_PTR)TRUE;
    
    	case WM_COMMAND:
    		if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
    		{
    			EndDialog(hDlg, LOWORD(wParam));
    			return (INT_PTR)TRUE;
    		}
    		break;
    	}
    
    	return (INT_PTR)FALSE;
    }
    

    Ich komme einem Ergebnis immer näher, toll 😋



  • Sieht soweit richtig aus.

    Die Stelle mit case WM_INPUT fehlt noch. Meine beiden Posts dazu kombinieren und
    per Copy&Paste reinkopieren.

    Fehlende PDB Dateien sollten nicht weiter stören ...



  • Vielen Dank,

    Kommt der WM_Input Teil zu "// Meldungshandler für Infofeld." oder "FUNKTION: WndProc(HWND, UINT, WPARAM, LPARAM)"

    Dort wo du die drei punkte hingecshrieben hast komt was genau hin?

    case WM_INPUT: 
       { 
       WPARAM code = GET_RAWINPUT_CODE_WPARAM(wParam);  // Retrieve input code from wParam in WM_INPUT 
    
       ... 
    
       if(code == RIM_INPUT) 
          return DefWindowProc(hWnd, message, wParam, lParam); 
       else 
          return 0; 
       }
    

    Danke



  • sgli schrieb:

    Kommt der WM_Input Teil zu "// Meldungshandler für Infofeld." oder "FUNKTION: WndProc(HWND, UINT, WPARAM, LPARAM)"

    In der Aboutbox macht es wohl wenig Sinn ...

    sgli schrieb:

    Dort wo du die drei punkte hingecshrieben hast komt was genau hin?

    Ist das wirklich jetzt dein Ernst ??? Wenn ja, scheinen ja die einfachsten Grundlagen zu fehlen ...

    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int wmId, wmEvent;
        PAINTSTRUCT ps;
        HDC hdc;
    
        switch (message)
        {
        case WM_INPUT: 
           { 
           WPARAM code = GET_RAWINPUT_CODE_WPARAM(wParam);  // Retrieve input code from wParam in WM_INPUT 
    
        UINT dwSize;
        GetRawInputData((HRAWINPUT)lParam, RID_INPUT, NULL, &dwSize, sizeof(RAWINPUTHEADER));
    
       ... 
    
       if(code == RIM_INPUT) 
          return DefWindowProc(hWnd, message, wParam, lParam); 
       else 
          return 0; 
       }
    

    Dir ist aber schon klar, das wir etwas Eigeninitiative erwarten ?
    Ich werde erst wieder was beisteuern wenn Du auch was anbietest ...



  • Danke für die Hilfe. Du kannst dir sicher vorstellen das es nicht allzu leicht für mich ist da voll einzusteigen. Ich wollte niemandem auf die Nerven gehen. ich möchte ganz einfach etwas lernen. Also bitte nicht gleich ausflippen 🙂

    Zum Code: Ich habe de WM_INPUT case schon bei LRESULT_CALLBACK eingefügt.

    Mich hat dieser Teil hier verwirrt: [code="cpp"]case WM_INPUT:
    {
    WPARAM code = GET_RAWINPUT_CODE_WPARAM(wParam); // Retrieve input code from wParam in WM_INPUT

    ...

    if(code == RIM_INPUT)
    return DefWindowProc(hWnd, message, wParam, lParam);
    else
    return 0;
    }[/code]

    Zusammen mit der Aussage:

    Das Microsoft Beispiel scheint etwas unvollständig zu sein. Wenn ich die Doku richtig verstanden habe fehlt z.b. der Aufruf von DefWindowProc()

    Wenn ich den Code jetzt kompiliere bekomme ich jetzt halt das leere Fenster. Beim debuggen reagiert das Fenster auf Bewegungen, d.h. es schliesst und öffnet sich wieder.

    Durch dieses kleine Beispiel habe ich schon einiges besser verstanden als vorhin. Danke dafür.



  • Poste mal den gesamten Code den du im Moment hast.



  • hustbaer schrieb:

    Poste mal den gesamten Code den du im Moment hast.

    Nicht mehr nötig. Ich habe eine (beinahe) elegante Lösung für mein Problem gefunden. Ich habe einige Open Source Projekte studiert die ähnliche Probleme lösen und sehr gut dokumentiert sind. Das hat mir sehr geholfen da ich funktionierende Beispiele hatte. zusammen mit der netten Hilfe hier konnte ich mir etwas funktionierendes zusammenschustern.

    Jetzt habe ich die grösseren Probleme aus dem Weg geräumt und schlage mich mit kleinere Herausforderungen rum.

    Auf jeden Fall vielen Dank für die Hilfe. 🙂

    Wer ähnliche Probleme hat: Die Beispiele auf dieser Seite haben mir geholfen http://jstookey.com/arcade/rawmouse/
    vor allem die Source von raw_mouse_test.exe war hilfreich.



  • Für den Fall das GetRawInputBuffer() benutzt wird, muss ein Implementationsfehler in WOW64 behandelt werden: Für 32 Bit Prozesse wird die 64 Bit Strukturdeklaration verwendet.


Anmelden zum Antworten