Cursor-Funktionen und system()-Befehle



  • Hallo,

    Ich beschäftige mich seit kurzer Zeit mit den Mausfunktionen in der Console (also X,Y,rechtsclick und linksclick).

    Nur treten da einige Probleme auf:

    1. Beim Aufruf der Funktion wartet das Programm, wenn es keine Aktion gibt - Das habe ich mit diesem Code rausgefunden:

    Mache Beep die ganze Zeit und wenn sich die Maus bewegt, gib die Koordianaten aus. Wenn eine Taste gedrückt wurde, gib deren Zustände aus.

    #include <windows.h>
    #include <iostream>
    using namespace std;
    
    INPUT_RECORD InRec;
    DWORD NumRead;
    
    int main()
    }
        while (1)
        {
                ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE),&InRec,1,&NumRead);
                if (InRec.Event.MouseEvent.dwEventFlags == 0)
                    {
                        if (InRec.Event.MouseEvent.dwButtonState & 0x01)
                            cout << "Left: Down" << endl;
                        else
                            cout << "Left: Up"  << endl;
                        if (InRec.Event.MouseEvent.dwButtonState & 0x02)
                            cout << "Right: Down" << endl;
                        else
                            cout << "Right: Up"  << endl;
                    }
                    else if (InRec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
                    {
                        cout << "Coord: " <<
                                InRec.Event.MouseEvent.dwMousePosition.X << "," <<
                                InRec.Event.MouseEvent.dwMousePosition.Y << "  " << endl;
                    }
                    Beep(440,150);
            }
    
        return 0;
    }
    

    Da ich mal darüber hinwegsehen kann habe ich eine Headerdatei gemacht, um das ganze zu vereinfachen:

    #ifndef MGLIB
    #define MGLIB
    
    #include <iostream>
    #include <windows.h>
    
    INPUT_RECORD InRec;
    DWORD NumRead; 
    DWORD Written;
    HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    
    namespace mglib {
    void cls(void){
         COORD pos = {0,0};
         FillConsoleOutputCharacter(hOut,' ',80*80,pos,&Written);
    }
    int lclick(void){
         ReadConsoleInput(hIn,&InRec,1,&NumRead);
         if (InRec.Event.MouseEvent.dwButtonState & 0x01)
            return 1;
            else
            return 0;               
    }          
    int rclick(void){
         ReadConsoleInput(hIn,&InRec,1,&NumRead);
         if (InRec.Event.MouseEvent.dwButtonState & 0x02)
            return 1;
            else
            return 0;
    
    }          
    int mousex(void){
         ReadConsoleInput(hIn,&InRec,1,&NumRead);
         return InRec.Event.MouseEvent.dwMousePosition.X;
    } 
    int mousey(void){
         ReadConsoleInput(hIn,&InRec,1,&NumRead);
         return InRec.Event.MouseEvent.dwMousePosition.Y;
    }
    }
    #endif
    

    Das funktioniert auch soweit, deshalb habe ich ein kleines Mal-Programm gemacht:

    #include <iostream>
    #include <windows.h>
    #include <conio.h>
    
    #include "mglib.h"
    using namespace std;
    using namespace mglib;
    
    int main (void){
        int x,y;
        while (1)
        {
                x = mousex();
                y = mousey();
                if (lclick()){
                              gotoxy(x,y);
                              cout << "O";
                              }
                else if (rclick()){
                     gotoxy(x,y);
                     cout << " ";
                }
                if ((x==0)&&(y==0)&& lclick())
                cls();
    
        }
        getch();
        return 0;
    }
    

    So, und jetzt das 2. Problem:

    Wie oben zu sehen, habe ich eine Clear-Funktion gemacht, da alle system() also auch system("cls") nicht funktioniern bzw. die Cursorfunktionen lahm legen.

    Also
    1. Unterbrechen des Programms beim Aufruf der Funktionen
    2. System()-Befehle

    Was kann ich dagegen tun?



  • Wenn es Dich stört, daß ReadConsoleInput nicht zurückkehrt, so lange nichts passiert, kannst Du zunächst mit PeekConsoleInput nachsehen, ob Daten vorhanden sind. PeekConsoleInput kehrt sofort zurück, auch wenn keine Daten zu lesen sind.

    Dein anderes Problem verstehe ich nicht. Du hast eine Funktion zum Bildschirmlöschen geschrieben, gut ... was willst Du mit system?

    Im übrigen glaube ich nicht, daß Deine Abfragen besonders geschickt sind. Du rufst zum Beipiel ReadConsoleInput auf, um die X-Position der Maus abzufragen. Bei diesem Aufruf wird das Event entfernt. Um nun die Y-Position in Erfahrung zu bringen, rufst Du erneut ReadConsoleInput auf, das aber wartet natürlich nun erst mal auf neue Daten, die alten hast Du ja schon "weggelesen".
    Des weiteren unterstellst Du einfach, daß ein Maus-Event aufgetreten ist, und liest aus der entsprechenden Struktur, ohne vorher zu prüfen, ob wirklich die Maus das vorliegende Input-Event ausgelöst hat ...
    Diese Input-Events können doch auch von der Tastatur oder anderen Dingen:
    http://msdn.microsoft.com/en-us/library/ms683499(v=VS.85).aspx
    ausgelöst werden ...



  • Danke für die Antwort!

    Die clear-Funktion von mir ist bestimmt 100x langsamer als die system("cls"), man merkt richtig wie der Bildschirm flackert. Also suche ich eine Alternative - sowie für die Funktion system("color xx"), da diese auch Probleme auslöst.

    Ich möchte aber auch auf x und y Koordianaten der Maus zugreifen, wenn sich nichts geändert hat (kein Event).

    Die Funktionen hab ich absichtlich so geschrieben, dass man sie auch in anderen Programmen einzeiln aufrufen kann.



  • Deine Clear - Funktion ist okay, sie ist zwar limitiert, weil Du von vornherein den Bereich festlegst, den Du löschen willst, aber wenn sie Deine Zwecke erfüllt, ist das schon gut so. Wenn der Bildschirm flackert, dann liegt es sicher an was anderem.

    Allerdings weiß ich nicht, was passiert, wenn Du zuviel in die Konsole schreibst, deshalb solltest Du die Größe des ScreenBuffers vorher ermitteln, dann schreibst Du immer genau die richtige Anzahl Leerzeichen.

    system ("color") kenn ich nicht, was soll das machen? Auch das kannst Du mit Sicherheit innerhalb Deines Programmes mit den passenden Konsolefunktionen lösen. Wenn es um Farben (Text und/oder Hintergrund) geht, sieh Dir mal die Funktionen mit Attribute im Namen an, also zB SetConsoleTextAttribute

    Auf die Mauskoordinaten kannst Du nicht zugreifen, wenn Du kein Event hast, kein Event --> kein INPUT_RECORD --> keine Information.

    Und noch mal: ReadConsoleInput liest ein Event und entfernt es. Wenn Du nun nur eine einzige Information daraus verwertest, zB die X-Position, dann hast Du auch nur diese. Der nächste Aufruf von ReadConsoleInput liefert Dir doch dann einen neuen Event, Deine Methode, die Daten zu holen, liefert Dir also eine X-Position und eine Y-Position, die gar nicht zusammengehören, da sie aus zwei verschiedenen Events stammen.

    Und auch noch mal: Wenn Du auf eine Taste drückst, wird auch ein Event ausgelöst, Du gehst aber immer davon aus, daß ein Maus-Event vorliegt, das kann doch nicht zu vernünftigen Ergebnissen führen. Du liest via Zugriff auf MouseEvent Speicherbereich aus, der unter Umständen mit Daten vom Typ KeyEvent oder eines der anderen möglichen Typen gefüllt ist.



  • Danke. Ich werde versuchen, beide Funktionen zu optimieren.

    System("color xx") legt die aktuelle Farbe der Konsole fest, also auch von dem, was schon da steht. Mit SetConsoleTextAttribute wird nur die Farbe der nächsten Ausgabe geändert.



  • MGOS schrieb:

    System("color xx") legt die aktuelle Farbe der Konsole fest, also auch von dem, was schon da steht.

    Das kannst Du mit FillConsoleOutputAttribute machen, so ähnlich wie bei FillConsoleOutputCharacter - für alle im Screen Buffer befindlichen Zeichen das Attribut neu setzen.
    Auch hier ist es besser, nicht einfach 80*80 Zeichen zu unterstellen, sondern die Größe des Screenbuffers erst zu ermitteln.



  • Danke, dann werde ich es so machen.



  • MGOS schrieb:

    Danke, dann werde ich es so machen.

    Wenn du dir aus der FAQ die Improved Console downloadest kannst du die Implementierung von vielen solcher Funktionen direkt ansehen.

    MfG SideWinder


Anmelden zum Antworten