Numery linii
Adam Boduch
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.
function TMainForm.GetCursor: TPoint;
begin
{
Jako rezultat Y zostaje przypisana wartość płynąca z komunikatu
EM_LINEFROMACHER. Komunikat podaje numer linii, w której znajduje
się kursor. Jeżeli parametr wParam to $FFFF to podaje numer linii, w której
umieszczony jest kursor.
}
Result.Y := SendMessage(Memo.Handle, EM_LINEFROMCHAR, -1, 0);
{
Poniższa wartość niesie ze sobą informacje o numerze znaku w linii.
Komunikat EM_LINEINDEX to informacja o pozycji pierwszego znaku w linii określonej
poprzez parametr wParam. Jeżeli wParam to $FFFF zwraca numer pierwszego znaku
w linii, w której znajduje się kursor.
Jeżeli od wartości SelStart komponentu Memo odejmiemy rezultat wykonania
komunikatu to otrzymamy numer znaku, w którym znajduje się kursor.
}
Result.X := Memo.SelStart - SendMessage(Memo.Handle, EM_LINEINDEX, -1, 0);
{
Obie wartości trzeba podnieść o jeden gdyż w Delphi pierwsza linia będzie
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:
procedure TMainForm.SetCursor(Row, Column: Integer);
begin
{
Pierwsze polecenie ustawia kursor w linii określonej parametrem Row.
Drugie polecenie dodaje do tego wartość parametru Column, które oznacza
numer znaku w linii.
}
Memo.SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, -1, 0);
Memo.SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, -1, 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:
(****************************************************************)
(* *)
(* 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 := SendMessage(Memo.Handle, EM_LINEFROMCHAR, -1, 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 - SendMessage(Memo.Handle, EM_LINEINDEX, -1, 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 := SendMessage(Memo.Handle, EM_LINEINDEX, -1, 0);
Memo.SelStart := SendMessage(Memo.Handle, EM_LINEINDEX, -1, 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.4programmers.net';
end;
end.
Do (|) i tyle :P
Zamiast:
Powinno być:
I wtedy działa OK
a dlaczego nie piszesz nic o WordWrap? Gdy WordWrap = True, to zwracany jest numer linii i kolumny z ekranu (zawinięcie wiersza zwiększa ilość linii).
Stawiam browar dla tego kto wie jak wyciągnąć prawdziwy numer linii (w miarę szybko, bez skanowania wszystkich znaków EOL).
"rezultad", "Komunikat podaje numer linii, w ktorej znajduje
sie kursor. Jezeli parametr wParam to $FFFF to podaje numer linii, w ktorej
umieszczony jest kursor."
i to Ty Adamie? :P
wstawiłem i mi wyskoczyło duuuuużo błedów