Bei gedrückter linken Maustaste Klicks ausführen



  • Hey 🙂
    Ich möchte bei gedrückter linken Maustaste mehrere Klicks ausführen solange diese gedrückt bleibt.
    Ich erstelle einen LowLevelMouseProc(Hook) und überprüfe ob LBUTTONDOWN aktiviert ist.

    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
    	// Set windows hook
    	cout << "Starting..." << endl;
    	HHOOK mouseHook = SetWindowsHookEx(WH_MOUSE_LL,MouseProc,hInstance,0);
    	MessageBox(NULL, "Press OK to stop.", "Information", MB_OK);
    	return 0;
    }
    LRESULT CALLBACK MouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
    	PKBDLLHOOKSTRUCT p = (PKBDLLHOOKSTRUCT)(lParam);
    	if (onoff == true)
    	{
    			if (wParam == WM_LBUTTONDOWN)
    		{
    			INPUT Input;  
    			Input.type = INPUT_MOUSE; 
    			Input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;     //Linke Taste Runter. 
    			SendInput(true, &Input, sizeof(Input));
    			ZeroMemory(&Input,sizeof(INPUT)); 
    			Input.mi.dwFlags = MOUSEEVENTF_LEFTUP;     //Linke Taste loslassen. 
    			SendInput(true, &Input, sizeof(Input));   
    			Sleep(60);
    		}
    	}
    	return CallNextHookEx(NULL, nCode, wParam, lParam);
    }
    

    Dies wird auch ausgeführt.. Jedenfalls wird nur ungefähr 16x geklickt und hört dann auf. Da diese aber solange Klicks senden soll wie die
    Linke Maustaste gedrückt bleibt, erfüllt das nicht den Zweck.
    Liegt es evtl. daran, dass diese SendInputs ebenfalls wahrgenommen werden von dem LLMOUSEHOOK und deshalb nur 16x geklickt wird?

    Ich hoffe ich bin hier im richtigen Unterforum.

    MfG



  • WM_LBUTTONDOWN kommt ja nur einmal wenn die linke Mousertaste gedrückt wird. Ich würde hier ein boolean Variable setzten, lmouse_gedrückt = TRUE. Wenn WM_LBUTTONUP kommt dann lmouse_gedrückt = FALSE, setzten. In einen anderen Threat würde ich dann die Variable abfragen und bei TRUE dann deine Funktion ausführen.



  • Danke für deine Antwort..
    Habe jetzt mal einen Zähler eingebaut und musste wirklich feststellen, dass immer nur einmal gezählt wird.
    Bin grad dabei entsprechend umzubauen und scheitere jetzt aber an dem neuen Thread. Ich bin noch Anfänger was c++ angeht und habe
    noch nicht mit Threads hantiert. Könntest du mir ein paar Ansätze geben? Außerdem kann man aus einem anderen Thread doch nicht einfach
    Variablen auslesen oder?

    MfG



  • Ich bin mir nicht sicher und in der MSDN wird es nicht explizit (aber implizit) gesagt, aber wenn du in der MouseProc MouseEvents generierst, dann besteht die Möglichkeit, dass auch der LL MouseHook davon erfährt. Worauf ich rauswill, du landest womöglich in einer Rekursion ohne Abbruchbedingung.
    EDIT: Ich seh gerade du hast das Problem selber erkannt, hatte mir deinen Beitrag nicht ganz durchgelesen alse das hier schrieb. Also: die MSDN sagt folgendes)

    MSDN zu LL Mouse Hook schrieb:

    The mouse input can come from the local mouse driver or from calls to the mouse_event function

    Ok hier wird mouse_event und nicht SendInput genannt. Aber:

    MSDN zu mouse_event schrieb:

    This function has been superseded. Use SendInput instead.

    "Ersetzt": könnte bedeuten (bzw. es ist sehr wahrscheinlich) dass SendInput genau das gleiche Verhalten wie mouse_event hat und somit auch den LL Mouse Hook aufruft.

    floorball



  • könnte so aussehen

    boolean lmouse_gedrückt = FALSE;		//irgendwo global festlegen
    
    /*
    ==============================================
    Go_Thread
    
    ==============================================
    */
    void Go_Thread(void){
    
    	while(1){
    		if(lmouse_gedrückt == TRUE){
    
    			//Hier deinen Kram einfügen
    
    		}
    		Sleep(60);
    	}
    	_endthreadex(0);
    }
    
    /*
    ==============================================
    Go_StartThread
    
    ==============================================
    */
    void Go_StartThread(void){
    
    	uintptr_t			TmpThread;
    	u_int			TmpThread_ID;
    
    	TmpThread = _beginthreadex(NULL, 0, (void *)Go_Thread, NULL, 0, &TmpThread_ID);
    	if(TmpThread){
    		CloseHandle((HANDLE)TmpThread);
    	}
    }
    

    Den Thread kannst du gleich zu Programmstart ausführen. Ist mit Sicherheit performancemäßig nicht die beste Entscheidung, aber so sollte es zumindest funktionieren.



  • Ähm ist wohl noch ein kleiner Denkfehler drinne. Der WM_LBUTTONUP Event kommt ja auch dann, wenn er künstlich von deiner Funktion erzeugt wurde. Ich weiss gerade nicht wie, aber irgendwie müsste man unterscheiden ob der Event von deiner Funktion oder wirklich von der Mouse kommt, gleiches gilt natürlich auch für WM_LBUTTONDOWN.



  • Diese Inputs sollen an ein Spiel(DirectX) gesendet werden. Mit SendInput klappt das auch, jedenfalls würde es dann so aussehen:
    LBUTTONDOWN(MAUS) -> LBUTTONDOWN(SIMULATION) -> LBUTTONUP(SIMULATION) -> lmbdown = false;
    Wie du schon erwähnt hast, müsste man unterscheiden können welcher Klick von der Maus stammt und welcher simuliert ist. Könnte man nicht
    eine Zusatzinformation (bspw. LParam) mitgeben und diesen im Hook auslesen und abfragen können?

    Außerdem hab ich ein Problem mit deinem zur verfügung gestellten Code. Ich hab ihn komplett so übernommen und process.h headerfile inkludiert.
    in der main dann auch aufgerufen. Ich bekomme jedoch vom Compiler einen Fehler ausgeschmissen.
    Bei

    TmpThread = _beginthreadex(NULL, 0, (void *)Go_Thread, NULL, 0, &TmpThread_ID);
    

    bekomme ich:

    [Error] invalid conversion from 'void*' to 'unsigned int ()(void)' [-fpermissive]

    Und im process.h headfile

    _CRTIMP uintptr_t __cdecl _beginthreadex(void *_Security,unsigned _StackSize,unsigned (__stdcall *_StartAddress) (void *),void *_ArgList,unsigned _InitFlag,unsigned *_ThrdAddr);
    

    bekomme ich:

    [Error] initializing argument 3 of 'uintptr_t _beginthreadex(void*, unsigned int, unsigned int ()(void), void*, unsigned int, unsigned int*)' [-fpermissive]

    angezeigt.

    MfG



  • Ok hat sich erledigt.. Hab mir die Meldung mal näher angeschaut und hab den void einfach in:
    unsigned int __stdcall Go_Thread(void 😉 abgeändert.

    Man muss doch aber irgendwie auch ExtraInformationen beim mausevent mitliefern können, die dann
    später ausgelesen werden können.


Anmelden zum Antworten