Search code examples
pythonvb6wxpythonrtf

Use VB 6 RichText control with wxPython


I have created a Rich Text Editor (richtext.RichTextCtrl) using wxPython 2.8.12.1 and Python 2.7. By using PyRTFParser, I achieved handling some RTF content and images. It also supports copy paste of RTF and images.

The issue is all the client databases contain RTF data stored using VB 6 RichText control. When I load these data into my RichTextCtrl, it does not support tables, looses some formatting and bullets, and shows errors for images (Windows Meta File).

I have to provide the facility that can show old data from databases (stored using VB 6 RichText control) into wxPython.

wx.TextCtrl provides TE_RICH and TE_RICH2 facilities but does not provide a method to retrieve RTF content. It does not support images too.

Consider following:

This is the word document from which I am copying content. Word Document to Copy content from

This is the paste result in VB 6 RichText control. Content pasted in VB 6 RichText control

This is the paste result in wx.TextCtrl with TE_RICH2. Provides better tables but no images. Content pasted in wx.TextCtrl

This is the paste result in richtext.RichTextCtrl. Table data is messed and formatting lost. Content pasted in richtext.RichTextCtrl

Is there any solution to support images in wx.TextCtrl as well as get RTF content form that? Or is there any way I can directly use VB 6 RichText control in wxpython?

RTF content example (stored in database):

{\rtf1\fbidis\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 Calibri;}{\f1\froman\fprq2\fcharset0 Times New Roman;}{\f2\froman\fprq2\fcharset2 Symbol;}{\f3\froman\fprq2\fcharset0 Cambria;}{\f4\fnil\fcharset0 MS Sans Serif;}}
{\colortbl ;\red0\green0\blue0;\red151\green72\blue7;\red54\green95\blue145;}
{\stylesheet{ Normal;}{\s1 heading 1;}}
\viewkind4\uc1\trowd\trgaph108\trleft-15\clbrdrt\brdrw15\brdrs\clbrdrl\brdrw15\brdrs\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3005\pard\intbl\ltrpar\sl276\slmult1\cf1\b\f0\fs24 Categor Limits\cell\cf0\b0\f1\fs20\row
\trowd\trgaph108\trleft-15\clbrdrl\brdrw15\brdrs\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1335\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3005\pard\intbl\ltrpar\sl276\slmult1\cf2\b\f0\fs22 Lower Limit\cell Sales Category\cell\cf0\b0\f1\fs20\row
\cf1\f0\fs22\trowd\trgaph108\trleft-15\clbrdrl\brdrw15\brdrs\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1335\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3005\intbl 0\cell Poor\cell\cf0\f1\fs20\row
\cf1\f0\fs22\trowd\trgaph108\trleft-15\clbrdrl\brdrw15\brdrs\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1335\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3005\intbl 1000\cell Average\cell\cf0\f1\fs20\row
\cf1\f0\fs22\trowd\trgaph108\trleft-15\clbrdrl\brdrw15\brdrs\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1335\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3005\intbl 5000\cell Good\cell\cf0\f1\fs20\row
\cf1\f0\fs22\trowd\trgaph108\trleft-15\clbrdrl\brdrw15\brdrs\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx1335\clbrdrb\brdrw15\brdrs\clbrdrr\brdrw15\brdrs \cellx3005\intbl 7000\cell Excellent\cell\cf0\f1\fs20\row
\pard\ltrpar\sa200\sl276\slmult1\f0\fs22 
\par \pard\ltrpar\fi-360\li720\sa200\sl276\slmult1\f2\'b7\tab\f0 Item 1
\par \f2\'b7\tab\f0 Item 2
\par \pard\ltrpar\keep\keepn\s1\sb480\sl276\slmult1\cf3\b\f3\fs28 Colorful Text here\'85
\par \pard\ltrpar\cf0\b0\f4\fs17 
\par }

Solution

  • VB6 is an ANSI RTF. ie NO UNICODE. It's also very old and many newer versions have been released.

    This is how to access a newer version. It creates a RTF window, send a message to get a COM interface, then you use it via TOM (thetext object model).

        Ret = LoadLibrary("c:\windows\system32\MSFTEDIT.dll")
        If Ret = 0 Then MsgBox "Load Lib " & Err.LastDllError
        Flags = WS_CHILD + WS_HSCROLL + WS_VSCROLL + WS_VISIBLE + ES_MULTILINE + ES_AUTOHSCROLL + ES_AUTOVSCROLL + ES_NOHIDESEL + ES_WANTRETURN
        Dim barray() As Byte
        barray = "RICHEDIT50W" & vbNullChar
        gRtfHwnd = CreateWindowEx(WS_EX_ACCEPTFILES + WS_EX_CLIENTEDGE, barray(0), "", Flags, 0, 0, ScaleX(Me.ScaleWidth, vbTwips, vbPixels), ScaleY(Me.ScaleHeight, vbTwips, vbPixels), Me.hWnd, vbNull, App.hInstance, vbNull)
    
        Ret = SendMessageByVal(gRtfHwnd, EM_SETTEXTMODE, TM_MULTILEVELUNDO + TM_PLAINTEXT + TM_MULTICODEPAGE, 0)
        If GetTextMode(gRtfHwnd) <> 41 Then MsgBox "get Text mode = " & GetTextMode(gRtfHwnd)
        Ret = SendMessageByVal(gRtfHwnd, EM_SETEDITSTYLE, SES_ALLOWBEEPS + SES_USECRLF, SES_ALLOWBEEPS + SES_USECRLF)
        Ret = SendMessageByVal(gRtfHwnd, EM_SETLANGOPTIONS, IMF_None, IMF_None)
        If GetTextMode(gRtfHwnd) <> 41 Then MsgBox "get Text mode (2) = " & GetTextMode(gRtfHwnd)
        Ret = SendMessageByVal(gRtfHwnd, EM_SETTYPOGRAPHYOPTIONS, TO_None, TO_None)
        'Below is the default anyway with CreateWin flags spec above
        Ret = SendMessageByVal(gRtfHwnd, EM_SETOPTIONS, ECO_AUTOHSCROLL + ECO_AUTOVSCROLL + ECO_NOHIDESEL + ECO_WANTRETURN, ECOOP_OR)
    
    
    Dim ParaFormat As ITextPara
    Dim FontFormat As ITextFont
    Ret = SendMessageAny(gRtfHwnd, EM_GETOLEINTERFACE, 0, TomObj)
    Set TomDoc = TomObj