Strona g│≤wna

 

Przechodzenie do dowolnej linii w Memo

Zapewne w wielu edytorach widzia│e╢ takie co╢: na dole napisane jest, w kt≤rej linii znajduje siΩ kursor. My poka┐emy Wam dodatkowo jak przechodziµ do dowolnej linii w Memo lub RichEdit i wstawiaµ tekst w│a╢nie w miejsce ustawionego kursora. 

Najpierw funkcja pobieraj▒ca numer linii oraz znaku w Memo. 

Listing 6.1


function TMainForm.GetCursor: TPoint;
begin
{
  Jako rezultad Y zostaje przypisana wartosc plynaca z komunikatu
  EM_LINEFROMACHER. Komunikat podaje numer linii, w ktorej znajduje
  sie kursor. Jezeli parametr wParam to $FFFF to podaje numer linii, w ktorej
  umieszczony jest kursor.
}
  Result.Y := Memo.Perform(EM_LINEFROMCHAR, $FFFF, 0);
{
  Ponizsza wartosc niesie ze soba informacje o numerze znaku w linii.

  Komunikat EM_LINEINDEX to informacja o pozycji pierwszego znaku w linii okreslonej
  poprzez parametr wParam. Jezeli wParam to $FFFF zwraca numer pierwszego znaku
  w linii, w ktorej znajduje sie kursor.

  Jezeli od wartosci SelStart komponentu Memo odejmiemy rezultad wykonania
  komunikatu to otrzymamy numer znaku, w ktorym znajduje sie kursor.
}
  Result.X := Memo.SelStart - Memo.Perform(EM_LINEINDEX, $FFFF, 0);
{
  Obie wartosci trzeba podniesc o jeden gdyz w Delphi pierwsza linia bedzie
  oznaczona jako 0, a my tego nie chcemy :)
}
  Inc(Result.X);
  Inc(Result.Y);
end;

Funkcja ta jako rezultat zwraca zmienn▒ typu TPoint, kt≤ra przechowuje wsp≤│rzΩdne X i Y kt≤re oznaczaj▒ pozycjΩ w Memo. W│a╢ciwie wiΩkszo╢µ wa┐nych rzeczy zosta│a ju┐ opisane w komentarzach. 

Teraz procedura ustawiaj▒ca kursor - trochΩ prostsza: 

Listing 6.2


procedure TMainForm.SetCursor(Row, Column: Integer);
begin
{
  Pierwsze polecenie ustawia kursor w linii okreslonej parametrem Row.
  Drugie polecenie dodaje do tego wartosc parametru Column, ktore oznacza
  numer znaku w linii.
}
  Memo.SelStart := Memo.Perform(EM_LINEINDEX, Row, 0);
  Memo.SelStart := Memo.Perform(EM_LINEINDEX, Row, 0) + Column;
end;

Dwie g│≤wne procedury ju┐ mamy - teraz pozostaje je tylko wykorzystaµ. Informacje dotycz▒ce pozycji kursora bΩd▒ wy╢wietlane w komponencie typu TPanel:

Listing 6.3


(****************************************************************)
(*                                                              *)
(*       Copyright (C) 2001 by Service for programmers          *)
(*            Build:  13.04.2001  -  Adam Boduch                *)
(*             HTTP://WWW.PROGRAMOWANIE.OF.PL                   *)
(*      E - mail:  boduch@poland.com                            *)
(*                                                              *)
(****************************************************************)

unit MainFrm;

interface

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

type
  TMainForm = class(TForm)
    Memo: TMemo;
    Panel: TPanel;
    btnSetCursor: TButton;
    edtLine: TEdit;
    edtChar: TEdit;
    procedure MemoKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure btnSetCursorClick(Sender: TObject);
  private
    procedure SetCursor(Row, Column : LongInt);
    function GetCursor : TPoint;
  end;

var
  MainForm: TMainForm;

implementation

{$R *.DFM}


function TMainForm.GetCursor: TPoint;
begin
{
  Jako rezultad Y zostaje przypisana wartosc plynaca z komunikatu
  EM_LINEFROMACHER. Komunikat podaje numer linii, w ktorej znajduje
  sie kursor. Jezeli parametr wParam to $FFFF to podaje numer linii, w ktorej
  umieszczony jest kursor.
}
  Result.Y := Memo.Perform(EM_LINEFROMCHAR, $FFFF, 0);
{
  Ponizsza wartosc niesie ze soba informacje o numerze znaku w linii.

  Komunikat EM_LINEINDEX to informacja o pozycji pierwszego znaku w linii okreslonej
  poprzez parametr wParam. Jezeli wParam to $FFFF zwraca numer pierwszego znaku
  w linii, w ktorej znajduje sie kursor.

  Jezeli od wartosci SelStart komponentu Memo odejmiemy rezultad wykonania
  komunikatu to otrzymamy numer znaku, w ktorym znajduje sie kursor.
}
  Result.X := Memo.SelStart - Memo.Perform(EM_LINEINDEX, $FFFF, 0);
{
  Obie wartosci trzeba podniesc o jeden gdyz w Delphi pierwsza linia bedzie
  oznaczona jako 0, a my tego nie chcemy :)
}
  Inc(Result.X);
  Inc(Result.Y);
end;

procedure TMainForm.SetCursor(Row, Column: Integer);
begin
{
  Pierwsze polecenie ustawia kursor w linii okreslonej parametrem Row.
  Drugie polecenie dodaje do tego wartosc parametru Column, ktore oznacza
  numer znaku w linii.
}
  Memo.SelStart := Memo.Perform(EM_LINEINDEX, Row, 0);
  Memo.SelStart := Memo.Perform(EM_LINEINDEX, Row, 0) + Column;
end;

procedure TMainForm.MemoKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
{ Jezeli uzytkownik nacisnie klawisz to wywolana zostanie procedura, a
  informacja o numerze linii i znaku pojawi sie na Panelu. }
  Panel.Caption := Format('Linia %d, znak: %d', [GetCursor.Y, GetCursor.X]);
end;

procedure TMainForm.btnSetCursorClick(Sender: TObject);
begin
{
  Po nacisnieciu przycisku pobierane zostaja dane z komponentow tekstowych
  i na podst. tych danych w komponencie Memo ustawiany zostaje kursor, a
  w miejsce kursora dodany zostaje tekst.
}
  SetCursor(StrToInt(edtLine.Text), StrToInt(edtChar.Text));
  Memo.SelText := ' www.programowanie.of.pl ';
end;

end.

Adam Boduch