Link to home
Start Free TrialLog in
Avatar of DanDaemon
DanDaemonFlag for Ukraine

asked on

Special TRichEdit component for text chat software...

Hello All,

I need a special RichEdit for my text chat example...
RichEdit like Miranda-IM message window...

It means that I can select text when somebody sends me message and it will not lost focus and selected area.
I can moving text with vertical scroll bar and when message will be arrived it will not lost text which I was seeing
in this moment... When this richedit lost focus it still not move to bottom when text will be inserted...
But when I move scrollbar or cursor to bottom it will insert text and do auto scroll... etc...

Please see how work ICQ message window or Miranda message window...

Ok, if somebody know same component, please send URL...

Thanks,
Dan
Avatar of geobul
geobul

Hi,

I don't have a component but rather code using standard RichEdit. If the following doesn't fit your needs then I'm sorry for the long post.

Regards, Geo

// The following example adds colored lines to a RichEdit in a timer event.
// If the user has selected text or the vertical scroll bar is not at the bottom
// new lines are saved in a string list and are added when it's possible:
// 1. the mouse is up
// 2. and there is no selected text
// 3. and the vertical scrollbar is at the bottom

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    Timer1: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure RichEdit1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure RichEdit1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  InSelection: boolean; // while mouse is down
  CantAdd: boolean; // do not add lines while true
  NewLines: TStringList; // add them here
  Colors: TStringList; // and their colors

  // the following two vars are for testing only
  count: integer; // line counter for showing
  col: TColor; // current color

implementation

{$R *.DFM}

uses richedit;

// returns true if the last line is visible
function IsLastLineVisible(re: TRichEdit): boolean;
var
  p: tpoint;
  LinesVisible: integer;
begin
  p := Point(1, re.ClientHeight);
  LinesVisible := re.Perform(EM_LINEFROMCHAR, re.Perform(EM_CHARFROMPOS, 0, Integer(@P)), 0);
  if LinesVisible >= re.Lines.Count
  then result := true
  else result := false;
end;

// used only by AddColoredLine procedure
// do not use it directly !!!
procedure AddOneColoredLine(re: TRichEdit; Line: string; c: TColor);
begin
  re.Lines.BeginUpdate;
  try
    re.SelStart := re.Perform(EM_LINEINDEX, re.Lines.Count - 1,0);
    re.Lines.Add(Line);
    re.SelLength := re.Perform(EM_LINEINDEX, re.Lines.Count - 1,0) - re.SelStart;
    re. SelAttributes.Color := c;
  finally
    re.Lines.EndUpdate;
  end;
  // move cursor at the end
  re.SelStart := re.Perform(EM_LINEINDEX, re.Lines.Count,0);
end;

// use this procedure for adding lines
procedure AddColoredLine(re: TRichEdit; Line: string; c: TColor);
var i: integer;
begin
  // determine if we can add new lines
  if (IsLastLineVisible(re)) and (not InSelection) then CantAdd := false
  else CantAdd := true;
  if re.SelLength > 0 then CantAdd := true;
  if CantAdd then begin
    // remember the line
    NewLines.Add(Line);
    Colors.Add(IntToStr(c));
  end else begin
    // add remembered lines if any
    for i := 0 to NewLines.Count - 1 do
      AddOneColoredLine(re, NewLines[i], StrToInt(Colors[i]));
    // clear the remembered lines
    NewLines.Clear;
    Colors.Clear;
    // add current line
    AddOneColoredLine(re, Line, c);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  NewLines := TStringList.Create;
  Colors := TStringList.Create;
  CantAdd := false;

  // for testing
  count := 1;
  col := clRed;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(NewLines) then NewLines.Free;
  if Assigned(Colors) then Colors.Free;
end;

procedure TForm1.RichEdit1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  InSelection := true;
end;

procedure TForm1.RichEdit1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  InSelection := false;
end;

// test routine for changing three colors
procedure ChangeColor;
begin
  if col = clRed then col := clGreen
  else if col = clGreen then col := clBlue
  else col := clRed;
end;

// for testing
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  AddColoredLine(RichEdit1, 'Line '+IntToStr(count), col);
  Inc(count);
  ChangeColor;
end;

end.
BTW, you may use another hidden (not visible) TRichEdit component instead of NewLines stringlist. This way Colors stringlist will become redundant and one line can have more than one color and various styles in it.
Avatar of DanDaemon

ASKER

Hello geobul,

Thank you very much, your source code is very good, but I have one question,
why it stops add line when I select some lines? How can I fix it?
That is the way I've faked that behaviour. I don't add lines to the richedit but keep them in a stringlist and add them all at once when it becomes possible (i.e. when there is no selected text, the last line is visible and the left mouse button is up). If I add a line while there is some selected text up in the richedit everything goes ugly saving the info of the selection and repositioning after the new line is added. I'm not able to fix it in an elegant way. Sorry.
yahh, thank you, but I do not need so :(
i suggest trichview as a richedit component. and trichviewactions. http://www.trichview.com/
ASKER CERTIFIED SOLUTION
Avatar of zoozalp
zoozalp

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thank you DanDaemon, i got my first 500 points ;-)
DanDaemon,

I'm just curious: can TRichView do exactly what you need? I'm asking because I might need that functionality in the near future.

Thanks.
Hello Geobul,

I wrote wrapper for standard TRichEdit and got TRichEdit which works 100% as I need.
It does not lose focuse, selection area and so on...

Will add images and all :)
OK thanks. So, you haven't tried TRichView.
No, I was using it as example for another my job :)