Klawiatura numeryczna w programie

0

Witam.

Mam pewien problem, otóż chciałem zrobić program który wylicza mi pewne rzeczy w wyglądzie przypominający windowsowki kalkulator. W trakcie pojawił się u mnie problem i chciałbym was prosić o pomoc.

  1. Chciałbym aby program zawierał klawiaturę numeryczną
    bb.jpg

Czyli gdy klikamy na dane okno Edit1 możemy wpisać w nim wartość, potem klikamy na Edit2 i znów korzystając z klawiaturki wpisujemy wartość itd.
Używałem takiej funkcji:

keybd_event(ord('5'), 1, 0, 0); 
keybd_event(ord('5'), 1, KEYEVENTF_KEYUP, 0); 
memo1.setfocus; 

Jednak sprawdza się ona tylko do jednego okna memo1 a nie działa dla dowolnego...

0

Podejrzewam że inni tak jak ja nie rozumieją o co Ci chodzi sądząc po tym jak długo nie ma odpowiedzi na prawdopodobnie proste pytanie.

0

sądząc po tym jak długo nie ma odpowiedzi na prawdopodobnie proste pytanie

Bo byłem na delegacji :P

Sam nie wiem co Ty kombinujesz... Jeżeli chcesz zrobić podobny efekt jak jest np. w windowsowskim kalkulatorze to po co symulujesz wciśnięcie klawiszy? Przecież nie musisz tego robić; Jest kilka sposobów na rozwiązanie tego problemu (pod warunkiem, że ja z kolei zrozumiałem dobrze o co chodzi);

Jeżeli chcesz dopisywać do pól jakieś wartości, to możesz zrobić to na zasadzie przypisywania:

procedure btn1Click(Sender: TObject)
begin
  edtStawka1.Text := edtStawka1.Text + '1';
end;

Coś w ten deseń; Ale to nie załatwia całej sprawy, bo musisz wiedzieć do którego pola masz wpisywać dane; W kalkulatorze systemowym masz jedno pole edycyjne, więc wiadomo do którego będą wprowadzane informacje; Ty masz dwa, więc trzeba będzie gdzieś przechować tą informacje; ActiveControl odpada, bo w momencie kliknięcia na przycisk on staje się aktywny (metoda ta sprawdza się fajnie podczas wywoływania jednego PopupMenu przypisanego dla wielu pól edycyjnych);

Musisz napisać coś więcej na ten temat, wtedy prawdopodobnie uzyskasz masę przydatnych informacji;

Jednak sprawdza się ona tylko do jednego okna memo1 a nie działa dla dowolnego...

Działa dla dowolnego, ale musi być w momencie symulowania wciśnięcia klawisza aktywne; Dla przykładu: jeżeli masz w swoim programie aktywny dany edit i zasymulujesz wciśnięcie klawisza A - zostanie do niego wpisane bez żadnego problemu; To tyczy się wszystkich komponentów, które "reagują" na naciskane klawisze; Zostanie wykonane to, co wykonało by się gdybyś normalnie wcisnął przycisk na klawiaturze; Ale tu to nie przejdzie, bo jeśli klikniesz na przycisk to oczywiście klawisz zostanie zasymulowany, ale przycisk stanie się w tym momencie aktywny i zareaguje na klawisze Enter i Spację - czyli zostanie po prostu wciśnięty (lub jeżeli w Caption przycisku jest znak & - wtedy po wciśnięciu klawisza odpowiadającego podkreślonej literce zostanie wywołane zdarzenie OnClick tegoż button'a);

0

Potrafię stworzyć klawiaturę w programie dzięki której przypisane wartości do przycisku wyświetlą oczekiwaną wartość w danym oknie np. memo1. Jednakże gdy mam memo1, memo2, memo3 musiał bym tworzyć oddzielną klawiaturę dla każdego z tych pól, a chciałbym aby klawiatura w programie działała w taki sam sposób jak "normalna klawiatura" czyli zaznaczam daną wartość i wpisuję liczby zaznaczam kolejną wartość i znów wpisuję wartość kolejną.

Ja bym to porównał do klawiatury ekranowej. Chciałbym aby to identycznie działało tylko że w obrębie programu??? Mam próbować dalej wyjaśniać?:P Czy tym razem lepiej pokazałem o co mi chodzi?

0

Ja bym to porównał do klawiatury ekranowej.

No teraz to wszystko jasne :) Masz kilka kontrolek tego samego typu i chcesz do nich wpisywać informacje jedną stworzoną przez siebie klawiaturą ekranową;

Trzeba by najpierw wiedzieć w jaki sposób działa systemowa klawiatura ekranowa, żeby zrobić profesjonalny efekt u Ciebie w programie; Jednak można to zrobić prościej ale mniej profesjonalnie;

Podczas kliknięcia w daną kontrolkę (do której chcesz wprowadzać informacje) zapisujesz do zmiennej jej identyfikator (np. liczbę czy nazwę komponentu) a później podczas kliknięcia w przycisk z numerkiem (na Twojej klawiaturze ekranowej) sprawdzić która była aktywna i do niej odpowiedznio wpisać cyfrę; Rozwiązanie dobre, ale ma minusy;

Lepiej by było sprawdzić które pole jest aktywne (przez ActiveControl), ale przyciski nie mogą być "zaznaczalne"; Wtedy gdy wciśniesz przycisk pole edycyjne pozostanie aktywne i będziesz mógł odwołać się do niego; Skorzystaj z przycisków klasy TSpeedButton; Jeżeli klikniesz na taki pole edycyjne zostanie zaznaczone i będziesz mógł wpisać do niego dane w taki sposób:

if ActiveControl.ClassName = 'TEdit' then //sprawdzenie czy aktywna kontrolka jest edycyjną
  TEdit(ActiveControl).Text := TEdit(ActiveControl).Text + '1'; //dopisanie cyfry 1

Zyskujesz prostotę, ale tracisz TabStop; Wciskając klawisz Tab nie aktywujesz tych przycisków (jak w klawiaturze ekranowej);

EDIT: Przy okazji - czy te kontrolki:

Stawki.png

są z klasy TMemo...?

0

Dziękuję bardzo, działa super;)

Tylko mam jeszcze pytanko ;) już dobrze wiem jak zrobić klawiaturę ale pojawia się u mnie pytanie jak zrobić klawisz Backspace???

0

No chyba nie myślisz symulować wciśnięcie tego klawisza??? :P

Sprawdź podczas kliknięcia w przycisk czy wciśnięto BkSp i jeżeli tak - unuń odpowiedni znak (odczytaj CaretPos i usuń poprzedni znak o ile istnieje);

0

Co do tych kontrolek to są klasy Tedit

0

Ewentualnie możesz sprawdzić podczas kliknięcia, czy Caption na buttonie to cyfra; Jeżeli tak - dodajesz cyfrę z Caption do edita a jeżeli nie - rozróżniasz go:

if ActiveControl.ClassName = 'TEdit' then
  if TSpeedButton(Sender).Caption[1] in ['0' .. '9'] then
    TEdit(ActiveControl).Text := TEdit(ActiveControl).Text + TSpeedButton(Sender).Caption
  else
    //rozpoznanie znaków specjalnych

Ten kod umieść w zdarzeniu OnClick buttona np. btn1, po czym przypisz to zdarzenie do wszystkich przycisków; Oprogramujesz raz, a będzie działało dla wszystkich;

0

Backspace udało mi się wywołać w taki sposób:

 keybd_event(VK_BACK, 0, 0, 0);
edit1.setfocus;

tylko że to działa tylko dla okna edit1...

0

Znalazłem rozwiązanie

 if ActiveControl.ClassName = 'TEdit' then //sprawdzenie czy aktywna kontrolka jest edycyjną
keybd_event(VK_BACK, 0, 0, 0);
TEdit(ActiveControl).setfocus;
0

Jeżeli symulujesz wciśnięcie klawisza procedurą keybd_event, to musisz także zasymulować puszczenie tego klawisza...

keybd_event(VK_BACK, 0, 0, 0);
keybd_event(VK_BACK, 0, KEYEVENTF_KEYUP, 0);
0

Ale gdy podpoiłem pod speedbutton wszystko działa...;)

Mam jeszcze jedno pytanko:

Case RadioGroup1.ItemIndex of
0: Memo1.Font.Color:=ClBlack;
1: Memo1.Font.Color:=ClRed;
2: Memo1.Font.Color:=ClGreen;
3: Memo1.Font.Color:=ClBlue; 

Jak to zapisać za pomocą if-ów?

0

bo speedbutton nie zbiera focusa. w pierwszym kodzie najpierw wysyłasz sekwencje klawiszy, a potem ustawiasz focusa, przez co sekwencja leci do buttona zamiast do memo

0
Case RadioGroup1.ItemIndex of
0: Memo1.Font.Color:=ClBlack;
1: Memo1.Font.Color:=ClRed;
2: Memo1.Font.Color:=ClGreen;
3: Memo1.Font.Color:=ClBlue;
if RadioGroup1.ItemIndex = 0 then Memo1.Font.Color := ClBlack else
if RadioGroup1.ItemIndex = 1 then Memo1.Font.Color := ClRed else
if RadioGroup1.ItemIndex = 2 then Memo1.Font.Color := ClGreen else
Memo1.Font.Color := ClBlue;

Powinno działać, ale nie sprawdzałem.

0

można powcinać tak

if RadioGroup1.ItemIndex = 0 then
  Memo1.Font.Color := ClBlack
else
  if RadioGroup1.ItemIndex = 1 then
    Memo1.Font.Color := ClRed
  else
    if RadioGroup1.ItemIndex = 2 then
      Memo1.Font.Color := ClGreen
    else
      Memo1.Font.Color := ClBlue;

albo tak

if RadioGroup1.ItemIndex = 0
  then Memo1.Font.Color := ClBlack
  else if RadioGroup1.ItemIndex = 1
         then Memo1.Font.Color := ClRed
         else if RadioGroup1.ItemIndex = 2
                then Memo1.Font.Color := ClGreen
                else Memo1.Font.Color := ClBlue;

albo jeszcze jakoś…

albo nawet tak:

if RadioGroup1.ItemIndex = 0
  then Memo1.Font.Color := ClBlack
else if RadioGroup1.ItemIndex = 1
  then Memo1.Font.Color := ClRed
else if RadioGroup1.ItemIndex = 2
  then Memo1.Font.Color := ClGreen
else Memo1.Font.Color := ClBlue;
0
Case RadioGroup1.ItemIndex of
  0: Memo1.Font.Color:=ClBlack;
  1: Memo1.Font.Color:=ClRed;
  2: Memo1.Font.Color:=ClGreen;
  3: Memo1.Font.Color:=ClBlue;
end;

Równie dobrze (albo nawet lepiej) było by skorzystać z tablic statycznych przechowujących te kolory...:

const
  aColors: array [0 .. 3] of TColor = (clBlack, clRed, clGreen, clBlue);

//...

  Memo1.Font.Color := aColors[RadioGroup1.ItemIndex];

Z sześciu linii zrobiły się dwie;

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