[ New messages · Members · Forum rules · Search · RSS ]
  • Page 1 of 1
  • 1
Forum » General category » BASIC programming » Line numbers in Richedit
Line numbers in Richedit
ZlatkoDate: Monday, 2020-02-10, 7:50 PM | Message # 1
Lieutenant
Group: Administrators
Messages: 62
Reputation: 0
Status: Offline
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  or OxygenBasic


Code
Procedure 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


and nain:

Code
Procedure 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
 
ZlatkoDate: Saturday, 2020-02-15, 1:03 PM | Message # 2
Lieutenant
Group: Administrators
Messages: 62
Reputation: 0
Status: Offline
There is a good solution in masm32:

Code
include \masm32\include\masm32rt.inc

DlgRichEdit MACRO dstyle,tx,ty,wd,ht,ctlID
    align_4 edi
    mov DWORD PTR [edi+0],  WS_VISIBLE or WS_CHILD or dstyle
    mov WORD  PTR [edi+8],  tx
    mov WORD  PTR [edi+10], ty
    mov WORD  PTR [edi+12], wd
    mov WORD  PTR [edi+14], ht
    mov WORD  PTR [edi+16], ctlID
    add edi, 18
    ustring "RichEdit20A"
    align_2 edi
    add edi, 2
ENDM

IDC_EDIT    EQU 100
MARGIN_X    EQU 30

.data?
    g_hInstance     HINSTANCE ?
    g_pOrgWndProc   WNDPROC ?
.code
WndProc  proc uses esi edi ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL pt:POINT
LOCAL sz[16]:CHAR
LOCAL lc:DWORD
LOCAL rect:RECT,rgn:HRGN

    invoke CallWindowProc,g_pOrgWndProc,hWnd,uMsg,wParam,lParam
    .if uMsg == WM_PAINT
        push eax
        .if rvx(lc=SendMessage,hWnd,EM_GETLINECOUNT,0,0)
            fnx ebx = GetDC,hWnd

            fn SaveDC,ebx
            fn GetClientRect,hWnd,&rect
            fn SelectClipRgn,ebx,rvx(rgn = CreateRectRgn,rect.left,rect.top,rect.right,rect.bottom)
            
            ;fnx br = SelectObject,ebx,rv(CreateSolidBrush,bkColor)
            invoke BitBlt,ebx,0,0,MARGIN_X,rect.bottom,ebx,0,0,PATCOPY
            ;fn DeleteObject,rv(SelectObject,ebx,br)
            
            fnx esi=SendMessage,hWnd,EM_GETFIRSTVISIBLELINE,0,0
            .while esi <= lc
                .break .if rv(SendMessage,hWnd,EM_LINEINDEX,esi,0) == -1
                fn SendMessage,hWnd,EM_POSFROMCHAR,&pt,eax
                mov eax,pt.y
                .break .if SDWORD ptr eax > rect.bottom
                fn wsprintf,&sz,"%lu",&[esi+1]
                fn TextOut,ebx,0,pt.y,&sz,rv(lstrlen,&sz)
                add esi,1
            .endw
            fn RestoreDC,ebx,-1
            fn DeleteObject,rgn
            fn ReleaseDC,hWnd,ebx
        .endif
        pop eax
    .endif
    ret
    
WndProc endp

DlgProc proc uses esi edi ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
LOCAL rect:RECT

    .if uMsg == WM_INITDIALOG
        invoke SendDlgItemMessage,hWnd,IDC_EDIT,EM_SETMARGINS,EC_LEFTMARGIN,MARGIN_X
        fnx g_pOrgWndProc = SetWindowLong,rv(GetDlgItem,hWnd,IDC_EDIT),GWL_WNDPROC,WndProc
        xor eax,eax
    .elseif uMsg == WM_CLOSE
        fn EndDialog,hWnd,0
    .else
        xor eax,eax
    .endif
    ret
    
DlgProc endp

main proc
    
    fnx g_hInstance = GetModuleHandle,0
    fn LoadLibrary,"Riched20.dll"
    
    Dialog "test","MS Sans Serif",12,WS_OVERLAPPED or WS_SYSMENU or DS_CENTER,1,10,10,100,100,1024
    DlgRichEdit ES_MULTILINE or ES_WANTRETURN or ES_AUTOHSCROLL or ES_AUTOVSCROLL ,0,0,90,50,IDC_EDIT
    CallModalDialog g_hInstance,0,DlgProc,0
    
    exit
main endp
end main


 
ZlatkoDate: Wednesday, 2020-02-19, 4:53 PM | Message # 3
Lieutenant
Group: Administrators
Messages: 62
Reputation: 0
Status: Offline
And finally with little( large) help of Charles Pegge author of Oxygen basic

Hi Charles
work excellent  

I see now where i make mistakes, it is about push/pop as i expect,
I simply forget to use IF  
and i don't know that we have in o2 EXIT IF ...
probably because i never use it.
I will try to addapt this code to one of my programs with more colors.
all best  


Code
'http://masm32.com/board/index.php?topic=3079.0
'http://www.jose.it-berater.org/richedit/iframe/index.htm
'http://forums.codeguru.com/showthread.php?446242-rich-edit-control-line-numbering-number
'https://groups.google.com/forum/#!topic/borland.public.cppbuilder.vcl.components.using/4cEJOqvXs0U

'include \masm32\include\masm32rt.inc
uses dialogs

'macro DlgRichEdit(dstyle,tx,ty,wd,ht,ctlID)
'    align_4 edi
'    mov DWORD PTR [edi+0],  WS_VISIBLE or WS_CHILD or dstyle
'    mov WORD  PTR [edi+8],  tx
'    mov WORD  PTR [edi+10], ty
'    mov WORD  PTR [edi+12], wd
'    mov WORD  PTR [edi+14], ht
'    mov WORD  PTR [edi+16], ctlID
'    add edi, 18
'    ustring "RichEdit20A"
'    align_2 edi
'    add edi, 2
'end macro

% IDC_EDIT 100
% IDC_RICHEDIT    101
% MARGIN_X  30

'.data?
    sys g_hInstance     'HINSTANCE ?
    sys g_pOrgWndProc   'WNDPROC ?
'.code
'WndProc  proc uses esi edi ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
'
function WndProc(sys hWnd,UMsg,wParam,lParam) as int callback
=============================================================
POINT  pt
CHAR sz[16]
DWORD lc
RECT crect
int rgn
int dret
int hDC
int line
int charpos

    dret=CallWindowProc(g_pOrgWndProc,hWnd,uMsg,wParam,lParam)

    if uMsg == WM_PAINT
        lc=SendMessage(hWnd,EM_GETLINECOUNT,0,0)
        if lc
            hDC = GetDC(hWnd)
            SaveDC(hDC)
            GetClientRect(hWnd,&crect)
            rgn = CreateRectRgn(crect.left,crect.top,crect.right,crect.bottom)
            SelectClipRgn(hDC,rgn)
           
            ;fnx br = SelectObject,ebx,rv(CreateSolidBrush,bkColor)
            % PATCOPY 0x00F00021
            BitBlt(hDC,0,0,MARGIN_X,crect.bottom, hDC,0,0,PATCOPY)
            ;fn DeleteObject,rv(SelectObject,ebx,br)
           
            line=SendMessage(hWnd,EM_GETFIRSTVISIBLELINE,0,0)
            while line <= lc
                charpos = SendMessage(hWnd,EM_LINEINDEX,line,0)
                exit if charpos == -1
                SendMessage(hWnd,EM_POSFROMCHAR,&pt,charpos)
                exit if pt.y > crect.bottom
                'wide char
                wsprintf(&sz,"%lu",line+1)
                TextOut(hDC,0,pt.y,sz,len(sz))
                line++
            wend
            RestoreDC(hDC,-1)
            DeleteObject(rgn)
            ReleaseDC(hWnd,hDC)
        endif      
    endif
    return dret
end function 'wndproc

'DlgProc proc uses esi edi ebx hWnd:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
function DlgProc(sys hWnd,uMsg,wParam,lParam) as int callback
=============================================================
Rect crect

    if uMsg == WM_INITDIALOG
         % EC_LEFTMARGIN 1
         SendDlgItemMessage(hWnd,IDC_EDIT,EM_SETMARGINS,EC_LEFTMARGIN,MARGIN_X)
        g_pOrgWndProc = SetWindowLong(GetDlgItem(hWnd,IDC_EDIT),GWL_WNDPROC,@WndProc)
        return 0
    elseif uMsg == WM_CLOSE
        return EndDialog(hWnd,0)
    else
        return 0
    endif
end function 'DlgProc endp

'main proc
   
    g_hInstance = GetModuleHandle(0)
    LoadLibrary("Riched20.dll")
   init_common_controls
   
   sys hDlg

   Dialog( 0, 0, 200, 100, "RichEdit modal dialog with line numbers",
                WS_OVERLAPPEDWINDOW or DS_CENTER )
   RichEdit( "RichEdit"+chr(13)+"box", IDC_EDIT, 0, 0, 200, 100, ES_AUTOHSCROLL or WS_HSCROLL )
   hDlg = CreateModalDialog( null, @DlgProc, 0 )
   
    'Dialog "test","MS Sans Serif",12,WS_OVERLAPPED or WS_SYSMENU or DS_CENTER,1,10,10,100,100,1024)
    'DlgRichEdit(ES_MULTILINE or ES_WANTRETURN or ES_AUTOHSCROLL or ES_AUTOVSCROLL ,0,0,90,50,IDC_EDIT)
    'CallModalDialog(g_hInstance,0,@DlgProc,0)

   
'exit
'main endp
'end main
 
Forum » General category » BASIC programming » Line numbers in Richedit
  • Page 1 of 1
  • 1
Search: