June 05, 2020, 12:38:22 am

News:

IonicWind Snippit Manager 2.xx Released!  Install it on a memory stick and take it with you!  With or without IWBasic!


Line Numbers in Richedit control using margins

Started by aurelCB, February 10, 2020, 09:43:38 am

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

aurelCB

February 10, 2020, 09:43:38 am Last Edit: February 10, 2020, 09:46:52 am by aurelCB
Hello
This topic i open as reference and i hope that would be usefull for anyone who wish to add
line numbers in his own text/code editor using richedit control and margin.

..but now something offtopic
I hope that nobody kill me because code is in Purebasic.
Yes i search trough many web places and cannot found anything usefull and simple
and as possible easy to understand and use with basic-like syntax
then i found one large program on PB forum - html editor which have
just i want line numbers in richedit control.
It looks to me preaty simple with few api functions...
I tested program with PB compiler and work excellent ,line numbering work like in any code editor.
All code for line numbers in two routines/functions/procedures ..so should be easy to translate to CB or
EB or IWB ..i hope


QuoteProcedure drawLinenumbers()
  id = GadgetID(#EDIT1)
  hdc = GetDCEx_(id, 0, #DCX_CACHE)

;  hFont = fontId(getGadgetFont(#EDIT1))
  hFont = GetGadgetFont(#EDIT1)

  prevObj = SelectObject_(hDC, hFont)

  GetTextMetrics_(hDC, @tm.TEXTMETRIC)
  fontH = tm\tmHeight

  GetClientRect_(id, rc.RECT)
  rc\right = leftM - 8
  FillRect_(hDC, rc, GetStockObject_(#WHITE_BRUSH))
  SetBkMode_(hDC, #TRANSPARENT)
  SetTextColor_(hDC, $C0C0C0)

  ;get the first line
  first = SendMessage_(id, #EM_GETFIRSTVISIBLELINE, 0, 0)

  ;get the last character/line
  pt.POINT\x = rc\left
  pt\y = rc\bottom
  lastChar = SendMessage_(id, #EM_CHARFROMPOS, 0, pt)
  last = SendMessage_(id, #EM_LINEFROMCHAR, lastChar, 0)
  ; get the first character
  pt\y = rc\top
  firstChar = SendMessage_(id, #EM_CHARFROMPOS, 0, pt)

  ;get the client coordinates fo the first character
  SendMessage_(id, #EM_POSFROMCHAR, @tChar.POINT, firstChar)
  ;adjust linenumber RECT
  rc\top = tChar\y

  For line = first To last
    DrawText_(hDc, Str(line + 1), -1, rc, #DT_RIGHT)
    rc\top + fontH
  Next
  SelectObject_(hDC, prevObj)
  ReleaseDC_(id, hDC)
EndProcedure



QuoteProcedure getLinenumber(id)
  ;gets the linenumber in an editorgadget from the caret position
  SetActiveGadget(id)
  GetCaretPos_(@pos.point)
  char = SendMessage_(GadgetID(id), #EM_CHARFROMPOS, 0, @pos)
  line =  SendMessage_(GadgetID(id), #EM_LINEFROMCHAR, char, 0)
  ProcedureReturn line
EndProcedure
forum for hobby programming:<br />https://aurelsoft.ucoz.com

h3kt0r

I'll try to convert this snippet to iwBasic syntax tonight.

h3kt0r

February 10, 2020, 09:00:14 pm #2 Last Edit: February 10, 2020, 09:47:19 pm by h3kt0r Reason: Update
This is what i've came up with. Haven't tested this snippet yet, you'll have to provide
the code template to create the window, the controls and the corresponding handler.
Don't forget to subclass your Richedit control at first.

Code Select
INT rline, rchar ': Global variables

Sub drawLinenumbers()
Int hdc, hRichEdit, hFont, prevObj, fontH, first, lastChar
Int last, textW, textH, FWEIGHT, FTSIZE, FFLAGS, leftM
RECT rc
POINT pt
POINT tChar
TEXTMETRIC tm
String FONTNAME
FONTNAME = "FixedSys"
FWEIGHT = 0
FTSIZE = 9
FFLAGS = 0
leftM = 54  ': Left margin value
SetFont WIN, FONTNAME, FTSIZE, FWEIGHT, FFLAGS
GETTEXTSIZE (WIN, "0", textW, textH)                 ': Find the desired text Height


  hRichEdit = GetControlHandle (WIN, RICHEDIT_1)
  hdc = GetDC(hRichEdit, 0, DCX_CACHE)

  hFont = CreateFont(textH,0,0,0, FWEIGHT,0,0,0,0,0,0,0,0, FONTNAME)

  prevObj = SelectObject(hDC, hFont)

  GetTextMetrics(hDC, tm)
  fontH = tm.tmHeight

  GetClientRect(hRichEdit, rc)
  rc.right = leftM - 8
  FillRect(hDC, rc, GetStockObject(WHITE_BRUSH))
  SetBkMode(hDC, TRANSPARENT)
  SetTextColor(hDC, 0xC0C0C0)

  ': get the first line
  first = SendMessage(hRichEdit, EM_GETFIRSTVISIBLELINE, 0, 0)

  ': get the last character/line
  pt.x = rc.left
  pt.y = rc.bottom
  lastChar = SendMessage(hRichEdit, EM_CHARFROMPOS, 0, pt)
  last = SendMessage(hRichEdit, EM_LINEFROMCHAR, lastChar, 0)
  ': get the first character
  pt.y = rc.top
  firstChar = SendMessage(hRichEdit, EM_CHARFROMPOS, 0, pt)

  ': get the client coordinates fo the first character
  SendMessage(hRichEdit, EM_POSFROMCHAR, tChar, firstChar)
  ': adjust linenumber RECT
  rc.top = tChar.y

  For rline = first To last
    DrawText(hDc, Str$(rline + 1), -1, rc, DT_RIGHT)
    rc.top+ = fontH
  Next rline
 
  SelectObject(hDC, prevObj)
  ReleaseDC(hRichEdit, hDC)
 
  Return
Endsub

Sub getLinenumber(hRichEdit)
POINT pos
  ': gets the linenumber in a RichEdit control from the caret position
  SetFocus(hRichEdit)
  GetCaretPos(pos)
  rchar = SendMessage(hRichEdit, EM_CHARFROMPOS, 0, pos)
  rline =  SendMessage(hRichEdit, EM_LINEFROMCHAR, rchar, 0)
  Return rline
EndSub

aurelCB

Well yes i know that i must subclass richedit but with or without subclasing not work as in PB
forum for hobby programming:<br />https://aurelsoft.ucoz.com

Andy

Aurel,

I've done it without subclassing (just added it in).

Will send you the code tomorrow as I'm a little busy for the rest of the day.

Andy.
 :)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

aurelCB

QuoteAurel,

I've done it without subclassing (just added it in).

Will send you the code tomorrow as I'm a little busy for the rest of the day.
That is nice to know Andy  ;)

also original C code is without subclassing.No need to hurry!
forum for hobby programming:<br />https://aurelsoft.ucoz.com