Entwickler-Ecke
Grafische Benutzeroberflächen (VCL & FireMonkey) - In TEdit nur ein Komma und Zahlen erlauben
Biarchiv - Do 15.06.06 20:50
Titel: In TEdit nur ein Komma und Zahlen erlauben
Hallo,
folgender Coder erlaubt das man nur Zahlen von 0-9 und Komma "," in
ein TEdit schreiben darf.
Allerdings wie würde das funktionieren damit die TEdit nur ein Komma akzeptiert und
ein weiteres nicht annimmt.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| var SS,SL,i,i1,f:integer; Buf:string; begin f := 0; with Sender as TEdit do begin SS:=SelStart; SL:=SelLength; SetLength(Buf,0); for i:=1 to length(Text) do if Text[i] in (['0'..'9',',']) then begin for i1:=1 to length(Text) do if Text[i] = ',' then f := f + 1; if (f >= 3) then break; Buf:=Buf+Text[i]; end; Text:=Buf; SelStart:=SS; SelLength:=SL; end; |
Marc. - Do 15.06.06 20:55
hallo,
warum prüfst du nicht einfach schon bei der Eingabe, ob bereits ein Komma enthalten ist?
Würde dann wie folgt aussehen:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); begin if key = ',' then if pos(',', edit1.Text) <> 0 then begin key := #0; end;
if not (key in ['0'..'9', ',' , #8]) then begin key := #0; end; end; |
mkinzler - Do 15.06.06 20:56
Du könntest es auch mit einem TMaskedEdit versuchen.
aim65 - Fr 16.06.06 10:57
@ NoTVerYEvilPzYchO
"edit.text" mag der Compiler ganz und gar nicht - erwartet sowas wie "edit1.text".
Daher ist der Ansatz leider nicht universell zu gebrauchen. :(
Marc. - Fr 16.06.06 18:37
@ aim65
er soll den Code ja auch nicht kopieren, sondern verstehen. Der Code selbst stammt aus meinem alten Taschenrechner. Ich hoffe allerdings, dass seine Edits nicht durchnummeriert sind, sondern entsprechende, sinnvolle Namen haben, die Rückschluss auf ihre Funktion geben. Ist das der Fall, muss er so oder so den Code anpassen.
Damit er allerdings jetzt universell brauchbar ist, habe ich den Quellcode entsprechend editiert :)
aim65 - Sa 17.06.06 10:48
@ NoTVerYEvilPzYchO
Ist mir schon klar.
Mein "universell nicht brauchbar" bezog sich auf die KeyPress-Routine und die Tatsache, daß man bei der von Dir angeführten Methode immer nur EIN bestimmtes Editfeld auf doppeltes Dezimalzeichen abfragen kann. Wenn ich nun z.B. 20 Eingabefelder habe, die über die Keypress-Routine bedient werden sollen, geht's halt so nicht. Ich habe bisher noch keine gute Lösung für das Abfangen des doppelten Dezimalzeichens innerhalb einer allgemeingültigen KeyPress-Abfrage gefunden. Scheitert immer wieder an der Backspace Problematik. Kennst Du eine? (ohne Bezug auf bestimmte Editfelder).
P.S. Ich verwende mittlerweile immer "DecimalSeparator" statt Komma oder Punkt. Mache ich, weil meine Progrämmchen auch auf englischen Versionen laufen sollen. Hab mal meine "Universal"-Routine hier kopiert, leider ohne Lösung des o.g. Problems ( :oops: für's Englisch).
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| begin if not (Key in [#8,'0'..'9']) then if Key in [',','.',';',':'] then Key := DecimalSeparator else if Key =#13 then begin Perform(WM_NEXTDLGCTL, 0, 0); Key := #0; end else Key := #0; end; |
Edit: Mein Kram geht wohl haarscharf am Thema vorbei, da Biarchiv ja wohl nur ein Edit-Feld braucht... :oops:
Born-to-Frag - Sa 17.06.06 10:54
Hallo!
Man kann doch statt
if Pos(',', Edit1.Text) > 0 ...
einfach
if Pos(',', (Sender as TEdit).Text) > 0 ...
nehmen, dann kann man für jedes Edit das gleiche KeyPress Ereignis verwenden, oder hab ich das jetzt falsch verstanden?
greetz
aim65 - Sa 17.06.06 11:09
@ Born-to-Frag
WARUM HAT MIR DAS KEINER VOR EINEM JAHR GESAGT??
Spaß beiseite - manchmal hat man wirklich eine ganze Bretterwand vor'm Kopp :autsch: :autsch:
Werde gleich Dein Zeilchen in meinen Kram einfügen, danke für den Tip. :dance:
(Mann, kann's immer noch nicht fassen - so alt und noch so beschränkt.. :evil: )
Biarchiv - Mo 19.06.06 21:35
Hallo,
fällt jamanden auch eine Lösung zo OnChange ein?
Sonst müßte ich alles Umbauen.
Mein Vorschlag läuft leider nicht.
Hier will ich prüfen ob schon ein , komma trin ist, wenn ja dann nur Zahlen akzeptieren.
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| var SS,SL,i,i1:integer; Buf:string; ifkomma : Boolean; begin with Sender as TEdit do begin SS:=SelStart; SL:=SelLength; SetLength(Buf,0); for i:=1 to length(Text) do begin showmessage(inttostr(pos(',', Text))); if (pos(',', Text) > 0) then ifkomma := true else ifkomma := false; if ifkomma = false then begin if Text[i] in ((['0'..'9',','])) then Buf:=Buf+Text[i]; end; if ifkomma = true then begin if Text[i] in ((['0'..'9'])) then Buf:=Buf+Text[i]; end; end; Text:=Buf; SelStart:=SS; SelLength:=SL; end; |
aim65 - Mo 19.06.06 23:46
Gibt es denn einen triftigen Grund, "OnChange" für dein Edit-Feld zu benutzen? (Außer, daß du evtl. bei einigen Edits das Ereignis von OnChange auf OnKeyPress ändern mußt).
Die KeyPress-Routine erschlägt doch deine Frage mit nur wenigen Zeilen, weil hier ein unerwünschtes Zeichen schon vorher abgefangen werden kann, bevor es im Edit erscheint. Bei deiner Methode kommt ein unerwünschtes Zeichen ja noch "durch" und müßte dann wieder aus dem String entfernt werden - abgesehen von der Komplexität deines Ansatzes.
Ehrlich gesagt, steige ich auch nicht so ganz durch deine Routine... :gruebel:
Du kannst jedenfalls alles, was du mit OnChange machen kannst, auch mit KeyPress erschlagen - und das mit wesentlich weniger Code.
Biarchiv - Di 20.06.06 16:50
aim65 hat folgendes geschrieben: |
Gibt es denn einen triftigen Grund, "OnChange" für dein Edit-Feld zu benutzen? (Außer, daß du evtl. bei einigen Edits das Ereignis von OnChange auf OnKeyPress ändern mußt).
Die KeyPress-Routine erschlägt doch deine Frage mit nur wenigen Zeilen, weil hier ein unerwünschtes Zeichen schon vorher abgefangen werden kann, bevor es im Edit erscheint. Bei deiner Methode kommt ein unerwünschtes Zeichen ja noch "durch" und müßte dann wieder aus dem String entfernt werden - abgesehen von der Komplexität deines Ansatzes.
Ehrlich gesagt, steige ich auch nicht so ganz durch deine Routine... :gruebel:
Du kannst jedenfalls alles, was du mit OnChange machen kannst, auch mit KeyPress erschlagen - und das mit wesentlich weniger Code. |
Ja, es sind ca. 500 Edits.
Warscheinlich muss ich es eh ändern.
Ich hab zu dumm, leider in der OnChange angefangen.
Lannes - Di 20.06.06 23:47
aim65 hat folgendes geschrieben: |
...Du kannst jedenfalls alles, was du mit OnChange machen kannst, auch mit KeyPress erschlagen - und das mit wesentlich weniger Code. |
wie behandelst Du das einfügen von Text über das Kontextmenü.
Und was ist mit Strg+V und Umschalt+Insert? Fängst Du das auch ab,
dann unterbindest damit eine gewünschte Funktionalität.
Schlage mal das folgende vor:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| sFloat : String = '0'; procedure TForm1.Edit1Change(Sender: TObject); var E: Extended; begin if TextToFloat(PChar(Edit1.Text), E, fvExtended) then sFloat := Trim(Edit1.Text) else begin Edit1.Text := sFloat; Edit1.SelStart := Length(Edit1.Text); end; end; |
Bei 500 Edits :roll: kann statt der Variable sFloat ein Array of String entsprechend genutzt werden.
aim65 - Mi 21.06.06 12:33
@ Lannes:
:shock: Klar, hast recht, wenn man nicht nur eine reine Tastatur-Eingabe sondern auch copy+paste usw. berücksichtigt. Ich war nur von der Tastatureingabe ausgegangen.
Dein eleganter Ansatz mit TextToFloat war mir neu - hab's gleich mal ausprobiert.
Dabei habe ich festgestellt, daß die erste Ziffer nicht mehr gelöscht werden kann. Wenn das erste Zeichen ein '-'(minus) oder ein nicht zulässiges Zeichen ist, erscheint eine '0', die ebenfalls nicht mehr löschbar ist. Hab ich was übersehen? :gruebel:
@ Biarchiv:
500 Edits - das riecht nach Arbeit, egal was du nimmst... :mrgreen:
Edit: Hatte übersehen, daß sFloat ja mit '0' initialisiert wird. ABER, wieso akzeptiert die Routine kein (führendes) Minuszeichen?
aim65 - Mi 21.06.06 13:34
Da bin ich schon wieder... :P
Hab' mal mit Lannes' Routine weiter herumgespielt und noch folgende Erkenntnisse gewonnen:
1) Was Erfreuliches:
Man kann die Procedure auf mehrere Edit-Felder anwenden, wenn man Born-to-Frag's Tip mit "(Sender as TEdit)" überall statt "Edit1" einbaut.
2) Man kann über Copy&Paste auch eine Zahl mit Minuszeichen einfügen, die auch richtig in der Variablen E weiterverarbeitet wird. Allerdings bleiben bei einem Löschversuch mit Backspace jetzt das '-' UND die nächste Ziffer stehen.
3) Bei der Weiterverarbeitung von E (ich hab einfach mal E*E genommen) gibt es beim Versuch, die erste (oder besser die letzte verbleibende) Ziffer zu löschen, die nette Meldung "Fehler bei Fließkommaoperation".
Habe selber (bis auf 1) noch nichts in der Procedure verändert. Wat nu? :roll:
Lannes - Mi 21.06.06 15:12
aim65 hat folgendes geschrieben: |
...ABER, wieso akzeptiert die Routine kein (führendes) Minuszeichen? |
nur wenn das '-' Zeichen als erstes eingegeben wird.
Halt mal den Code erweitern um eine zusätzliche Bedingung:
Delphi-Quelltext
1:
| if (Text = '-') or (TextToFloat(PChar(Text), E, fvExtended)) then |
aim65 hat folgendes geschrieben: |
...Da bin ich schon wieder... |
zu 1.
klar geht das :wink: siehe unten
zu 2.
Bedingung (Text = '') eingebaut und keine Vorbelegung mit '0'
zu 3.
Die Variable E ist nur für die Funktion TextToFloat eingebaut.
Wenn man mit E rechnen willst, dann nur wenn Edit.Text nicht leer ist.
Hier ein allgemeiner und verbesserter Code damit man ihn für viele Edits einsetzen kann.
Dazu alle Edits in der Tag-Eigenschaft von 0 bis X durchnummerieren und ein Array zur Zwischenspeicherung verwenden. Die Procedure allen Edits als Event-Handler für OnChange zuweisen. Der Code sieht dann in etwa so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| sFloatArr : Array [0..9] of String; procedure TForm1.AllEditChange(Sender: TObject); var E: Extended; begin with TEdit(Sender) do if (Text = '') or (Text = '-') or (TextToFloat(PChar(Text), E, fvExtended)) then begin sFloatArr[Tag] := Trim(Text); if Text <> sFloatArr[Tag] then begin Text := sFloatArr[Tag]; SelStart := Length(Text); end; if Text <> '' then end else begin Text := sFloatArr[Tag]; SelStart := Length(Text); end; end; |
aim65 - Mi 21.06.06 17:15
Komme gerade vom Rasenmähen (muß ja auch mal sein... )
Gleich mal deine Routine ausprobiert: Na, geht doch... :lol:
Zitat: |
nur wenn das '-' Zeichen als erstes eingegeben wird. |
Alles andere macht ja bei einer Eingabe keinen Sinn.
Nur der Vollständikeit halber: in Zeile 15 muß es heißen
Delphi-Quelltext
1:
| if (Text <>'') and (Text <>'-') then |
(ich weiß, nur wenn man in der Routine selbst weiterrechnen will).
Da ich nicht so fit bin, noch eine Verständnisfrage: Bei welchen Anwendungen ist der Tag-Array sinnvoll?
Konnte jedenfalls bei mehreren Edit-Feldern ohne die Tags keine Probleme feststellen.
Dachte hierbei an Biarchiv :mrgreen:
Jedenfalls, prima Lösung, hab's schon in meine Sammlung aufgenommen.
Lannes - Mi 21.06.06 19:30
aim65 hat folgendes geschrieben: |
...Da ich nicht so fit bin, noch eine Verständnisfrage: Bei welchen Anwendungen ist der Tag-Array sinnvoll?
Konnte jedenfalls bei mehreren Edit-Feldern ohne die Tags keine Probleme feststellen. |
in dem Array wird über die Tag-Eigenschaft der Edits als Index für jedes Edit der letzte gültige Wert zwischengespeichert. Sonst würde bei einer Fehleingabe (als erste Eingabe) der letzte gültige Wert, der in einem anderen Edit eingegeben wurde, in das aktuelle Edit gesetzt. Außerdem hat das den Vorteil, das die Werte für weitere Überprüfungen, Berechnungen usw in einem Array vorliegen.
Alternativ kann mit nur eine Variable gearbeitet werden, wenn zusätzlich in einem allgemeinen Event-Handler für das Ereignis OnEnter der Wert zwischengespeichert wird.
aim65 - Mi 21.06.06 19:48
Danke für die Info
Biarchiv - Mo 26.06.06 11:05
Hallo,
danke Lannes der Code funktioniert sehr gut.
Nur ein kleinen Fehler hat er noch.
Er soll fals TEdit leer ist einfach 0,00 reinschreiben da es sonst
zu einen flaschen Gleitkommawert kommt.
aim65 - Mo 26.06.06 11:18
Ich würde das oder die Editfelder in Form.Create/Activate mit '0,00' initialisieren.
Dann diesen Code-Teil von Lannes' Routine verändern:
Delphi-Quelltext
1: 2: 3: 4: 5:
| with TEdit(Sender) do if Text='' then Text:='0,00' else if (Text = '-') or (TextToFloat(PChar(Text), E, fvExtended)) then begin.... |
Dann wird beim Löschen des Feldes automatisch '0,00' gesetzt.
Edit: :oops: Sorry, ist absoluter Käse, da bei einer Zahleneingabe das '0,00' nicht gelöscht wird. Mal wieder zu schnell....
Edit2:
Hab mal weiter gebastelt. Das hier vermeidet jedenfalls die Fehlermeldung. Das Editfeld bleibt allerdings leer. Hoffe, daß ich keinen weiteen Mist gebaut habe. Jedenfalls gehts bei mir jetzt mit allen Eingaben und Korrekturen.
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| with TEdit(Sender) do begin if Text='' then E:=0; if (Text = '') or (Text = '-') or (TextToFloat(PChar(Text), E, fvExtended)) then begin.. ... end; |
Falls du Berechnungen in der OnChange durchführen willst, mußt du das unten auch ändern:
Delphi-Quelltext
1: 2:
| if (Text <> '') and (Text <>'-') or (E=0) then |
Ansonsten bleibt halt der letzte gültige Wert für E stehen.
(Highlight für "or (E=0)" funktioniert nicht ??? )
Lannes - Mo 26.06.06 14:30
Biarchiv hat folgendes geschrieben: |
...Nur ein kleinen Fehler hat er noch.
Er soll fals TEdit leer ist einfach 0,00 reinschreiben da es sonst
zu einen flaschen Gleitkommawert kommt. |
als Fehler würde ich das nicht bezeichnen.
Mit 0,00 hättest Du ja eventuell für weitere Berechnungen mit den so erzeugten Werten auch Probleme. Das musst Du ja dann auch in der Berechnungs- oder Auswertungsprozedur überprüfen.
Man kann den Code so umbauen, das 0,00 automatisch gesetzt wird.
Etwa so(und nochmal optimiert), Edit.Tag durchnummerieren!:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| sFloatArr : Array [0..9] of String; procedure TForm1.AllEditChange(Sender: TObject); var E: Extended; const _DEFAULT = '0,00'; begin with TEdit(Sender) do begin if (Text = '') then sFloatArr[Tag] := _DEFAULT else if (Text = '-') or (TextToFloat(PChar(Text), E, fvExtended)) then sFloatArr[Tag] := Trim(Text); Text := sFloatArr[Tag]; SelStart := Length(Text); end; end; |
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!