Einfügen in DBGrid aus Zwischenspeicher. Wie u wo Exception abfangen?



  • Du musst vermutlich einfach nur sicherstellen, dass Du Dich im richtigen Modus befindest: Edit oder Insert. Ein weiterer Stolperstein könnte sein, dass Du eine AutoInc-Variable in der Tabelle hast. A
    ußerdem sollte das Hinzufügen von identischen Datensätzen nicht möglich sein, falls doch, musst Du die Indizes überarbeiten. Du musst immer mindestens einen eindeutigen Index haben, ansonsten handelst Du Dir nur Probleme ein.



  • Hallo @Joe_M.,

    ich könnte bei den Events BeforeInsert bzw. BeforeEdit eingreifen. Das ist mir klar. Nur woher weiß mein Programm, dass
    der User soeben mit der rechten Maustaste die Zwischenablage benutzt hat. Mit dem Event OnKeyDown im DBGrid klappt das auch nicht, da kann ich nicht eingreifen.
    Dieser Event funktioniert nur, wenn man neben/unter dem Gitter klickt, wenn man in die Zellen klickt, kommt keine Reaktion. Ein Abfangen der rechten Maustaste ist somit nicht möglich.

    Soweit ich weiß, wird beim Einfügen aus dem Clipboard eine "WM_Paste"-Message versandt. Ich denke hier ließe sich was machen, ich weiß nur nicht wie diese Windowsmessage verwenden kann? Da bin ich "noch" überfordert.

    Hat jemand Rat und Hilfe?



  • Ob Daten über über die Zwischenablage kopiert werden, oder von Hand eingeben werden, ist vollkommen egal. Du hast ein konzeptionelles Problem.



  • Hallo

    Das Verarbeiten von Windows-Messages kannst du dir hier anschauen.
    Allerdings glaube ich wie Joe das du so nur an den Symptomen des Problems arbeitest, aber nicht an der eigentlichen Ursache.

    bis bald
    akari



  • Hallo @akari, hallo @Joe_M.

    @Akari Danke für den Link. Ich habe in den letzten krampfhaft Tagen versucht hier mit den Windows Messages weiter zu kommen, leider ohne Erfolg. Im Delphi-Forum konnte ich auch keine Lösung finden. Dort gibt es das gleiche Problem, scheinbar nicht lösbar.

    Du hast ein konzeptionelles Problem.

    Was heißt hier konzeptionelles Problem?

    Man nehme eine Form
    platziere darauf
    1 Verbindung zur Datenbank (hier: TADOConnection)
    1 DataSet (hier: ADODataSet)
    1 DataSource
    1 DBGrid.

    Man starte eine SQL-Abfrage in der Datenbank mit dem DataSet und fülle das DBGrid.
    Ich weiß nicht, was an diesem Konzept falsch sein kann. Man möge mich belehren. 😕

    Jetzt nochmal zu meinem Problem:
    Wenn die Daten im Gitter stehen, soll der User die Daten editieren, einfügen, löschen dürfen, logo!
    Wenn der User per Tastatur die Eingaben durchführt funktioniert alles prima.

    Ich filtere die Usereingaben mit einer kleinen angepaßten Funktion und prüfe auf korrekte Eingabeform im Event BeforePost. Das klappt wunderbar.

    Ich kann nur nicht verhindern, dass der User irgendeinen Quatsch per Zwischenablage eingibt. Leider sieht das DBGrid die Zwischenablage vor. Ich weiß nicht wie ich das kontrollieren oder abschalten kann.
    Nur wenn der User per Zwischenablage einfügt erhalte ich die Exceptions. Das ist extrem unschön und unprofessionell.

    Sowie es aussieht geht diese Eingabe über Zwischenspeicher auch an dem Event BeforePost vorbei, denn ansonsten müßte die Eingabe über meine Prüfroutine gefiltert werden und durchfallen, was sie aber nicht macht

    Sorry, also ich weiß hier wirklich nicht mehr weiter, wie ich das unterbinden soll.



  • Möchtest du denn generell das Einfügen über die Zwischenablage verhindern (d.h. sowohl das Menü ausblenden als auch Strg+V unterbinden) oder aber nur, wenn inkorrekte Daten in der Zwischenablage sind?

    Ich filtere die Usereingaben mit einer kleinen angepaßten Funktion und prüfe auf korrekte Eingabeform im Event BeforePost. Das klappt wunderbar.

    Wie sieht denn diese Abfrage aus?



  • Hallo @~Clipboard,

    Vielleicht hast Du eine Idee, wie ich die Zwischenablage abfangen kann? Am besten wäre natürlich ich könnte direkt auf die Eingabe zugreifen, wenn der User seine Einfügungen (PASTE) im DBGrid durchgeführt hat.
    Dann könnte ich mit einer Funktion eingreifen.
    Wenn das nicht geht, na dann halt die Zwischenablage sperren, wie auch immer, mit Balken, Ketten oder Sonstigem 😃

    Im folgenden, wie von Dir gewünscht, stelle ich 'mal mein DB-Problem vor. Der Verständlichkeit halber ist der gezeigten Ablauf natürlich stark gegenüber dem Programm reduziert.

    Mit einem Klick auf einen Radiobutton hole ich unterschiedliche gewünschte Datenmengen mit SQL-Abfrage in ein DataSet. Das DataSet maskiere ich dann um den User anzuzeigen, wie die Eingabe zu erfolgen hat.
    Das DBGrid besteht nur aus einer Spalte. Es sollen hier Grunddaten verwaltet werden, mit einer strikten Eingabekontrolle.

    Das sieht dann in etwa so aus:

    void __fastcall TForm1::RadioGroup1Click(TObject *Sender){
    TRadioGroup* rG = dynamic_cast<TRadioGroup*>(Sender);
    BasisFeld wahl; // =>enum {feld1typ, feld2typ,... }
      wahl = (BasisFeld)(rG->ItemIndex);               
      switch (wahl){
      case feld1typ: BasicData(rG->ItemIndex); //Routine holt die Daten aus einer Datenbank-Tabelle
        		     ADODataSet1->Fields->Fields[0]->EditMask = ">AAAAAAAAAAAAAAA;0;_"; //Eingababmaske
        		     break;
      case feld2typ: BasicData(rG->ItemIndex);
                     //...
    }
    

    Die Prüfung, ob die Eingaben konform sind werden hier nach der Eingabe durch den User durchgeführt

    void __fastcall TForm1::ADODataSet1BeforePost(TDataSet *DataSet){
    BasisFeld wahl; 
    bool okay;
      AnsiString Eingabe = DBGrid1->SelectedField->AsString;
      wahl = (BasisFeld)(RadioGroup1->ItemIndex);
      switch (wahl){
        case feld1typ : okay = Checkfeld1typ(Eingabe); break;
        case feld2typ : okay = Checkfeld2typ(Eingabe); break;
       //... 
        default       : ;
      };  //switch
      if (!okay){
        ShowMessage("hier erfolgt spezielle Fehlermeldung");
        DataSet->Cancel();     //falsch also den alten Eintrag zurückschreiben
        Abort();               //springt aus Routine, Dateneintrag wird abgebrochen
      }                           
      else
        DBGrid1->SelectedField->AsString = Eingabe; //alles in Ordnung, Eintragen
    }
    

    Hier dann eine meiner Prüffunktionen, mit der eventuell noch das ausgefiltert/korrigiert werden kann, was die Eingabemaske durchläßt (wäre hier nicht nötig, da in der Maske bereits gut abgesichert)

    //löscht aus einem String alle Zeichen, außer A...Z, a..z, 0..9, sowie " "
    bool TForm1::Checkfeld1typ(AnsiString &s) { //so oder so ähnlich sind meine Prüffunktionen aufgebaut
    char c;
      AnsiString ts = s;
      int len = ts.Length();
      if (len < 1) return false; //keine Leerstrings zulassen
      int j = 1;
      while (j < len + 1) {
        c = (char)ts[j];
        if (isdigit(c) || isalnum(c) || (c == ' '))  j++;
        else {
          ts.Delete(j, 1);
          len--;
        }
      };
      len = ts.Length();
      if (len > 0) {
        s = ts;
        return true;
      }
      else
        return false;
    }
    




  • Sorry, daß ich jetzt erst wieder schreibe.

    Also an deinem Code fällt mir als erstes auf, daß du in der BeforePost-Methode direkt auf das DBGrid anstatt auf das übergebene Dataset zugreifst.

    Versuch mal:

    AnsiString Eingabe = DataSet->Fields->Fields[0]->AsString;
    

    Und für das Sperren der Zwischenablage gibt es verschiedene Möglichkeiten:
    - eigenes Popup-Menü für DBGrid hinterlegen
    - Tastatur abfragen (OnKeyDown): bei Ctrl+V "Key = 0" setzen

    Aber was ich noch nicht verstehe, wieso die Eingaben über die Zwischenablage an deinem Programm vorbei gehen und direkt in der DB landen?



  • Hallo @Jansen, @~Clipboard,

    vielen Dank für Eure Tipps u den Link.

    Mittlerweile habe ich festgestellt, dass das Problem mit der Zwischenablage vor allem dann auftritt, wenn ich mein Feld mit EditMask versehen habe.
    Ohne Maske funktioniert (auch) die Zwischenablage.

    Ich komme hier momentan nicht so richtig weiter. Ich lasse deshalb zuerst mal dieses Problem links liegen, indem ich Maskierungen mit EditMask lösche und verfeinere dafür meine Eingabekontrolle per Funktionen.


Anmelden zum Antworten