SendInput Unerschiede je nach Ziel(anwendung)?



  • Hallo,

    die Überschrift klingt vieleicht etwas blöd, aber sie trifft mein Problem, vor dem ich gerade stehe. Ich habe eine Software geschrieben, die Tastatur- und Mauseingaben simuliert und so Software von Drittanwendungen fernsteuern kann. Da der ganze Code reichlich umfangreich ist, habe ich das Problem in ein extra Projekt gepackt und hoffe hier auf Hilfe.

    Der folgende "Demo"-Code (Sorry für die Länge, ich habe ihn auch extra gut kommentiert, damit man ihn schneller lesen kann, zwischen den Pfeilen vermute ich das für mich noch nicht nachvollziehbare Problem) soll folgende Aufgabe erfüllen: Er soll das Wordfenster maximieren, "Hallo" eingeben, das ganze Wort auf einmal markieren (Strg+Alt+Pfeil links), die Farbpalette aufrufen, die Farbe rot auswählen und die Markierung wieder aufheben.

    Das Problem: Der folgende Code funktioniert einwandfrei unter WinXP mit Word 2003. Er funktioniert nur eingeschränkt unter WinXP mit Word2000 sowie Win2000 mit Word2000. Eingeschränkt heißt, das Wort "Hallo" wird nicht markiert. Scheinbar wird die Tastenkombi Strg+Alt+Pfeil links in Word2000 nur als Strg+Pfeil links umgesetzt, denn der Cursor springt von der Position hinter dem "o" vor das "H", markiert das Wort aber nicht. Habe das Problem daher bei Word vermutet, aber wenn ich es manuell selber mache, dann funktioniert es auch.
    Scheint also evtl. doch ein Problem in meinem Code zu sein, aber dann verstehe ich nicht, warum es unter Word2003 funktioniert.

    Danke für Eure Ideen, bin für jede dankbar.

    P.S: An den Sleeps()'s liegt es nicht, das Problem bleibt das gleiche, wenn ich sie wegnehme, habe sie nur eingebaut, um das ganze nachvollziehen zu können, während es abläuft.

    void __fastcall TForm1::Button_StartClick(TObject *Sender)
    {
       InputData.type = INPUT_KEYBOARD;
       InputData.ki.wVk = 0;
       InputData.ki.wScan = 0;
       InputData.ki.dwFlags = 0;
       InputData.ki.time = time(NULL);
       InputData.ki.dwExtraInfo = 0;
    
       hWnd = FindWindow(NULL, "Dokument1 - Microsoft Word");
       ShowWindow(hWnd,SW_MAXIMIZE);
       SetActiveWindow(hWnd);
       SetForegroundWindow(hWnd);
       ::Sleep(1000);
    
       if(hWnd == GetForegroundWindow())
       {
          //Shift drücken
          InputData.ki.wVk = VK_SHIFT;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste H drücken und wieder loslassen
          InputData.ki.wVk = 0;
          InputData.ki.wScan = 35;
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Shift wieder loslassen
          InputData.ki.wVk = VK_SHIFT;
          InputData.ki.wScan = 0;
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste a drücken und wieder loslassen
          InputData.ki.wVk = 0;
          InputData.ki.wScan = 30;
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste l drücken und wieder loslassen
          InputData.ki.wVk = 0;
          InputData.ki.wScan = 38;
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste l ein zweites Mal drücken und wieder loslassen
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste o drücken und wieder loslassen
          InputData.ki.wVk = 0;
          InputData.ki.wScan = 24;
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
      :arrow_right: 
    
          //ab hier besteht das Problem, dass die 3er Tastenkombi
          //Shift + Strg + Pfeiltaste in Word2000 nicht erkannt wird.
          //Der Cursor bewegt sich zwar Wortweise (Strg+Pfeil),
          //aber die Markierung (Shift) erfolgt in Word2000 nicht, in Word2003 schon
    
          //Shift drücken
          InputData.ki.wVk = VK_SHIFT;
          InputData.ki.wScan = 0;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Strg drücken
          InputData.ki.wVk = VK_LCONTROL;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Pfeiltaste links drücken
          InputData.ki.wVk = VK_LEFT;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Pfeiltaste wieder loslassen
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //irgendwo bis hier muss der Fehler liegen,
          //wenn es denn ein Fehler ist ???
    
      :arrow_right: 
    
          //Strg wieder loslassen
          InputData.ki.wVk = VK_LCONTROL;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Shift wieder loslassen
          InputData.ki.wVk = VK_SHIFT;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Alt drücken
          InputData.ki.wVk = VK_MENU;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste t drücken und wieder loslassen
          InputData.ki.wVk = 0;
          InputData.ki.wScan = 20;
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Alt wieder loslassen
          InputData.ki.wVk = VK_MENU;
          InputData.ki.wScan = 0;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste z drücken und wieder loslassen
          InputData.ki.wVk = 0;
          InputData.ki.wScan = 21;
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Menü wird aufgerufen -> warten
          ::Sleep(2000);
    
          //Alt drücken
          InputData.ki.wVk = VK_MENU;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Taste f drücken und wieder loslassen
          InputData.ki.wVk = 0;
          InputData.ki.wScan = 33;
          InputData.ki.dwFlags = KEYEVENTF_SCANCODE;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Alt wieder loslassen
          InputData.ki.wVk = VK_MENU;
          InputData.ki.wScan = 0;
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Pfeiltaste unten drücken und wieder loslassen
          InputData.ki.wVk = VK_DOWN;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Pfeiltaste unten ein zweites Mal drücken und wieder loslassen
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Pfeiltaste unten ein drittes Mal drücken und wieder loslassen
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Return drücken und wieder loslassen
          InputData.ki.wVk = VK_RETURN;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          // TAB drücken und wieder loslassen
          InputData.ki.wVk = VK_TAB;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Return drücken und wieder loslassen
          InputData.ki.wVk = VK_RETURN;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
    
          //Pfeiltaste rechts drücken und wieder loslassen
          InputData.ki.wVk = VK_RIGHT;
          InputData.ki.dwFlags = 0;
          SendInput(1, &InputData, sizeof(InputData));
          InputData.ki.dwFlags = KEYEVENTF_KEYUP;
          SendInput(1, &InputData, sizeof(InputData));
          ::Sleep(150);
       }
    }
    

  • Mod

    Und warum machst Du es nicht viel einfacher mit Office-Automation anstatt zum senden von Tastaturbefehlen zu greifen?



  • Martin Richter schrieb:

    Und warum machst Du es nicht viel einfacher mit Office-Automation anstatt zum senden von Tastaturbefehlen zu greifen?

    Wie bereits im Eröffnungposting geschrieben, ist dies nur ein Democode, der extra dafür geschrieben wurde, um das Problem darzustellen. Meine Software soll durch Tastatur- und Mauseingaben JEDE andere Software steuern können (was sie bisher schon mit einem halben Dutzend Fremdanbietersoftware eindrucksvoll bewiesen hat). Wenn ich jedoch jetzt auf eine Software stoße, bei der die Umsetzung nicht vollständig funktioniert, dann kann ich auch nicht ausschließen, dass es evtl. noch mehrere Anwendungen gibt, bei der meine Steuerungscodes nicht umgesetzt werden können.
    Ein Problem, dass nicht auftreten darf, denn was man manuell über die Tastatur eingeben kann, muss man auch simulieren können.
    Und da die manuelle Eingabe Strg+Alt+Pfeil links auch unter Word2000 funktioniert, muss sie auch über SendInput funktionieren können.

    Und wenn ich den Fehler in meinem Code finde, zumindest gehe ich davon aus, dass dort der Fehler liegt, dann kann ich das Problem auch generell beheben, unabhängig von der zu steuernden Software.


Anmelden zum Antworten