Autor Beitrag
Biarchiv
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 688



BeitragVerfasst: Do 15.06.06 20:50 
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.

ausblenden 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 >= 3then break;
    Buf:=Buf+Text[i];
    end;
  Text:=Buf;
  SelStart:=SS;
  SelLength:=SL;
 end;
Marc.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1876
Erhaltene Danke: 129

Win 8.1, Xubuntu 15.10

BeitragVerfasst: 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:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
{******* Nur Zahlen und ein Komma im Editfeld *******}
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
 if key = ',' then
  if pos(',', edit1.Text) <> 0 then  // falls noch kein Komma vorhanden ist pos = 0
   begin
      key := #0;
   end;


 if not (key in ['0'..'9'',' , #8]) then  // nur zahlen, komma
    begin
      key := #0;
    end;
end;


Zuletzt bearbeitet von Marc. am Fr 16.06.06 18:30, insgesamt 2-mal bearbeitet
mkinzler
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 4106
Erhaltene Danke: 13


Delphi 2010 Pro; Delphi.Prism 2011 pro
BeitragVerfasst: Do 15.06.06 20:56 
Du könntest es auch mit einem TMaskedEdit versuchen.

_________________
Markus Kinzler.
aim65
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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.
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 1876
Erhaltene Danke: 129

Win 8.1, Xubuntu 15.10

BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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).
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
//Caution: This routine does NOT prevent multiple inputs of the decimal point!!
begin  
if not (Key in [#8,'0'..'9']) then
  if Key in [',','.',';',':'then   //accidental use of Shift key?
    Key := DecimalSeparator   //Comma or dot as decimal point...
  else                        //(depending on Windows language settings)
    if Key =#13 then          //"CR" equal to the "TAB" Key
      begin
        Perform(WM_NEXTDLGCTL, 00);  //set focus to next field
        Key := #0;                     //avoid beep tone
      end
    else 
    Key := #0;   //There was no valid key
end;


Edit: Mein Kram geht wohl haarscharf am Thema vorbei, da Biarchiv ja wohl nur ein Edit-Feld braucht... :oops:
Born-to-Frag
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1094

Win XP SP2, Win 2000 SP4
Delphi 7, 2k5
BeitragVerfasst: 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

_________________
Theorie ist wenn man alles weiß, aber nichts funktioniert. Praxis ist wenn alles funktioniert, aber niemand weiß warum.
Microsoft vereint Theorie und Praxis: Nichts funktioniert und niemand weiß warum.
aim65
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 688



BeitragVerfasst: 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.

ausblenden 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) > 0then 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 688



BeitragVerfasst: Di 20.06.06 16:50 
user profile iconaim65 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Di 20.06.06 23:47 
user profile iconaim65 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:
ausblenden 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
  //Enthält der String keinen gültigen Gleitkommawert, gibt TextToFloat False zurück
  if TextToFloat(PChar(Edit1.Text), E, fvExtended) then
    //TextToFloat wertet führende und schließende Leerzeichen nicht als Fehler
    sFloat := Trim(Edit1.Text)//akzeptieren und sichern
    else
      begin
      Edit1.Text := sFloat;//letzte gültige Eingabe wiederherstellen
      //damit der Cursor wieder am Ende steht
      Edit1.SelStart := Length(Edit1.Text);
      end;
end;


Bei 500 Edits :roll: kann statt der Variable sFloat ein Array of String entsprechend genutzt werden.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
aim65
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Mi 21.06.06 15:12 
user profile iconaim65 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:
ausblenden Delphi-Quelltext
1:
if (Text = '-'or (TextToFloat(PChar(Text), E, fvExtended)) then					


user profile iconaim65 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:
ausblenden 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..9of 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//wenn es denn in OnChange sein muss
        //rechnen
      end
      else
        begin
        Text := sFloatArr[Tag];
        SelStart := Length(Text);
        end;
end;

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
aim65
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2352
Erhaltene Danke: 4

Win XP, 95, 3.11, IE6
D3 Prof, D4 Standard, D2005 PE, TurboDelphi, Lazarus, D2010
BeitragVerfasst: Mi 21.06.06 19:30 
user profile iconaim65 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.

_________________
MfG Lannes
(Nichts ist nicht Nichts) and ('' <> nil ) and (Pointer('') = nil ) and (@('') <> nil )
aim65
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: Mi 21.06.06 19:48 
Danke für die Info
Biarchiv Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 688



BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 312

Win 9x, Win XP
Delphi 3pro, 7PE
BeitragVerfasst: 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:
ausblenden 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.
ausblenden 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; //zusätzlich für oben


Falls du Berechnungen in der OnChange durchführen willst, mußt du das unten auch ändern:
ausblenden Delphi-Quelltext
1:
2:
if (Text <> ''and (Text <>'-'or (E=0 then //wenn es denn in OnChange sein muss
  //Berechnungen...

Ansonsten bleibt halt der letzte gültige Wert für E stehen.
(Highlight für "or (E=0)" funktioniert nicht ??? )