Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Formatting RichEdit Content

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Formatting RichEdit Content

    I've previously published various ways to format RichEdit content. Here's an example that does 5 kinds of formatting:

    Case - upper/lower
    Character Spacing - horizontal gap between characters
    Line Spacing - vertical gap between lines
    Paragraph Formatting - merge lines separated by a single $crlf into paragraphs
    Underline - underline the currently selected line of text

    Discussion here.

    Code:
    'Compilable Example:  'Jose Includes
    #Compile Exe
    #Dim All
    %Unicode = 1
    #Include "Win32API.inc"
    
    %MultiLineREStyle_Wrap    = %WS_Child Or %WS_ClipSiblings Or %WS_Visible Or %ES_MultiLine Or %WS_VScroll Or %ES_AutoVScroll                    Or %ES_WantReturn Or %ES_NoHideSel Or %WS_TabStop Or %ES_SaveSel
    
    Global RTFExpandA As WStringZ * %Max_Path
    
    Enum Equates Singular
       IDC_RichEdit = 500
       IDC_Case
       IDC_Letters
       IDC_Under
       IDC_Lines
       IDC_Paragraph
    End Enum
    
    Global hDlg,hRichEdit,OldREProc As Dword
    Global UnderlineCurrentLine, WideSpacing, LIneSpacing, CaseType, FormatParagraph As Long
    Global LastUnderLine, TurnOffResult As Long
    Global OriginalText$
    
    Function PBMain() As Long
       Dialog Default Font "Arial Black", 24, 1
       Dialog New Pixels, 0, "PowerBASIC",,,700,700, %WS_OverlappedWindow To hDlg
       OriginalText$ = "This is a formatting" + $CrLf + "test to figure out the" + $CrLf + "formatting code I want!"
       OriginalText$ += $CrLf + $CrLf + OriginalText$
       LoadLibrary("msftedit.dll")
       Control Add "RichEdit50W", hDlg, %IDC_RichEdit, OriginalText$,10, 60, 680, 630, %MultiLineREStyle_Wrap, %WS_Ex_ClientEdge
       Control Handle hDlg, %IDC_RichEdit To hRichEdit
       SendMessage hDlg, %EM_SetEventMask, 0, %ENM_SelChange
       OldREProc = SetWindowLong(hRichEdit, %GWL_WNDPROC, CodePtr(REProc))
    
       Control Add Button, hDlg, %IDC_Case,"Case", 10,10,120,35
       Control Add Button, hDlg, %IDC_Letters,"Ltrs", 140,10,120,35
       Control Add Button, hDlg, %IDC_Under,"Under", 270,10,120,35
       Control Add Button, hDlg, %IDC_Lines,"Lines", 410,10,120,35
       Control Add Button, hDlg, %IDC_Paragraph,"Para", 560,10,120,35
       Dialog Show Modal hDlg Call DlgProc
    End Function
    
    CallBack Function DlgProc() As Long
       Select Case Cb.Msg
          Case %WM_InitDialog
             RTFExpandA = "\expndtw720 "
          Case %WM_Command
             Select Case Cb.Ctl
                Case %IDC_Case        : Format_Case(hDlg,%IDC_RichEdit)           'hDlg/%IDC_RichEdit are Global, but in practice I might Format one of several RichEdit controls
                Case %IDC_Letters     : Format_WideSpacing(hDlg,%IDC_RichEdit)
                Case %IDC_Lines       : Format_LineSpacing(hDlg,%IDC_RichEdit)
                Case %IDC_Paragraph   : Format_Paragraph(hDlg,%IDC_RichEdit)
                Case %IDC_Under       : Format_Underline
             End Select
       End Select
    End Function
    
    Sub sBeep : WinBeep (250,300) : End Sub
    
    Function REProc(ByVal hWnd As Dword, ByVal wMsg As Long, ByVal wParam As Dword, ByVal lParam As Long) As Long
       Local CallSetCaret, i As Long, KeyState As Long
       Select Case wMsg
          Case %WM_KeyUp
            If (hWnd = hRichEdit) And UnderLineCurrentLine Then RERemoveUnderLines(hRichEdit) : REUnderLineCurrentLine(hRichEdit)
          Case %WM_LButtonUp
            If (hWnd = hRichEdit) And UnderLineCurrentLine Then RERemoveUnderLines(hRichEdit) : REUnderLineCurrentLine(hRichEdit)
          Case %WM_Destroy
             SetWindowLong(hWnd, %GWL_WNDPROC, OldREProc)
       End Select
       Function = CallWindowProc(OldREProc, hWnd, wMsg, wParam, lParam)
    End Function
    
    Function RESelectedText(hControl As Dword) As String   'always get text from hRichEdit
       Local rP As CharRange, temp$
       SendMessage hControl, %EM_ExGetSel, 0, VarPtr(rP)
       Control Get Text GetParent(hControl), %IDC_RichEdit To temp$
       Replace $CrLf With $Lf In temp$
       temp$ = Mid$(temp$, rP.cpmin+1 To rP.cpmax)
       Replace $Lf With $CrLf In temp$
       Function = temp$
    End Function
    
    Sub RERemoveUnderLines(hControl As Dword)  'remove underline from all words
       Local cf As CharFormat2
       RETurnOff hControl
       cf.cbSize = SizeOf(cf)
       SendMessage hControl, %EM_GetCharFormat, %SCF_All, VarPtr(cf)
       cf.dwMask = %CFM_UnderLine
       cf.dwEffects = cf.dwEffects Xor Not %CFM_Underline
       SendMessage hControl, %EM_SetCharFormat, %SCF_All, VarPtr(cf)
       RETurnON hControl
    End Sub
    
    Sub REUnderlineCurrentLine(hControl As Dword)
       Local cf As CharFormat2, rP As CharRange
       Local CurrentLine, LineLength As Long
    
       RETurnOff(hControl)
    
       CurrentLine = SendMessage(hControl, %EM_EXLineFromChar, 0,-1)   'current line# / 1st line of selection
       LastUnderLine = CurrentLine
       rP.cpMin = SendMessage(hControl, %EM_LineIndex, CurrentLine, 0)  'position of 1st char in line#
       LineLength = SendMessage(hControl, %EM_LineLength, rP.cpMin, 0)  'length of line starting at that char position
       rP.cpMax = rP.cpMin + LineLength
       SendMessage(hControl, %EM_EXSetSel, 0, VarPtr(rP))               'select specified text (rP.cpmin-rP.cpmax)
    
       'remove existing underlines
       cf.cbSize = SizeOf(cf)
       SendMessage hControl, %EM_GetCharFormat, %SCF_All, VarPtr(cf)
       cf.dwMask = %CFM_UnderLine
       cf.dwEffects = cf.dwEffects Xor Not %CFM_Underline
       SendMessage hControl, %EM_SetCharFormat, %SCF_All, VarPtr(cf)
    
       'underline
       cf.cbSize = SizeOf(cf)
       SendMessage hControl, %EM_GetCharFormat, %SCF_Selection, VarPtr(cf)
       cf.dwMask = %CFM_UnderLine
       cf.dwEffects = cf.dwEffects Xor %CFM_Underline
       SendMessage hControl, %EM_SetCharFormat, %SCF_Selection, VarPtr(cf)
       SendMessage(hControl, %EM_SetSel, rP.cpMin, rP.cpMin)
    
       RETurnOn(hControl)
    
    End Sub
    
    Sub RETurnOff(hControl As Dword)
       TurnOffResult = SendMessage(hControl, %EM_GETEVENTMASK, 0, 0)  'get current event mask
       SendMessage(hControl, %EM_SETEVENTMASK, 0, 0)
       SendMessage(hControl, %WM_SETREDRAW, 0, 0)
    End Sub
    
    Sub RETurnOn(hControl As Dword)
       SendMessage hControl, %WM_SETREDRAW, 1, 0
       InvalidateRect hControl, ByVal %NULL, 0 : UpdateWindow hControl
       If TurnOffResult Then SendMessage(hControl, %EM_SETEVENTMASK, 0, TurnOffResult)  'restore event mask
    End Sub
    
    Sub Format_Case(hParent As Dword, ControlID As Long)
       CaseType Xor=1
       RESetText_New hParent, ControlID
    End Sub
    
    Sub Format_WideSpacing(hParent As Dword, ControlID As Long)
       Incr WideSpacing : If WideSpacing > 2 Then WideSpacing = 0
       RESetText_New hParent, ControlID
    End Sub
    
    Sub Format_Underline
       UnderLineCurrentLine Xor=1
       RERemoveUnderLines(hRichEdit)
       If UnderLineCurrentLine Then REUnderLineCurrentLine(hRichEdit)
    End Sub
    
    Sub Format_LineSpacing(hParent As Dword, ControlID As Long)
       Incr LineSpacing : If LineSpacing > 2 Then LineSpacing = 0
       RESetText_New hParent, ControlID
    End Sub
    
    Sub Format_Paragraph(hParent As Dword, ControlID As Long)
       FormatParagraph Xor=1
       RESetText_New hParent, ControlID
    End Sub
    
    Sub RESetText_New(hParent As Dword, ControlID As Long)
       Local hControl As Dword, temp$, ParaFormt2 As PARAFORMAT2, RtfText As String
    
       hControl = GetDlgItem(hParent,ControlID)
       RETurnOff hControl
    
       'Case
       RtfText = IIf$(CaseType, UCase$(OriginalText$), OriginalText$)
       Control Set Text hParent, ControlID, RtfText
    
       'Paragraph Formatting
       If FormatParagraph Then
          Replace $CrLf + $CrLf    With "::::;;;;::::"  In RtfText  'get rid of paragraph separation
          Replace $CrLf            With $Spc            In RtfText  'merge individual lines separated by a single $crlf
          Replace "::::;;;;::::"   With $CrLf + $CrLf   In RtfText  'restore the paragraph separation
          Control Set Text hParent, ControlID, RtfText
       End If
    
       'Character Spacing
       If WideSpacing Then
          RTFExpandA = Choose$(WideSpacing, "\expndtw360 ", "\expndtw720 ")
          RtfText = "{\rtf1\ansi " + RTFExpandA + RtfText + "}"    'Insert expand instruction.
          Replace $CrLf With "\par " In RtfText
          'Replace "{\rtf1\ansi \expndtw360 {\rtf1\ansi \expndtw360" With "{\rtf1\ansi \expndtw360" In RtfText
          SendMessage hControl, %WM_SetText, 0, StrPtr(RtfText)  'place in RichEdit as RTF text
       End If
    
       'Line Spacing
       If LineSpacing Then
          SendMessage hControl, %EM_SetSel, 0, -1
          ParaFormt2.dwMask           = %PFM_LINESPACING
          ParaFormt2.dyLineSpacing    = Choose(LineSpacing,30,40,50) '20 = one line height, 40 = 2, 10 = ½
          ParaFormt2.bLineSpacingRule = 5  'Five mean that dyLineSpacing is in twentieth, see MSDN
          ParaFormt2.cbSize           = SizeOf(PARAFORMAT2)
          SendMessage(hControl, %EM_SETPARAFORMAT, 0, VarPtr(ParaFormt2))
          SendMessage hControl, %EM_SetSel, -1, 0
       End If
    
       RETurnON hControl
       SendMessage hControl, %EM_SetSel, 0, 0  'could capture the starting postion and restore it here
       Control Set Focus hParent, ControlID
    
    End Sub
    ​
Working...
X