19. Klávesnica, ďalší formulár


Posledná zmena: 26.11.2002

Banner Text 26.11.2002

    čo sme sa doteraz naučili

    • pri práci s komponentom TEdit sme využili udalosť onKeyPress

    čo sa budeme dnes učiť

    • ovládanie programu pomocou klávesnice, napr. klávesov šípok
    • otvorenie ďalšieho formulára

Klávesnica

s klávesnicou pracujeme pomocou troch udalostí:

  • onKeyDown - práve bol zatlačený nejaký kláves
  • onKeyUp - práve bol pustený nejaký kláves
  • onKeyPress - stlačili sme "obyčajný" kláves (ktorý má svoj ASCII kód)

prvé dve udalosti oznámia nie ASCII kód klávesu ale "virtuálny kód" (v Helpe si pozrite identifikátory konštánt) a tiež v parametri Shift zistíme, či bol pri tom zatlačený napr. Shift alebo Ctrl (podobne ako pri udalostiach pri práci s myšou)

nasledujúci program ukáže použitie klávesnice - do formulára umiestnime komponenty Label1 a Timer1 (nastavíme mu nejaký krátky Interval) - teraz môžeme na klávesnici súčasne tlačiť aj viac šípok a tým riadiť pohyb textu po ploche formulára:

pohyb textu vo formulári:

var
  dx,dy:integer;    // môžeme predpokladať, že sú inicializované na 0

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  with Label1 do begin
    Left:=Left+dx;
          // nedá sa urobiť inc(Left,dx); lebo Left nie je premenná
    Top:=Top+dy;
  end;
end;

procedure TForm1.FormKeyDown(Sender:TObject; var Key:Word;
          Shift:TShiftState);
begin
  case Key of
    vk_left:   dx:=-1;
    vk_right:  dx:=1;
    vk_up:     dy:=-1;
    vk_down:   dy:=1;
    vk_escape: Close;
  end;
end;

procedure TForm1.FormKeyUp(Sender:TObject; var Key:Word;
          Shift:TShiftState);
begin
  case Key of
    vk_left,
    vk_right: dx:=0;
    vk_up,
    vk_down:  dy:=0;
  end;
end;
  • pri práci s klávesnicou si treba dávať pozor na iné komponenty, ktoré "kradnú" informácie z klávesnice (napr. Memo, Button, Edit a pod.) - najjednoduchšie riešenie v prípade, že chceme pracovať s klávesnicou, je ich nepoužívať, alebo spracovávať vstup z klávesnice na týchto komponentoch...

Príklad

  • text zadávaný z klávesnice vypisujeme do grafickej plochy Image1, Enter posunie kurzor o riadok nižšie - príklad ilustruje použitie onKeyPress

prvá jednoduchá verzia:

var
  x,y:integer;

procedure TForm1.FormCreate(Sender: TObject);
begin
  x:=20; y:=20;
  with Image1.Canvas.Font do begin
    Name:='Arial'; Height:=50; Style:=[fsBold];
  end;
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key>=' ' then begin
    Image1.Canvas.TextOut(x,y,Key);
    inc(x,20);
  end
  else if Key=#13 then begin
    x:=20; inc(y,50);
  end;
end;
  • druhá verzia ukazuje, ako môžeme zobrazovať textový kurzor, zároveň používa metódu TextExtend, pomocou ktorej zistí šírku a výšku vypisovaného znaku

druhá verzia - proporčné písmo a kurzor:

var
  x,y:integer;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DoubleBuffered:=true;
  x:=20; y:=20;
  with Image1.Canvas, Font do begin
    Name:='Arial'; Height:=50; Style:=[fsBold];
    MoveTo(x,y); LineTo(x,y+Height);
  end;
end;

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
var
  s:TSize;
begin
  with Image1.Canvas do begin       // zmaže kurzor
    Pen.Color:=clWhite;
    MoveTo(x,y); LineTo(x,y+Font.Height);
  end;
  if Key>=' ' then with Image1.Canvas do begin
    TextOut(x,y,Key);
    s:=TextExtent(Key); inc(x,s.cx);
    if x>Image1.Width-20 then Key:=#13;
  end;
  if Key=#13 then begin
    s:=Image1.Canvas.TextExtent('M');
    x:=20; inc(y,s.cy);
  end;
  with Image1.Canvas do begin        // nakreslí kurzor
    Pen.Color:=clBlack;
    MoveTo(x,y); LineTo(x,y+Font.Height);
  end;
end;

NDÚ

  • zrealizujte kláves Backspace - treba si pamätať každý zapísaný znak (v niečom podobnom ako zásobník) - aby sme ho mohli zmazať, treba vedieť jeho pozíciu a buď jeho hodnotu alebo veľkosť

Príklad

  • v ďalšom príklade riadime šípkami viac korytnačiek - len jedna z nich je aktívna, Enter prepína aktívnosť na nasledujúcu korytnačku

viac korytnačiek:

var
  k:TVelaKor;
  akt:integer = 0;

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
begin
  randomize; zmaz;
  k:=TVelaKor.Create;
  for i:=1 to 10+random(10) do
    k.UrobKor(random(sirka-100)+50,random(vyska-100)+50);
  k.HP:=6;
  k.k[akt].FP:=clRed;
  k.Dopredu(0);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  k.Free;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
    vk_left:   k.k[akt].Vlavo(90);
    vk_right:  k.k[akt].Vpravo(90);
    vk_up:     with k.k[akt] do begin
                 FP:=clBlack; Dopredu(10); FP:=clRed; Dopredu(0);
               end;
    vk_return: begin
                 with k.k[akt] do begin FP:=clBlack; Dopredu(0); end;
                 akt:=(akt+1) mod k.pk;
                 with k.k[akt] do begin FP:=clRed; Dopredu(0); end;
               end;
  end;
end;
  • druhá verzia "vizualizuje" aktívnu korytnačku a jej momentálny smer
  • využívame tu pomocnú bitmapu na zapamätanie si stavu plochy tesne pred vykreslením červenej šípky
  • zároveň s ovládaním klávesnice beží časovač, ktorý hýbe aktívnu korytnačku po malých krokoch

viac korytnačiek:

var
  k:TVelaKor;
  akt:integer;
  bmp:TBitmap;

procedure kresliAktivnu;
begin
  bmp.Assign(Form1.Image1.Picture);
  with k.k[akt] do begin
    FP:=clRed; Dopredu(10);
    HP:=7; Dopredu(0);
    HP:=4; Dopredu(-10);
    FP:=clBlack;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
begin
  randomize; zmaz;
  k:=TVelaKor.Create;
  for i:=1 to 10+random(10) do
    k.UrobKor(random(sirka-100)+50,random(vyska-100)+50);
  k.HP:=4;
  k.Dopredu(0);
  bmp:=TBitmap.Create;
  kresliAktivnu;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  k.Free; bmp.Free;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  Image1.Canvas.Draw(0,0,bmp);
  case Key of
    vk_left:   k.k[akt].Vlavo(90);
    vk_right:  k.k[akt].Vpravo(90);
    vk_up:     k.k[akt]. Dopredu(10);
    vk_return: akt:=(akt+1) mod k.pk;
    vk_escape: Close;
  end;
  kresliAktivnu;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Image1.Canvas.Draw(0,0,bmp);
  with k.k[akt] do begin
    Dopredu(1); Vlavo(1);
  end;
  kresliAktivnu;
end;

Príklad

  • v príklade zadefinujeme jednoduchý objekt s bitmapou, ktorý sa potom hýbe niektorým smerom a odráža sa od okrajov plochy - smer sa určuje klávesmi šípok

definovanie jednoduchého objektu s bitmapou:

type
  TObrazok = class
    bmp:TBitmap;
    x,y,dx,dy:integer;
    constructor Create(meno:string; xx,yy:integer);
    destructor Destroy; override;
    procedure posun(sir,vys:integer);
    procedure kresli(c:TCanvas);
  end;

constructor TObrazok.Create(meno:string; xx,yy:integer);
begin
  bmp:=TBitmap.Create;
  bmp.LoadFromFile(meno);
  bmp.TransparentColor:=clWhite;
  bmp.Transparent:=true;
  x:=xx; y:=yy; dx:=0; dy:=0;
end;

destructor TObrazok.Destroy;
begin
  bmp.Free;
end;

procedure TObrazok.posun(sir,vys:integer);
begin
  inc(x,dx); inc(y,dy);
  if (x<0) or (x>sir) then dx:=-dx;
  if (y<0) or (y>vys) then dy:=-dy;
end;

procedure TObrazok.kresli(c:TCanvas);
begin
  c.Draw(x-bmp.Width div 2,y-bmp.Height div 2,bmp);
end;

práca s obrázkovým objektom a s klávesnicou:

var
  a:TObrazok;

procedure TForm1.FormCreate(Sender: TObject);
begin
  randomize;
  a:=TObrazok.Create('opica.bmp',
         random(Image1.Width),random(Image1.Height));
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Image1.Canvas.FillRect(Image1.ClientRect);
  a.posun(Image1.Width,Image1.Height);
  a.kresli(Image1.Canvas);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  a.Free;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
          Shift: TShiftState);
begin
  with a do
    case Key of
      vk_left:  dec(dx);
      vk_right: inc(dx);
      vk_up:    dec(dy);
      vk_down:  inc(dy);
      vk_home:
        begin
          dx:=0; dy:=0;
        end;
    end;
end;

môžeme experimentovať s odrážaním objektu na hranici plochy:

procedure TObrazok.posun(sir,vys:integer); 
begin 
  inc(x,dx); inc(y,dy); 
  if x<0 then begin dx:=abs(dx) div 2; x:=0; end;
  if x>sir then begin dx:=-abs(dx) div 2; x:=sir-1; end;
  if y<0 then begin dy:=abs(dy) div 2; y:=0; end;
  if y>vys then begin dy:=-abs(dy) div 2; y:=vys-1; end;
end;

Otvorenie ďalšieho formulára

  • v našej aplikácii môžeme pracovať aj s viacerými formulármi:
    • niekedy sa nám môže hodiť pre ďalšie výpisy, grafiku, ako dialógové okno pre zadávanie parametrov a pod. (takýto formulár môže fungovať - byť otvorený paralelne s hlavným formulárom),
    • inokedy potrebujeme otvoriť nový formulár tak, aby bol hlavný formulár zatiaľ blokovaný a čakalo sa, kým sa tento nový nezavrie, napr. pre informácie o programe
  • v menu File zvolíme New a Form - automaticky sa vytvorí nový unit (Unit2.pas) - do tohoto nového formulára môžeme poukladať ľubovoľné komponenty, napr. text pomocou Label1, alebo tlačidlo Button1 s textom Ok

do Button1Click môžeme priradiť napríklad Close - uzavretie formulára:

procedure TForm2.Button1Click(Sender: TObject);
begin
  Close;
end;
  • aby sme tento nový formulár mohli otvoriť z hlavného okna, musíme za Implementation vložiť riadok uses Unit2; a napr. na nejaké tlačidlo priradiť otvorenie formulára:

napr.

procedure TForm1.Button1Click(Sender: TObject);
begin
  Form2.ShowModal;    // alebo Form2.Show;
end;
  • ShowModal znamená, že sa nové okno otvorí tak, že sa čaká na jeho uzavretie - až potom sa pokračuje v hlavnom formulári
  • ak by sme namiesto toho použili Show, tak by sa druhé okno otvorilo a boli by aktívne obe: hlavné aj toto nové

skonštruovanie nového formulára

  • nový formulár (napr. okno s informáciami o programe) môžeme vytvoriť aj priamo v programe, napr.

napr.:

procedure TForm1.Button1Click(Sender: TObject);
var
  f:TForm;
begin
  if Shift=[ssRight] then begin
    f:=TForm.Create(self);
    with f do begin
      Name := 'mojformular';
      Caption := 'O programe';
      Width := 350;
      Height := 253;
      BorderStyle := bsSingle;
      Position := poScreenCenter;
      with TLabel.Create(f) do begin
        Name := 'Label';
        Parent := f;
        Font.Height := 24;
        Font.Name := 'Arial';
        Caption := 'Niečo o mojom programe:'#13#13+
                   'je to ukážkový program'#13+
                   'na prácu s rôznymi komponentmi';
        Left := 20;
        Top := 16;
        AutoSize:=true;
      end;
      with TButton.Create(f) do begin
        Name := 'Ok';
        Parent := f;
        Caption := 'Ok';
        Left := 72;
        Top := 192;
        Width := 75;
        Height := 25;
        ModalResult := mrOK;
      end;
      ShowModal;    // zobrazí nový formulár a čaká na jeho zatvorenie
      Free;         // zruší nový formulár
    end;
  end;
end;

Poznámka

  • ak v prostredí Delphi pri vytváraní formulára zvolíme cez pravoklikové menu "View as Text", zobrazí sa textová forma definícií komponentov na formulári - toto môžeme využiť pri konštruovaní formulára, resp. komponentov v našom programe


© 2002 AB, KVI
blaho@fmph.uniba.sk