TEdit dodatkowe 4 założenia - pomoc

0

Witam,

Możecie mi pomóc przerobić ten kod tak aby w polu TEdit były takie założenia:

  1. nie można wpisywać przecinka ',' jeżeli:
    a) nie wpisano żadnej liczby,
    b) już jest jeden przecinek,
  2. Jak wpisano tylko 1 zamienia się na 1,00
  3. Jeżeli wpisano mniej znaków niż 7, ale pojawił się ',' i dwie cyfry przechodzi automatycznie do następnego pola.

Udało mi się zrobić (bazując na przykładach w Google)

  • dopuszczane znaki ( tylko cyfry, przecinek, enter, backspace
  • tylko 2 miejsca po przecinku
  • jak wcisnę klawisz Enter przechodzi do następnego pola
  • jak wklepie 7 znaków przechodzi do następnego pola

Potrzebuje tego, aby program mój miał wartości walutowe, i nie pozwalał na wpisywanie np. takich danych:
,23
1234,,,
1234,5,

 
procedure TForm1.Pole_ZywnoscChange(Sender: TObject);
begin
if pos(',', Pole_Zywnosc.text)<>0 then
  if (length(Pole_Zywnosc.Text) - 2 > pos(',', Pole_Zywnosc.text)) then
  begin
   Pole_Zywnosc.Text:=copy(Pole_Zywnosc.Text,1,length(Pole_Zywnosc.Text)-1);
   Pole_Zywnosc.SelStart:=length(Pole_Zywnosc.Text);
  end;
end;

procedure TForm1.Pole_ZywnoscKeyPress(Sender: TObject; var Key: Char);
begin
If Key in ['0'..'9',#8,#13,','] {jeśli klikasz jeden z tych znaków to }
then  {wpisuj }
else Key:=#0;  { inaczej nie wpisuj}
If Length(Pole_Zywnosc.text)=7 then  {jeśli napisano 7 znaków to }
Pole_Chemia.SetFocus; {uaktywnij pole Pole_Chemia}
If Key=#13 then {jeśli wciśnięty klawisz to Enter}
Pole_Chemia.SetFocus; {uaktywnij pole Pole_Chemia}
end;

Z góry wdzięczny będę za pomoc.

0

Zobacz sobie ten kod, nie jest idealny, kiedyś ktoś mi go podpowiedział
na innym forum i użyłem tylko w jednym testowym programie, i możesz
sobie go dostosować do swoich potrzeb jeśli coś nie jest tak jak chcesz.

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/systemifo-decimalseparator.html
var
  MyDecimal : PChar;
  Przecinek : string;
  PozycjaKursora : Integer;
  PozycjaPrzecinka : Integer;
begin
  MyDecimal := StrAlloc(10);
  GetLocaleInfo(LOCALE_SYSTEM_DEFAULT, LOCALE_SDECIMAL, MyDecimal, 10);
  Przecinek := MyDecimal;
// Ponizszy kod pozwala na wprowadzenie do Edit tylko cyfr oraz
// symbolu dziesietnego (przecinek) i tylko dwoch cyfr po nim
  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;
0

DZIĘKI,
z pkt3. po namyśle jednak zrezygnuje, ale pozostaje mi jeszcze do zrealizowania pkt2.

tj. jak z liczby całkowitej zmienić na rzeczywistą

0

Olesio, w module SysUtils jest zdefiniowany DecimalSeparator, więc nie trzeba używać funkcji GetLocaleInfo. Po co sobie komplikować życie.

**Mastek **sprawdź taką procedurę. Zamiast konkretnej nazwy Edita użyłem (Sender as TEdit), tak będzie bardziej uniwersalnie.
Nie dawałem procedur Exit w każdym warunku if ... then, aby niepotrzebnie nie przedłużać kodu (zysk na szybkości będzie prawie żaden)

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
begin
  if Key in ['0'..'9', #8, #13, DecimalSeparator] then begin
    // 1a. Ignoruj przecinek, jeśli to pierwszy znak (nie ma cyfr)
    if (Key = DecimalSeparator) and (Length((Sender as TEdit).Text) = 0) then Key:= #0;
    // 1b. Ignoruj następny przecinek
    if (Key = DecimalSeparator) and (Pos(DecimalSeparator, (Sender as TEdit).Text) > 0) then Key:= #0;
    // 2. Dopisuj 2 zera po przecinku
    if Key = #13 then begin
      if Pos(DecimalSeparator, (Sender as TEdit).Text) = 0
        then (Sender as TEdit).Text:= (Sender as TEdit).Text + DecimalSeparator + '00';
      // Go to next Edit
    end;
    // Tylko 2 miejsca po przecinku
    if (Pos(DecimalSeparator, (Sender as TEdit).Text) > 0) and
       (Length((Sender as TEdit).Text) = Pos(DecimalSeparator, (Sender as TEdit).Text) + 2)
    then if not (Key in [#8, #13]) then Key:= #0;
  end
  else Key:= #0;
end;

Być może trzeba będzie jeszcze coś dopracować, ale to w końcu Twój program, więc dalej kombinuj sam

0

Windows 7 ma buga powodującego, że VCL czasami wczytuje złe ustawienia narodowe. Warto to naprawić, wystarczy na początku programu w pliku .dpr dodać dwie linijki:

SetThreadLocale(LOCALE_USER_DEFAULT);
GetFormatSettings;
0

Super, przerobiłem troszkę twój kodzik Simplex

  • dodałem "00" jeżeli jest 1,
  • dodałem "0" jeżeli jest 1,2
 procedure TForm1.Pole_ZywnoscKeyPress(Sender: TObject; var Key: Char);
begin
  if Key in ['0'..'9', #8, #13, DecimalSeparator] then begin
    // 1a. Ignoruj przecinek, jeśli to pierwszy znak (nie ma cyfr)
    if (Key = DecimalSeparator) and (Length((Sender as TEdit).Text) = 0) then Key:= #0;
    // 1b. Ignoruj następny przecinek
    if (Key = DecimalSeparator) and (Pos(DecimalSeparator, (Sender as TEdit).Text) > 0) then Key:= #0;
    // 2a. Dopisuj 1 zero po przecinku
    if Key = #13 then begin
      if (Pos(DecimalSeparator, (Sender as TEdit).Text) >= 1 ) and
       (Length((Sender as TEdit).Text) = Pos(DecimalSeparator, (Sender as TEdit).Text) + 1)
       then (Sender as TEdit).Text:= (Sender as TEdit).Text + '0';
    end;
    // 2b. Dopisuj 2 zera po przecinku jeżeli sam przecinek
    if Key = #13 then begin
      if (Pos(DecimalSeparator, (Sender as TEdit).Text) >= 1 ) and
       (Length((Sender as TEdit).Text) = Pos(DecimalSeparator, (Sender as TEdit).Text))
       then (Sender as TEdit).Text:= (Sender as TEdit).Text + '00';
    end;
    // 2. Dopisuj 2 zera po przecinku
    if Key = #13 then begin
      if Pos(DecimalSeparator, (Sender as TEdit).Text) = 0
        then (Sender as TEdit).Text:= (Sender as TEdit).Text + DecimalSeparator + '00';
      // Go to next Edit
      Pole_Chemia.SetFocus;
    end;
    // Tylko 2 miejsca po przecinku
    if (Pos(DecimalSeparator, (Sender as TEdit).Text) > 0) and
       (Length((Sender as TEdit).Text) = Pos(DecimalSeparator, (Sender as TEdit).Text) + 2)
    then if not (Key in [#8, #13]) then Key:= #0;
  end
  else Key:= #0;
end;

ale mam jeszcze 4 problemy (pewnie proste) z którymi na razie nie mogę sobie poradzić:

  1. nie mogę nic pisać jak tekst jest zaznaczony (np. klikając shift+tab)
  2. jak zrobić aby taka sama akcja stała się jak wybiorę myszką drugie (inne pole edit)
  3. nie wiem dlaczego nie działa mi ten kod w następnym TEdit tzn:
  • klikając ENTER na TForm1.Pole_Zywnosc przenosi mnie do TForm1.Pole_Chemia - słysze BEEP ( dlaczego ?)
  • tutaj już ta procedura nie działa (mogę nawet wpisując litery)
0
  1. jak zrobić aby taka sama akcja stała się jak wybiorę myszką drugie (inne pole edit)

Wybrać te same zdarzenie w Object Inspectorze w zakładce Events
dla innych pól edycyjnych albo zrobić to poprzez kod, jeżeli są one
tworzone dynamicznie lub wolisz to zrobić poprzez kod bo masz ów
pól bardzo dużo czyli JakisEdit.OnKeyPress := JakisEditKeyPress; .

TForm1.Pole_Chemia - słysze BEEP ( dlaczego ?)

  • tutaj już ta procedura nie działa (mogę nawet wpisując litery)

Nie chcesz słyszęc "beep'a" to dodawaj na końcu Key := #0; a co
do odpowiedzi poprzednika, że nie trzeba osobnego kodu do tego,
aby sprawdzić symnbol dziesiętny, to ja to wolałem zrobić tak jak
w poprzednim swoim postcie pokazałem, bo można założyć, iż na
przykład bardzo uparty użytkownik zmieni separator dziesiętny, w
trakcie pracy programu. Wiem, że to ekstremalne, ale może mieć
miejsce. A na pozstałe Twoje pytania może odpowie Ci ktoś inny.

0

Beepa już nie ma - dzięki.

Co do Eventsów, to nie wiem o co chodzi jeszcze.
A wiesz może który odpowiada za zwolnienie TEdita myszką ?

0

To prościej Tobie tego nie wytłumacze. Powinieneś poczytac jakieś
kursy, bo obsługa Object Inspectora to banalne podstawy. Za to w
sumie ja teraz nie rozumiem o co chodzi ze "zwalnianiem myszki".
Są zdarzenia OnEnter oraz OnExit, mają one miejsce wtedy, kiedy
Edit zyskuje Focus (po kliknięciu myszką lub przejście TABem) jak
też za utracenie focusa (kiedy przekażemy focus innej kontrolce).

0
  1. nie mogę nic pisać jak tekst jest zaznaczony (np. klikając shift+tab)
  // Tylko 2 miejsca po przecinku
  if (Pos(DecimalSeparator, (Sender as TEdit).Text) > 0) and
     (Length((Sender as TEdit).Text) = Pos(DecimalSeparator, (Sender as TEdit).Text) + 2)
     and ((Sender as TEdit).SelText = '')   // Dodaj tą linię
  then if not (Key in [#8, #13]) then Key:= #0;

Aby po naciśnięciu klawisza Enter przechodzić do następnego (w kolejności TabOrder, a nie konkretnego) Edita:

  // Go to next Edit
  SelectNext(Sender as TWinControl, True, True);

Uwaga. Może być konieczna zmiana kolejności kontrolek - PPM na formularzu i wybierasz TabOrder

Aby przypisać procedurę KeyPress do pozostałych Editów - zaznaczasz je wszystkie na formularzu przytrzymując klawisz Ctrl (oprócz tego, który już ma przypisaną), następnie w Object Inspector wybierasz OnKeyPress, czarny trójkąt po prawej stronie i wybierasz z listy (bo może być więcej niż jedna) odpowiednią procedurę. Właśnie po to wszędzie w procedurze jest Sender as ..., aby procedura była uniwersalna i zadziałała dla dowolnego Edita.

Mam nadzieję, że to rozwiąże problem.

0

dzięki wielkie wam za pomoc :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1