No announcement yet.

Character Spacing (Not Kerning)

  • Filter
  • Time
  • Show
Clear All
new posts

  • #41
    Code, friends and party! Life is good!


    • #42
      Yes, Pierre, life is good, but there is no way that it was 9 Dec when I last participated in this thread. All I can say is that life has too many distractions. This holiday, I think my wife had grandkids over just about every day (up to 4 kids at a time, playroom is where my office is) or we had some evening event to go to or I had my usual tennis break. Productivity of late has been nothing like what I was hoping for!

      At any rate, I'm back here looking/salivating at your RichEdit expansion code. I'm sure I'll be back with a few questions!


      • #43
        So, Pierre,
        Does replacing $CRLF with "\par" mean that the RichEdit will not longer contain $LF anywhere? I have other code that works on the RichEdit content under the assumption that $LF is still the line break character.

        For my needs, I'll want the entire RichEdit content to be toggled between wide and not wide. To do that, I deleted the %SFF_Selection from the EM_StreamIN and EM_StreamOUT messages. Seems to work.

        I'm assuming that I can load the expansion RTF strings when a RichEdit is empty, so that anything the user types in will be wide.

        If I do put the expansion RTF code around a selection, then select it and place the unexpand code around that, should I not first remove the previously entered expansion code? It seems like I'll have unnecessary RTF in the control otherwise.

        I don't think I understand CopyMemory well enough to know why it's the choice for allocating a buffer.

        I'll go play with the code to find the answers myself, but having looked at it for just a little while now, those were my first questions that come to mind.

        However, based on my questions, if you think I've mis-understood how your code works, please let me know.


        • #44
          Looking more closely at your code, it seems that you never extract the RTF code from the RichEdit, rather you just extract the normal text, then wrap it in the expansion RTF code before putting it back in the RichEdit. Is that right?

          If that's the case, why is the simpler Control Get Text hDlg, %IDC_RichEdit to sRtfText statement not appropriate to replace the reRichEditToString/reRichEdittoStringCalllback functions? I've not used EM_StreamOut before so perhaps I'm missing something? Any reason to use EM_StreamOut?

          When I make that replacement, the code seems to perform as expected.

          I will note that if I wanted to operate on the selection, rather than the entire text, that the EM_StreamOut becomes more useful. Although, even then there are non-EM_StreamOut was to get the selected text.

          However, the same is not true for inserting the expansion code + Text back into the RichEdit. The Control Set Text statement simply pastes in the expansion code as text and the RichEdit does not use it to format the text. So for returning the text, EM_StreamIN seems necessary.

          Thanks again for your work on this. I'm having fun dissecting/understanding it!


          • #45
            And, Pierre,
            Is there no other way to insert RTF code into a RichEdit control, than using EM_StreamIn. It seems like a long way to go about it, when normal text can be entered easily with an EM_SetText message.

            Is there a philosophy about using StreamIN and StreamOUT that makes them a better approach?

            ... added ... I looked around and found this that describes an alternate approach, but have not tried it out yet.


            • #46
              If I remove the line that has EM_SetTypoGraphyOptions, the wide letter spacing still happens - will come on and go off on demand. Is it a Win7-only necessity?

              I removed the two lines of code that replace $CRLF with \par and the example will go wide, but when I reverse it, the end of line characters disappear. I'm not sure how that works.

              I thought you could mix and match RTF and non-RTF code through StreamIN, but apparently not?

              The slightly more minimal code that works for me ... do you know of reasons why not to do this?

              'Compilable Example:
              #Compiler PBWin 10
              #Compile Exe
              #Dim All
              #Include ""
              Global hDlg As Dword, hRichEdit As Dword
              %IDC_RichEdit = 500
              %IDC_On       = 501
              %IDC_Off      = 502
              Function PBMain() As Long
                 Local style&, buf$
                 buf$ =  "This is sample" + $CrLf + "text for the" + $CrLf + "edit control."
                 style& = %WS_Child Or %WS_ClipSiblings Or %WS_Visible Or %WS_HScroll Or %WS_VScroll Or %ES_MultiLine Or _
                          %ES_AutoHScroll Or %ES_AutoVScroll Or %ES_NoHideSel Or %ES_SAVESEL Or %ES_WantReturn
                 Dialog Default Font "Tahoma", 12, 1
                 Dialog New Pixels, 0, "Test Code",300,300,400,300, %WS_OverlappedWindow To hDlg
                 Control Add Button, hDlg, %IDC_On,"On", 30,10,60,25
                 Control Add Button, hDlg, %IDC_Off,"Off", 120,10,60,25
                 LoadLibrary("msftedit.dll") : InitCommonControls
                 Control Add "RichEdit50W", hDlg, %IDC_RichEdit, buf$,20,40,360,240, style&, %WS_Ex_ClientEdge
                 Control Handle hDlg, %IDC_RichEdit To hRichEdit
                 SendMessage(hRichEdit, %EM_SETTARGETDEVICE, 0, 0) 'Enable wordwrap
                 Dialog Show Modal hDlg Call DlgProc
              End Function
              CallBack Function DlgProc() As Long
                  Local ParaFormt2 As PARAFORMAT2, sRtfText As String
                  Select Case Cb.Msg
                     Case %WM_InitDialog
                     Case %WM_Command
                        Select Case Cb.Ctl
                           Case %IDC_On
                              Control Get Text hDlg, %IDC_RichEdit To sRtfText
                              Replace $CrLf With "\par " In sRtfText
                              sRtfText = "{\rtf1\expndtw360\expnd72 " & sRtfText & "\expnd0\expndtw0}" 'Insert expand instruction.
                              reRichEditFromStringReplace(hRichEdit, sRtfText) 'Send rtf String to a RichEdit control.
                           Case %IDC_Off
                              Control Get Text hDlg, %IDC_RichEdit To sRtfText
                              Replace $CrLf With "\par " In sRtfText
                              sRtfText = "{\rtf1 \expndtw0\expnd0 " & sRtfText & "\expnd0\expndtw0}"  'Insert unExpand instruction with zero value.
                              reRichEditFromStringReplace(hRichEdit, sRtfText) 'Send rtf String to a RichEdit control.
                        End Select
                  End Select
              End Function
              Function reRichEditFromStringCallBack(ByVal pDwordArray As Dword Pointer, ByVal pRichEditBuffer As Dword, ByVal cb As Long, ByRef pcb As Long) As Long
                 pcb = Min(@pDwordArray[1], cb)
                 If pcb > 0 Then
                    CopyMemory(pRichEditBuffer, @pDwordArray[0], pcb)
                    @pDwordArray[0] = @pDwordArray[0] + pcb
                    @pDwordArray[1] = @pDwordArray[1] - pcb
                 End If
              End Function
              Function reRichEditFromStringReplace(ByVal hRichEdit As Dword, ByVal sRtfText As String) As Long   'Send rtf String to a RichEdit
                 Local EditStreamInfo As EDITSTREAM
                 Dim dwArray(0 To 1)  As Dword
                 dwArray(0)                 = StrPtr(sRtfText)
                 dwArray(1)                 = Len(sRtfText)
                 EditStreamInfo.dwCookie    = VarPtr(dwArray(0))
                 EditStreamInfo.pfnCallback = CodePtr(reRichEditFromStringCallBack)
                 Function = SendMessage(hRichEdit, %EM_STREAMIN, %SF_RTF Or %SFF_PLAINRTF, VarPtr(EditStreamInfo))
                 If EditStreamInfo.dwError Then WinBeep(1500, 100) : WinBeep(1500, 100)
              End Function


              • #47
                Yep, removing SFF_Selection from EM_StreamIN and EM_StreamOUT mean to work on all content.

                EM_SetTypoGraphyOptions is needed for MsftEdit.DLL RichEdit50W 4.1 under Window 7, not for Windows 10 MsftEdit.DLL RichEdit50W version 7.5.

                Under text mode, CRLF is CRLF, under RTF mode, CRLF have visual effect on internal RTF text, but not on the resulting text, "\par " does.

                You may mix RTF code, normal text and RichEdit functions API's, as long as you got a good idea of what you do.
                For example, "Control Get Text hDlg, %IDC_RichEdit To sRtfText" is OK but you will loose, let's say, bolded text if any, coder's choice.

                CopyMemory is pretty simple, it copy some bytes from a Source to a Dest. CopyMemory(STRPTR(Dest), STRPTR(Source), ByteCount)

                Other way to insert RTF code into a RichEdit control: Using Rich Edit Controls


                • #48
                  Thanks for the comments. You response answers another question I had, regarding the use of the expnd72 RTF code, but raises another.

                  To remove wide character spacing, I could simply do this, without dealing with RTF content.

                  Control Get Text hDlg, %IDC_RichEdit To PlainText
                  Control Set Text hDlg, %IDC_RichEdit, PlainText
                  But, as you note, that would lose any formatting that was present. To keep the formatting I would need to use STREAMOUT to get the RTF content of the RichEdit.

                  In that case, however, I assume I would need to find and remove the RTF code that causes the wide character spacing, UNLESS it's the case that applying an outer layer of RTF code overrides any inner RTF code, such that embedded expansion codes like this ...

                  <unexpand><expand> ... content .. </expand> </unexpand>

                  would result in unexpanded text.

                  I'll have to experiment with that to confirm.