Solved

add a gutter to a richedit

Posted on 2004-09-20
8
927 Views
Last Modified: 2013-11-22
I know there are lots of custom richedit components out there, but most of them are shareware, with nag screen and anyway i need to add the gutter to an already customized richedit.

so, the question is, is there a way to add a gutter to a richedit?
if yes, any example code or link that i can follow?

thanks
0
Comment
Question by:urif
  • 3
  • 3
  • 2
8 Comments
 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 12100531
I know that you need to add it by code, but there's an already coded free cmp that have this feauture. Look at Synedit http://synedit.sourceforge.net/download.php...you could read the code to learn how to add it to a ritchedit
0
 

Author Comment

by:urif
ID: 12100568
thanks i tried that option, i even tried using synedit, but the code is a bit complex in some files that it gave me a headache, more than help.
it's a great component in itself, but to change it or extract part of its code, well, that';s another story. to make it short, tried it, didn't work.

thanks anyway
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12103049
Try this. It's for a tCustomMemo, but I believe RichEdit stems from that...

procedure SetMemoMargins(aMemo:tCustomMemo; aLeft,aRight:word);
begin
  if Assigned(aMemo) then
    SendMessage(aMemo.Handle,EM_SETMARGINS,EC_LEFTMARGIN or EC_RIGHTMARGIN,MakeLong(aLeft,aRight));
end;
0
 

Author Comment

by:urif
ID: 12110013
it doesn't do anything.

this is the code i have when i create my richedit:


procedure TForm1.SetMemoMargins(aMemo:TCustomRichEdit; aLeft,aRight:word);
begin
  if Assigned(aMemo) then
    SendMessage(aMemo.Handle,EM_SETMARGINS,EC_LEFTMARGIN or EC_RIGHTMARGIN,MakeLong(aLeft,aRight));
end;


procedure TForm1.FormCreate(Sender: TObject);
var
   t : TTabSheet;
   r : TRichedit;
begin
   DragAcceptFiles(Handle, true);
   t := TTabsheet.Create(self);
   t.PageControl := PageControl1;
   t.parent := PageControl1;
   t.Caption:='Untitled1';
   r := trichedit.create(self);
   r.parent := t;
   r.align := alClient;
   r.Font.Name:='Courier New';
   r.Font.Size:=10;
   r.ScrollBars:=ssBoth;
   r.PopupMenu:=PopupMenu1;
   r.WordWrap:=true;
   r.PlainText:=true;
   r.OnChange:=REChange;
   r.OnKeyUp:=EditorKeyUp;
   r.OnKeyPress:=EditorKeyPress;
   r.OnMouseDown:=EditorMouseDown;
   r.HideSelection:=false;
   r.WantTabs:=true;
   t.show;
   ActiveRich:=r;
   SetMemoMargins(r,100,100);  //<---------------------- now, just playing, but it won't do anything
end;



any ideas?
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 22

Expert Comment

by:Ferruccio Accalai
ID: 12110089
What about this idea?
Here's some code found somewhere and adjusted to have a Gutter Kind....

*** Unit1.pas ***

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    gutter: TRichEdit;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    procedure RichWindowProc(var Message: TMessage);
    procedure SyncVScroll;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  oldRichProc: TWndMethod;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  i: integer;
begin
 OldRichProc := RichEdit1.WindowProc;
 RichEdit1.WindowProc := RichWindowProc;
  // Add the line numbers to the gutter
 for i:=0 to RichEdit1.Lines.Count-1 do
   gutter.Lines.Add(Format('%d',[i+1]));
end;

procedure TForm1.RichWindowProc(var Message: TMessage);
begin
  OldRichProc(Message);

  case Message.Msg of
    WM_VSCROLL:
      // For scrolling via the scroll bar
      gutter.Dispatch(Message);
    WM_MOUSEMOVE:
      // For highlighting text
      // Only if Left button is down
      if ( (GetAsyncKeyState(VK_LBUTTON) and $8000)<>0 ) then
        SyncVScroll;
    WM_TIMER:
      // For scrolling using the mouse wheel - this uses the TIMER event
      SyncVScroll;
    WM_KEYDOWN:
      // For scrolling using the cursor movement keys
      case Message.WParam of
        VK_DOWN,VK_UP,
        VK_PRIOR,VK_NEXT:
          SyncVScroll;
        VK_HOME,VK_END:
          // Only if CTRL is down
          if ( (GetAsyncKeyState(VK_CONTROL) and $8000)<>0 ) then
            SyncVScroll;
      end;
  end;
end;

procedure TForm1.SyncVScroll;
var
  Msg: TWMScroll;
begin
  Msg.Msg := WM_VSCROLL;
  Msg.Pos := GetScrollPos(RichEdit1.Handle,SB_VERT);
  Msg.ScrollBar := 0;
  Msg.ScrollCode := SB_THUMBTRACK;
  gutter.Dispatch(Msg);
  Msg.ScrollCode := SB_THUMBPOSITION;
  gutter.Dispatch(Msg);
  Msg.ScrollCode := SB_ENDSCROLL;
  gutter.Dispatch(Msg);
end;

end.

*** Unit1.dfm ***

object Form1: TForm1
  Left = 192
  Top = 107
  Width = 231
  Height = 259
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object RichEdit1: TRichEdit
    Left = 32
    Top = 0
    Width = 185
    Height = 201
    Lines.Strings = (
      'interface'
      ''
      'uses'
      'Windows, Messages, SysUtils, '
      'Variants, Classes, Graphics, '
      'Controls, Forms,'
      'Dialogs, ComCtrls, StdCtrls;'
      ''
      'type'
      'TForm1 = class(TForm)'
      'RichEdit1: TRichEdit;'
      'gutter: TRichEdit;'
      'procedure FormCreate(Sender: '
      'TObject);'
      'private'
      '{ Private declarations }'
      'procedure RichWindowProc(var '
      'Message: TMessage);'
      'procedure SyncVScroll;'
      'public'
      '{ Public declarations }'
      'end;'
      ''
      'var'
      'Form1: TForm1;'
      'oldRichProc: TWndMethod;'
      ''
      'implementation'
      ''
      '{$R *.dfm}'
      ''
      'procedure TForm1.FormCreate'
      '(Sender: TObject);'
      'var'
      'i: integer;'
      'begin'
      'OldRichProc := '
      'RichEdit1.WindowProc;'
      'RichEdit1.WindowProc := '
      'RichWindowProc;'
      ''
      '// Add the line numbers to the '
      'gutter'
      'for i:=0 to RichEdit1.Lines.Count-1 '
      'do'
      'gutter.Lines.Add(Format(''%d'',[i+1]));'
      'end;'
      ''
      'procedure '
      'TForm1.RichWindowProc(var '
      'Message: TMessage);'
      'begin'
      'OldRichProc(Message);'
      ''
      'case Message.Msg of'
      'WM_VSCROLL:'
      '// For scrolling via the scroll bar'
      'gutter.Dispatch(Message);'
      'WM_MOUSEMOVE:'
      '// For highlighting text'
      '// Only if Left button is down'
      'if ( (GetAsyncKeyState'
      '(VK_LBUTTON) and $8000)<>0 ) '
      'then'
      'SyncVScroll;'
      'WM_TIMER:'
      '// For scrolling using the mouse '
      'wheel - this uses the TIMER event'
      'SyncVScroll;'
      'WM_KEYDOWN:'
      '// For scrolling using the cursor '
      'movement keys'
      'case Message.WParam of'
      'VK_DOWN,VK_UP,'
      'VK_PRIOR,VK_NEXT:'
      'SyncVScroll;'
      'VK_HOME,VK_END:'
      '// Only if CTRL is down'
      'if ( (GetAsyncKeyState'
      '(VK_CONTROL) and $8000)<>0 ) '
      'then'
      'SyncVScroll;'
      'end;'
      'end;'
      'end;'
      ''
      'procedure TForm1.SyncVScroll;'
      'var'
      'Msg: TWMScroll;'
      'begin'
      'Msg.Msg := WM_VSCROLL;'
      'Msg.Pos := GetScrollPos'
      '(RichEdit1.Handle,SB_VERT);'
      'Msg.ScrollBar := 0;'
      'Msg.ScrollCode := '
      'SB_THUMBTRACK;'
      'gutter.Dispatch(Msg);'
      'Msg.ScrollCode := '
      'SB_THUMBPOSITION;'
      'gutter.Dispatch(Msg);'
      'Msg.ScrollCode := '
      'SB_ENDSCROLL;'
      'gutter.Dispatch(Msg);'
      'end;'
      ''
      'end.')
    ScrollBars = ssVertical
    TabOrder = 0
  end
  object gutter: TRichEdit
    Left = 0
    Top = 0
    Width = 33
    Height = 201
    BevelOuter = bvRaised
    BevelKind = bkSoft
    Color = clBtnFace
    TabOrder = 1
  end
end

F68 ;-)
0
 
LVL 7

Expert Comment

by:LRHGuy
ID: 12111486
Try this one, seems to work for a richedit ...

procedure SetMemoMargins(aMemo:tCustomMemo; aLeft,aRight:word);
var
  R:TRect;
begin
  if Assigned(aMemo) then begin
    SendMessage(aMemo.Handle,EM_GetRect,0,longint(@R));
    R.Left:=R.Left+aLeft;
    R.Right:=R.RIght-aRight;
    SendMessage(aMemo.Handle,EM_SetRect,0,longint(@R));
  end;
end;
0
 

Author Comment

by:urif
ID: 12116370
Ferruccio68:
 ok, what it does is to add another richedit to the side? and use it as a gutter?
i tried a solution similar to this but it's a pain in the... to synchonize both things, plus it doesn't look good. there is that line in between the two richedits.... to make it short, tried that before.
the only reason i am asking here is because i tried a lot of possible solutions and so far nothing, i was hopping that someone might give me an answer, thanks so much anyway.

LRHGuy:

i don;t know what richedit are you using, or maybe you are just using a memo. in any case it doesn't work _at all_ with neither delphi 6 nor delphi 7 versions and the richedits that come with them. thanks anyways.

by the way you can download the whole source code from http://www.geocities.com/urifrid/eedit-5.2-src.zip
and tried it yourself. the project is open source so i'll be happy if you want to help
0
 
LVL 7

Accepted Solution

by:
LRHGuy earned 100 total points
ID: 12117509
Here's what I discovered.

In my testing in my own demo, I set the margin by clicking a button. It always worked.

Trying to set the margins before the control is showing, though, doesn't seem to work right.

So, to get it to work in your pgm, here's what I did:

const
  cUMsg1=wm_User+1;

TForm1=
    private
    procedure UMSG1(var Msg:tmessage); message cUMsg1;
    procedure NewActiveRich(aRE:tRichEdit);

procedure TForm1.UMSG1(var Msg: tmessage);
begin
  SetMemoMargins(ActiveRich,30,30);
end;

procedure TForm1.NewActiveRich(aRE:tRichEdit);
begin
  ActiveRich:=aRE;
  PostMessage(Handle,cUMsg1,0,0);
end;


I replaced every occurence of ActiveRich:=   to  NewActiveRich()

It seems to work.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Delphi OLE Error 8 93
problem when i try to pack my dll file with upx 9 71
Path  to current project in Delphi. 2 71
Internet Explorer View Settings Question 15 105
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

914 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now