Ir para conteúdo
Fórum Script Brasil
  • 0

Como Saber O Numero Da Linha Em Que Você está No Richedit?


D4n1l0d

Pergunta

tp, sabe aqueles programas que mostram no rodape o numero da linha e o numero da caractere em que você está?? tp o editor de unit que mostra linha:caractere ( 10:12 ) ==> linha 10 , caractere 12

a caractere em sei usando o

richedit1.SelStart

que me fala aonde a seleção começa, mas serve

e agora

como eu faço pra saber o numero da linha que você está editando??

Link para o comentário
Compartilhar em outros sites

8 respostass a esta questão

Posts Recomendados

  • 0

Não encontrei outro meio de viabilizar o que você queria e como até agora não apareceu uma sugestão, então vou postar a minha.

Achei que ficaria complicado explicar, então fiz as alterações naquele seu código que "corrigi" e lhe postei anteriormente. Considerei que você tem uma StatusBar no form:

type
  TForm1 = class(TForm)
  ...
  private
    ParssingText :Boolean;  // apenas para segurança, prefiro não arriscar
  end;
...

procedure TForm1.FormCreate(Sender: TObject);
begin
  ParssingText := False;
end;

procedure TForm1.RichEdit1KeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
 // processa as teclas de movimentação de texto 
  if Key in [VK_BACK, VK_RETURN, VK_PRIOR, VK_NEXT, VK_UP, VK_DOWN, VK_HOME, VK_END, VK_LEFT, VK_RIGHT] then
    RichEdit1.OnChange(Sender);
end;

procedure TForm1.RichEdit1Change(Sender: TObject);
var
  PosNaLinha,
  PosNoTexto,
  LenLinha,
  IdxLinha,
  IdxColuna,
  ContaPos,
  SavedPos :integer;
begin
 // não executa o procedimento se ainda estiver processando o texto
  if ParssingText then
    Exit;

  ParssingText := True;
  SavedPos := richedit1.SelStart;
  IdxLinha := 0;
  ContaPos := 0;
  repeat
    LenLinha := Length(RichEdit1.Lines[IdxLinha]) +2;  // soma os caracteres #10 e #13
    if (ContaPos +LenLinha) = SavedPos then  // ocorre sempre que teclar enter (linha em branco)
    begin
      IdxColuna := 0; // Início da linha
      Inc(IdxLinha);  // Avança Linha
      Break;
    end else
      if (ContaPos +LenLinha) > SavedPos then  // quando passar da posição do cursor sai
      begin
        IdxColuna := SavedPos -ContaPos;  // Posição do cursor na linha
        Break;
      end;
    Inc(ContaPos, LenLinha);
    Inc(IdxLinha);
  until IdxLinha > RichEdit1.Lines.Count;
  StatusBar1.Panels[0].Text := Format('%d:%d', [IdxLinha +1,IdxColuna +1]);

  PosNaLinha := 0;
  PosNoTexto := 0;
  for IdxLinha := 0 to richedit1.Lines.Count -1 do
...  // segue com o código do post anterior

Talvez até desse para integrar o código do primeiro loop (que calcula o posicionamento do cursor) no segundo, aproveitando o mesmo, mas ficou complicado de mais o gerenciamento das variáveis envolvidas, então deixei assim para simplificar.

Espero ter ajudado.

[]s

Link para o comentário
Compartilhar em outros sites

  • 0

Tente utilizar WndProc:

procedure WndProc(var Msg:TMessage); override;
procedure TForm1.WndProc(var Msg:TMessage);
begin
  if RE1 <> nil then
  begin
    Label1.Caption := IntToStr(RichEdit1.CaretPos.Y+1) + ':' +
                               IntToStr(RichEdit1.CaretPos.X+1);
    Label1.Refresh;
  end;
  inherited;
end;

Oops, RE1 = RichEdit1

Link para o comentário
Compartilhar em outros sites

  • 0

Olá Micheus, acho que a mais correta seria escrever na WindowProc do RichEdit, porque a WndProc é executada para todas as msgs do Form e a maioria delas não são para o RE. O problema da WindowProc é que tem que se conhecer as msgs para atualizar o Label, que eu não conheço todas, senão provavelmente dará um StackOverflow.

Link para o comentário
Compartilhar em outros sites

  • 0
acho que a mais correta seria escrever na WindowProc do RichEdit, porque a WndProc é executada para todas as msgs do Form e a maioria delas não são para o RE
O problema da WindowProc é que tem que se conhecer as msgs para atualizar o Label, que eu não conheço todas, senão provavelmente dará um StackOverflow
duas boas observações.

Acho que o primeiro problema poderia ser corrigido reescrevendo o procedimento de janela para o RichEdit - e não precisamos derivar um novo componente, de TRichEdit, para isto, certo?!

O segundo problema poderiamos resolver levando em conta a solução do primeiro problema e o fato de que as mensagens que influenciarão na movimentação do cursor (posicionamento no texto) serão a do click do botão esquerdo do mouse (mensagem WM_LBUTTONDOWN) e uma tecla pressionada (mensagem WM_KEYDOWN).

vejamos como ficaria minha proposta associada a sua solução (s3c):

...
type
  TForm1 = class(TForm)
  ...
  private
    SavedRichEditProc :TWndMethod;
    procedure NewRichEditProc(var Message: TMessage);
  ...
  end;

 ...

procedure TForm1.NewRichEditProc(var Message: TMessage);
begin
  case Message.Msg of
    WM_LBUTTONDOWN,
    WM_KEYDOWN:
      begin
// mative minha status bar
        StatusBar1.Panels[0].Text := IntToStr(RichEdit1.CaretPos.Y+1) + ':' +
                                     IntToStr(RichEdit1.CaretPos.X+1);
// mative seu label
        Label1.Caption := IntToStr(RichEdit1.CaretPos.Y+1) + ':' +
                                   IntToStr(RichEdit1.CaretPos.X+1);
        Label1.Refresh;
      end;
  end;
// aqui chamamos o procedimento salvo no OnShow do form
  SavedRichEditProc(Message);
end;

procedure TForm1.FormShow(Sender: TObject);
begin
 // o teste previne para o caso de o form não for modal (ShowModal) e vier a ser 
 // mostrado várias vezes (usando apenas Show) durante sua existência
  if not Assigned(SavedRichEditProc) then
  begin
   // salvamos o procedimento de janela padrão do RichEdit
    SavedRichEditProc := RichEdit1.WindowProc;
   // setamos ele para o nosso novo procedimento
    RichEdit1.WindowProc := NewRichEditProc; 
  end;
end;

Eu optei por alterar o procedimento de janela padrão do RichEdit no evento OnShow do form, porque se alguém vier a aproveitar esta idéia para outra situação, deve ter em mente que durante o processo de criação (no OnCreate) das janelas (principal e filhas) há uma avalanche de eventos. Assim, se as mensagens corretas não forem filtradas, há o risco de seu form não aparecer (experimente colocar no OnCreate e retirar o filtro - case). Além do mais, em nosso caso, o RichEdit está disponível para edição apenas após a janela ser mostrada.

Porém haverá um efeito colateral que naquele meu, imenso e grosseiro, exemplo consegui contornar. Quando você tecla enter no fim da linha - indo para uma nova - o indicador de posição na linha do componente não é atualizado até que se começe a digitar algo. Porém, isto também deve poder ser contornado.

Link para o comentário
Compartilhar em outros sites

  • 0

Ok s3c. não havia percebido que a atualização da posição estava um pouco atrasada.

O negócio é interceptar outras mensagens:

...
  case Message.Msg of
    WM_LBUTTONUP,  // atualiza quando o botão é solto - a caret já foi atualizado
    WM_KEYUP,  // atualiza quando a tecla é solta - a caret já foi atualizado
    WM_KEYDOWN,  // isso evita que ao se manter a tecla pressionada a posição não seja atualizada
    WM_SETFOCUS:  // ao receber o foco
      begin
        StatusBar1.Panels[0].Text := IntToStr(RichEdit1.CaretPos.Y+1) + ':' +
...

O motivo daquele efeito colateral, que citei no meu post anterior, era devido ao que você colocou no seu post acima. Agora ficou ok e acredito que não precisará de timer (era só uma questão de pegar a posição no momento correto).

[]s

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,3k
    • Posts
      652,4k
×
×
  • Criar Novo...