Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Nur Zahlen mit 1000 Trennzeichen???


lexmy3 - Do 02.03.06 10:44
Titel: Nur Zahlen mit 1000 Trennzeichen???
Hallo Allesamt,

Ich möchte in einem Editfeld nur Zahlen eingeben können und in diesem soll automatisch 1000 Trennzeichen eingefügt werden.

Also aus 1000000000 soll 1000.000.000 werden.

Habe hier Einiges gefunden jedoch nicht das Wahre.

Mfg

lexmy3

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:
24:
25:
26:
27:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var a:integer;
    b:string;
begin
    b:=(sender as tedit).Text;


     if key='.' then begin
      a:=0;
      if length(b)>0 then begin
      while a<=length(b) do begin
          if b[a]='.' then begin
          key:=#0;
          exit;  
          end;
          inc(a);
      end;
      end;
      exit;
    end;


    if  key>#57 then key:=#7;
    if (key>#31and (key<#48then key:=#7;


end;


lexmy3 - Do 02.03.06 11:32

So jetzt habe ich was anderes Entdeckt aber ohne Trennzeichen kann mir hier einer eventuell helfen?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
begin
if pos('1',Edit2.Text) > 0 then
  begin
    if key in ['0'..'9'then key := key
    else key := #0;
    exit;
  end;
      if  key>#57 then key:=#7;
      if (key>#31and (key<#48then key:=#7;
      end;

 end.


mfg
lexmy3


Narses - Do 02.03.06 11:57

Moin!

Ich halte den Ansatz, die Eingabe in ein Editfeld über den Zeichenhandler abzuwickeln für falsch. Damit wirst du z.B. Einfügen mit STRG+C nicht abfangen, was ich bei einem Editfeld für absolut selbstverständlich halte. Deshalb schlage ich einen Filter-Ansatz auf Veränderungs-Ereignis-Basis [http://www.delphi-forum.de/viewtopic.php?p=292145#292145] vor.

Mußte nur noch das Trennzeichen einfügen, fertig. :wink:

cu
Narses


MSCH - Do 02.03.06 11:57

Denk daran, das Zahlen im Format ("100.00.00") nicht mehr mit
StrToInt() ungewandelt werden können. Zusätzlich bekommst du ggf. Probleme,
wenn der Anwender statt "." ein "," haben möchte (-->Ländereinstellungen).

Entweder du überschreibst die Paint() Methode oder nimmt statt TEdit --> TMaskEdit.

grez
msch


lexmy3 - Do 02.03.06 12:48

user profile iconMSCH hat folgendes geschrieben:
Denk daran, das Zahlen im Format ("100.00.00") nicht mehr mit
StrToInt() ungewandelt werden können. Zusätzlich bekommst du ggf. Probleme,
wenn der Anwender statt "." ein "," haben möchte (-->Ländereinstellungen).

Entweder du überschreibst die Paint() Methode oder nimmt statt TEdit --> TMaskEdit.

grez
msch


Hey iat denn Editmask besser für die Zahleneingabe geeignet??

Wenn ja dann mach ich es mit der.

Nur das mit FormatFloat oder wie #.## ???


lexmy3 - Do 02.03.06 12:53

Also muss ich nur noch die Tausender Trennzeichen einfügen oder???
Wie?
Habe was mit 'ThousandSeparator' gehört oder?


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:
procedure TForm1.MaskEdit1KeyPress(Sender: TObject; var Key: Char);

  function Filter(const S: String): String;  
    const
      OK: Set of Char = ['0'..'9'];
    var
      i: Integer;  
  begin
    Result := '';
    for i := 1 to Length(S) do
      if (S[i] in OK) then
        Result := Result +S[i];
  end;  


begin
  if (MaskEdit1.Modified) then begin
    MaskEdit1.Text := Filter(MaskEdit1.Text); // Eingabe bereinigen
    MaskEdit1.SelStart := Length(MaskEdit1.Text); // Cursor ans Textende stellen
  end;
end;

end.


Narses - Do 02.03.06 12:58

Moin!

Hmm, deine Umgangsform und deine Eigeninitiative kommen mir etwas unnötig gering vor... :| nur so am Rande.

Ansatz: Du gehst den gefilterten String von hinten in Dreierschritten durch und fügst die Punkte ein. Kannste genauso aufbauen, wie den Zeichenfilter, als function also z.B.

cu
Narses


alzaimar - Do 02.03.06 13:45

Mich nerven Editoren, die die Tausenderzeichen schon während der Eingabe anzeigen.
Ich überschreibe einfach das OnEnter und OnExit-Ereignis des Editcontrols. Die Zahl wird mit Tausendertrennzeichen angezeigt, zum Editieren verschwinden die aber, sodass ich ein einfaches, unkompliziertes Editfeld habe.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
Function ThousandsToInt (Const aString : String) : Integer;
Begin
  Result := StrToIntDef (StringReplace (aString,ThousandSeparator,'', [rfReplaceAll]), 0);
End;

Function IntToThousands (Const aValue : Integer) : String;
Begin
  Result := FormatFloat (',0',aValue);
End;

Procedure TMyForm.MyEditEnter (Sender : TObject);
Begin
  With Sender as TEdit Do Text := IntToStr (ThousandsToInt (Text));
End;

Procedure TMyForm.MyEditExit (Sender : TObject);
Begin
  With Sender as TEdit Do Text := IntToThousand (StrToIntDef (Text,0)));
End;


raiguen - Do 02.03.06 13:52

Moin :-)

Also, ich halt von der Maskiererei nicht viel. Ist mir zu unflexibel irgendwie...

Ich würd das so machen (das Beispiel arbeitet mit Gleitkomma, also nix Ganze zahlen):


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:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
procedure TForm1.Edit1Exit(Sender: TObject);
var s: String;
    i: Integer;
begin
  //--falls vorhanden, zunächst 'deaktivieren' sonst kommt's evtl zum Deadlock
  Edit1.Onchange := nil;
  //-- falls bereits formatiert, dann hau die Tausenderzeichen raus
  for i := 1 to Length(Edit1.Text) do
    if Copy(Edit1.Text,i,1) <> '.' then
      s := s + Copy(Edit1.Text,i,1);
  if Edit1.Modified then
    Edit1.Text := Format('%9.2n',[StrToFloat(s)]);

  //--wieder 'aktivieren'
  Edit1.OnChange := Edit1Change;
end;

   //-- nachfolgnd der Code von Narses, etwas modifiziert
procedure TForm1.Edit1Change(Sender: TObject);

  function Filter(const S: String): String;
    const
      OK: Set of Char = ['0'..'9',',']; //Komma muss drin bleiben
    var
      i: Integer;
  begin
    Result := '';
    for i := 1 to Length(S) do
      if (S[i] in OK) then
        Result := Result +S[i];
  end;

begin
  if (Edit1.Modified) then begin
    Edit1.Text := Filter(Edit1.Text); // Eingabe bereinigen
    Edit1.SelStart := Length(Edit1.Text); // Cursor ans Textende stellen
  end;
end;


Kannst es ja Deinen Wünschen entsprechend anpassen; soll ja nur ne Idee sein ;-)

Gruß


alzaimar - Do 02.03.06 14:07

Super raiguen: Das Gleiche wie mein Code, nur doppelt so kompliziert.


lexmy3 - Do 02.03.06 16:06

Hall, Vielen Dank ersrmal für die Reaktionen!

Habe jetzt diesen Code übernommen und dieser funktioniert, jedoch wenn ich eine Eingabe gemacht und diese dann gelöscht habe kommt eine Exeption auf. 'Kein gültiger Gleitkomma wert'

Das muss noch beseitigt werden dann ist es Perfekt.




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:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
procedure TForm1.Edit6Exit(Sender: TObject);
var s: String;  
    i: Integer;
begin  
  //--falls vorhanden, zunächst 'deaktivieren' sonst kommt's evtl zum Deadlock
  Edit6.Onchange := nil;
  //-- falls bereits formatiert, dann hau die Tausenderzeichen raus
  for i := 1 to Length(Edit6.Text) do
    if Copy(Edit6.Text,i,1) <> '.' then
      s := s + Copy(Edit6.Text,i,1);
  if Edit6.Modified then
    Edit6.Text := Format('%9.n',[StrToFloat(s)]); // für Cents => Anzahl der NullStellen vor _.n angeben!!

  //--wieder 'aktivieren'
  Edit6.OnChange := Edit6Change;
end;

procedure TForm1.Edit6Change(Sender: TObject);
  function Filter(const S: String): String;
    const
      OK: Set of Char = ['0'..'9',','] ; // Komma muss drin bleiben 
    var
      i: Integer;
  begin
    Result := '';
    for i := 1 to Length(S) do
      if (S[i] in OK) then
        Result := Result +S[i];
  end;

begin
  if (Edit6.Modified) then begin
    Edit6.Text := Filter(Edit6.Text); // Eingabe bereinigen
    Edit6.SelStart := Length(Edit6.Text); // Cursor ans Textende stellen

  end;
end;


end.


MSCH - Do 02.03.06 18:22

tja, keine Eingabe ist auch eine!
StrToInt/StrToFloat('') gibts nicht. Benutze statt dessen StrToIntDef/StrToFloatDef.

Aber wie gesagt, solche "Methoden" sind echt krude.
Warum baust du dir nicht eine Eigene Komponente, abgeleitet von TEdit - wo du nur
die Paint() Methode überschreiben musst?

grez
msch


raiguen - Fr 03.03.06 12:11

user profile iconalzaimar hat folgendes geschrieben:
Super raiguen: Das Gleiche wie mein Code, nur doppelt so kompliziert.

Ähm - Dein Code ist natürlich eleganter :D

Beim Erstellen meines Postings war allerdings Deine Antwort noch nicht 'sichtbar'...

Gruß

user profile iconMSCH hat folgendes geschrieben:
tja, keine Eingabe ist auch eine!
StrToInt/StrToFloat('') gibts nicht. Benutze statt dessen StrToIntDef/StrToFloatDef.

Aber wie gesagt, solche "Methoden" sind echt krude.
Warum baust du dir nicht eine Eigene Komponente, abgeleitet von TEdit - wo du nur
die Paint() Methode überschreiben musst?

grez
msch


StrToInt(..)/StrToFloat(..) gibts nicht!? Ähm...und wieso funzt mein Code dann bei mir??

Tja, wenn ma sich in Komponentenbau auskennt, mag das ja ein weiterer Weg sein. Aber wenns nur um ein,zwei Editfelder geht, dann lohnt sich der Aufwand nicht!?

Gruß


MSCH - Fr 03.03.06 12:21

wenn in deinem Textfeld nichts enthalten ist , laufen StrToInt/StrToFloat ins Leere,
da dann StrToInt('') aufgerufen wird, was typischerweise einen Laufzeitfehler zur Folge hat.

grez
msch


raiguen - So 05.03.06 14:40

user profile iconMSCH hat folgendes geschrieben:
wenn in deinem Textfeld nichts enthalten ist , laufen StrToInt/StrToFloat ins Leere,
da dann StrToInt('') aufgerufen wird, was typischerweise einen Laufzeitfehler zur Folge hat.

grez
msch


Moin :-)

Ist klar, deswegen sollte man im Code das auch abprüfen... ;-) Die Art und Weise wie, darüber kann sich der Programmierer ja selbst mal Gedanken machen :-P. Mein CodeSchnipsel sollte ja nur als Anregung dienen ;-)

Gruß