Skocz do zawartości

[Delphi] Problem z Editem do wpisywania liczb


olesio

Polecane posty

Witam. Problem może banalny, ale nie za bardzo jestem biegły jeżeli chodzi o nadmiar if - then...

 

Nie bardzo służy mi MaskEdit, dlatego chciałem odpowiednio oprogramować zwykłego Edita aby

przyjmował jedynie cyfry i znak ustawiony w systemie jako Separator Dziesiętny, ale ów separator

nie może być pierwszym znakiem w Edit. Poniższy kod działa w metodzie OnKeyPress dla Edita o

nazwie KwotaEdit, ale ja chciałbym żebyście mi powiedzieli czy na pewno jest prawidłowy, gdyż w

przypadku dodać jak chcę do niego dodać możliwość wpisania tylko dwóch cyfr po separatorze to

dzieją się dziwne rzeczy, po przecinku można wpisywać także litery, a gdy dopisze albo dwie cyfry

albo dwie litery - to trace możliwość użycia klawisza backspace albo delete do usuwania tekstu.

 

procedure TMainForm.KwotaEditKeyPress(Sender: TObject; var Key: Char);
// Poniżej jest kod wykrywający Symbol dziesiętny - pochodzi ze strony:
// http://greatis.com/delphicb/tips/lib/syste...lseparator.html
var
MyDecimal : PChar;
Przecinek : string;
begin
MyDecimal := StrAlloc(10);
GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, MyDecimal, 10);
Przecinek := MyDecimal;

// Pozwala wpisać do Edit tylko cyfry na początku i symbol dziesiętny
if (Key in ['0'..'9', #8])
or (Length(KwotaEdit.Text) > 0)
and (Key = Przecinek[1])
then
begin
KwotaEdit.ReadOnly := FALSE;
end
else
begin
KwotaEdit.ReadOnly := True;
end;

// Pozwala wpisać do Edit tylko jeden przecinek
if (Pos(Przecinek, KwotaEdit.Text) > 0)
then
begin
if (Key in ['0'..'9', #8])
then
begin
KwotaEdit.ReadOnly := FALSE;
end
else
begin
KwotaEdit.ReadOnly := True;
end;
// Tutaj chciałbym dopisać jeszcze jakiś kod...
end;
end;

 

Co jest nie tak? Prosił bym o poprawienie tego kodu tak aby Edit akceptował tylko cyfry,

klawisze backspace i delete oraz pozwalał na wprowadzenie jednego separatora i to nie

jako pierwszego znaku oraz pozwalał na wpisanie tylko dwóch cyfr po owym separatorze.

Z góry dziękuje za jakiś kod, który spowoduje że Edit będzie działał tak jak założyłem :)

Pozdrawiam: olesio

Link do komentarza
Udostępnij na innych stronach

Nie podam ci kodu, ale napisze jak ja bym to widział.

1. Użytkownik wpisuje do edita co chce.

2. W metodzie OnLeave, albo OnChange, OnEnter, albo coś podobnego analizujemy to co zostało wpisane, np. w taki sposób:

- Używamy FloatToStr, aby sprawdzić czy wpisana jest poprawna wartość liczbowa, jeśli będzie niepoprawna to FloatToStr wywali błąd więc zamykamy to w try ... except.

- Kiedy mamy już wartość liczbową to zaokrąglamy ją do 2 miejsc po przecinku (bo chyba tak chcesz).

- Zaokrągloną liczbę wpisujemy do edita.

Link do komentarza
Udostępnij na innych stronach

Witaj :rolleyes:

 

ja się pobawiłem Twoim kodem :rolleyes:

 

sprawdź, czy o to Ci chodziło:

 

procedure TForm1.KwotaEditKeyPress(Sender: TObject; var Key: Char);
var
 MyDecimal : PChar;
 Przecinek : string;
begin
 MyDecimal := StrAlloc(10);
 GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, MyDecimal, 10);
 Przecinek := MyDecimal;

 if (Key in ['0'..'9', #8]) or (Key = Przecinek[1]) then
 begin
 end else
 begin
   Key:=chr(0);
   exit;
 end;

 if (Length(KwotaEdit.Text) = 0) and (Key = Przecinek[1]) or (Length(KwotaEdit.Text) > 0) and (Key = Przecinek[1]) and (Pos(Przecinek, KwotaEdit.Text) > 0) then
 begin
   Key:=chr(0);
   exit;
 end;

 if (Key in [#8]) then else
 begin
   if (Pos(Przecinek, KwotaEdit.Text) > 0) then if ((Length(KwotaEdit.Text)) < (Pos(Przecinek[1], KwotaEdit.Text)) + 2) then
   else begin
     Key:=chr(0);
     exit;
   end;
 end;
end;

 

Pozdrawiam :rolleyes:

Link do komentarza
Udostępnij na innych stronach

Tsr: dzięki, też na to wpadłem dopiero później, popróbuje też chyba ze zdarzeniem OnExit.

 

xevil21: również wielkie dzięki, dokładnie o to mi chodziło. Pozostaje tylko jedna kwestia do

zrobienia i z tym będzie najciężej, bo komponnet Edit nie ma chyba własności, w której była

by zawarta pozycja kursora w Editcie. Bo chodzi o to że jak wpiszemy 123,45 i checmy do

Edita dopisać przed przecinkiem jakąś cyfrę - nie będzie to możliwe. Chyba że tak musi być.

 

Póki co wykorzsytałem kod xevil21 bez ostatniego warunku czyli bez ograniczania wpisania

liczby do dwóch miejsc po przecinku. A dla buttona który robi obliczenia pobierając liczbę z

KwotaEdit ustawiłem Default na False, a w zdarzeniu OnExit dla KwotaEdit wpisałem kod:

function Zaokraglij(Liczba: Double; Miejsca: Byte): Double;
// Funckcja pochodzi z forum strony: http://komputery.katalogi.pl
// Aby ją znaleźć w google - wystarczy wpisać: Delphi Zaokraglij.
var
Ile, I: integer;
begin
Ile := 1;
for I := 1 to Miejsca do
Ile := Ile * 10;
Zaokraglij := Round(Liczba * Ile) / Ile;
end;

procedure TMainForm.KwotaEditExit(Sender: TObject);
begin
// Zaokraglenie wpisanej w Edit liczby do dwóch miejsc po przecinku
if KwotaEdit.Text <> '' then
begin
KwotaEdit.Text := FloatToStr(Zaokraglij(StrToFloat(KwotaEdit.Text), 2));
end;
end;

Pozdrawiam: olesio

Link do komentarza
Udostępnij na innych stronach

Hey :rolleyes:

 

Pozostaje tylko jedna kwestia do

zrobienia i z tym będzie najciężej, bo komponnet Edit nie ma chyba własności, w której była

by zawarta pozycja kursora w Editcie.

 

można to zrobić tak:

 

procedure TForm1.KwotaEditKeyPress(Sender: TObject; var Key: Char);
var
 MyDecimal : PChar;
 Przecinek : string;
 PozycjaKursora: Integer;
begin
 MyDecimal := StrAlloc(10);
 GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, MyDecimal, 10);
 Przecinek := MyDecimal;

 PozycjaKursora:= Kwotaedit.SelStart - SendMessage (Kwotaedit.Handle, EM_LINEINDEX, PozycjaKursora, 0);
 caption:='Pozycja kursora='+IntToStr(PozycjaKursora);

 if (Key in ['0'..'9', #8]) or (Key = Przecinek[1]) then
 begin
 end else
 begin
   Key:=chr(0);
   exit;
 end;

 if (Length(KwotaEdit.Text) = 0) and (Key = Przecinek[1]) or (Length(KwotaEdit.Text) > 0) and (Key = Przecinek[1]) and (Pos(Przecinek, KwotaEdit.Text) > 0) then
 begin
   Key:=chr(0);
   exit;
 end;

 if (Key in [#8]) then else
 begin
   if (Pos(Przecinek, KwotaEdit.Text) > 0) then if ((Length(KwotaEdit.Text)) < (Pos(Przecinek[1], KwotaEdit.Text)) + 2) then
   else begin
     Key:=chr(0);
     exit;
   end;
 end;
end;

 

Pozdrawiam :rolleyes:

Link do komentarza
Udostępnij na innych stronach

Hey :rolleyes:

 

teraz powinno działać dobrze i jest chyba idioto odporne :rolleyes:

 

sorki, ale wcześniej nie mogłem się tym zająć.

 

procedure TForm1.KwotaEditKeyPress(Sender: TObject; var Key: Char);
var
 MyDecimal: PChar;
 Przecinek: string;
 PozycjaKursora: Integer;
 PozycjaPrzecinka: Integer;
begin
 MyDecimal:=StrAlloc(10);
 GetLocaleInfo(LOCALE_SYSTEM_DEFAULT,LOCALE_SDECIMAL,MyDecimal,10);
 Przecinek:=MyDecimal;

 PozycjaKursora:=Kwotaedit.SelStart-SendMessage(Kwotaedit.Handle,EM_LINEINDEX,PozycjaKursora,0);
 PozycjaPrzecinka:=Pos(Przecinek,KwotaEdit.Text);

 if (Key in ['0'..'9',#8]) or (Key=Przecinek[1]) and (PozycjaKursora>0)
 and (PozycjaKursora>=Length(KwotaEdit.Text)-2) then
 begin
 end else
 begin
   Key:=chr(0);
   exit;
 end;

 if (Length(KwotaEdit.Text)=0) and (Key=Przecinek[1]) or (Length(KwotaEdit.Text)>0)
 and (Key=Przecinek[1]) and (Pos(Przecinek,KwotaEdit.Text)>0) then
 begin
   Key:=chr(0);
   exit;
 end;

 if (Key in [#8]) then else
 begin
   if (Pos(Przecinek,KwotaEdit.Text)>0) then
   begin
     if PozycjaKursora>=PozycjaPrzecinka  then
     if ((Length(KwotaEdit.Text))<(Pos(Przecinek[1],KwotaEdit.Text))+2) then
     else begin
       Key:=chr(0);
       exit;
     end;
   end;
 end;
end;

 

Pozdrawiam :rolleyes:

Link do komentarza
Udostępnij na innych stronach

Hey :rolleyes:

 

teraz powinno działać dobrze i jest chyba idioto odporne :rolleyes:

 

sorki, ale wcześniej nie mogłem się tym zająć.

 

Dziękuje pięknie, dokłądnie o to chodziło :) Edit zachowuje się jak trzeba.

Nie znałem wcześniej "sztuczki" z SendMessage. I teraz w kodzie nie

potrzeba zaokrąglania w OnExit - wszsystkiego "pilnuje" OnKeyPress.

Pozdrawiam: olesio

Link do komentarza
Udostępnij na innych stronach

  • 2 months later...

Piękna procedurka, ale może ktoś podpowie jak ją zastosować dla 12 pól edit, bez tworzenia 12 procedur?

Nom każdemu Editowi przypisujesz do zdarzenia OnKeyPress tą jedną procedurkę.

edtCosTam.OnKeyPress := KwotaEditKeyPress;
EditTysiacPiecsetStoDziewiecset.OnKeyPress := KwotaEditKeyPress;

Link do komentarza
Udostępnij na innych stronach

Można tak ciut więcej kodu?

Załóżmy, że mam poniższy fragment kodu i przypisałem przez Event OnKeyPress Edit1, Edit2 i Edit3 do KwotaEditKeyPress.

Tyle, że ten kod nie przeskoczy linijki PozycjaKursora:=, bo wywala - Undeclared identifier: 'Kwotaedit'.

Ja wiem, że to pewnie trywialne, ale ostatni program pisałem w TP z 10 lat temu pod DOS, a teraz muszę sklecić coś w Delphi i jeszcze się nie przełączyłem na inny sposób myślenia :unsure:

 
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls;

type
 TForm1 = class(TForm)
   Edit1: TEdit;
   Edit2: TEdit;
   Edit3: TEdit;
 procedure KwotaEditKeyPress(Sender: TObject; var Key: Char);
 private
    { Private declarations }
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.KwotaEditKeyPress(Sender: TObject; var Key: Char);

var
 MyDecimal: PChar;
 Przecinek: string;
 PozycjaKursora: Integer;
 PozycjaPrzecinka: Integer;
begin
 MyDecimal:=StrAlloc(10);
 GetLocaleInfo(LOCALE_SYSTEM_DEFAULT,LOCALE_SDECIMAL,MyDecimal,10);
 Przecinek:=MyDecimal;

 PozycjaKursora:=Kwotaedit.SelStart-SendMessage(Kwotaedit.Handle,EM_LINEINDEX,PozycjaKursora,0);
{.........}
end;
end.

Link do komentarza
Udostępnij na innych stronach

Witam!

 

wystarczy w wyżej załączonym kodzie zmienić nazwę kontrolki Kwotaedit na TEdit(Sender)

 

procedure TForm1.KwotaEditKeyPress(Sender: TObject; var Key: Char);
var
 MyDecimal: PChar;
 Przecinek: string;
 PozycjaKursora: Integer;
 PozycjaPrzecinka: Integer;
begin
 MyDecimal:=StrAlloc(10);
 GetLocaleInfo(LOCALE_SYSTEM_DEFAULT,LOCALE_SDECIMAL,MyDecimal,10);
 Przecinek:=MyDecimal;

 PozycjaKursora:=TEdit(Sender).SelStart-SendMessage(TEdit(Sender).Handle,EM_LINEINDEX,PozycjaKursora,0);
 PozycjaPrzecinka:=Pos(Przecinek,TEdit(Sender).Text);

 if (Key in ['0'..'9',#8]) or (Key=Przecinek[1]) and (PozycjaKursora>0)
 and (PozycjaKursora>=Length(TEdit(Sender).Text)-2) then
 begin
 end else
 begin
   Key:=chr(0);
   exit;
 end;

 if (Length(TEdit(Sender).Text)=0) and (Key=Przecinek[1]) or (Length(TEdit(Sender).Text)>0)
 and (Key=Przecinek[1]) and (Pos(Przecinek,TEdit(Sender).Text)>0) then
 begin
   Key:=chr(0);
   exit;
 end;

 if (Key in [#8]) then else
 begin
   if (Pos(Przecinek,TEdit(Sender).Text)>0) then
   begin
     if PozycjaKursora>=PozycjaPrzecinka  then
     if ((Length(TEdit(Sender).Text))<(Pos(Przecinek[1],TEdit(Sender).Text))+2) then
     else begin
       Key:=chr(0);
       exit;
     end;
   end;
 end;
end;

 

Teraz powinno działać dobrze :)

 

Pozdrawiam!

 

P.S. Bardzo ważna uwaga: dla pierwszego edita przypisz tą procedurke w następujący sposób:

 

1. W okienku Object Inspector wybierz interesującą Cię kontrolkę edit,

 

2. Przejdź do zakładki Events,

 

3. Kliknij dwa razy lewym przyciskiem myszki w polu OnKeyPress,

 

4. W wygenerowanym zdarzeniu wklej powyższy kod pomijając powtarzające się linijki,

 

czyli 1 i ostatnią!!! (Zaznaczasz sobie w/z procedurę bez 1 i ostatniej linijki,

 

kopiujesz, a w wygenerowanym zdarzeniu kasujesz słowo begin, umieszczasz kursor

 

w jego miejscu i wklejasz wcześniej zaznaczony kod. Teraz możesz już reszcie

 

editów przypisać to zdarzenie w normalny sposób.)

Link do komentarza
Udostępnij na innych stronach

Serdeczne dzięki za szybką odpowiedź. Coś mi świtało, że trzeba użyć czegoś z Sender.

Toster: Pomoc jest bardzo pomocna (sporo mi podpowiedziała), ale na ten błąd to nic mądrego nie podpowie. Ot, brak deklaracji zmiennej i już ;)

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

×
×
  • Utwórz nowe...