Page 1 of 1

Printing RTF using CreateTextServices()

PostPosted: Fri Feb 04, 2022 7:43 pm
by Antonio Linares
to test it, from FWH\samples do:

buildh32.bat tim

tim.prg
Code: Select all  Expand view
#include "FiveWin.ch"

function Main()

   local oWnd

   DEFINE WINDOW oWnd

   ACTIVATE WINDOW oWnd ;
      ON PAINT PrnSayRTF( hDC )

return nil

#pragma BEGINDUMP

#include <windows.h>
#include <hbapi.h>
#include <Richedit.h>
#include <TextServ.h>
#include <memory>

EXTERN_C const IID IID_ITextHost = {
    0xc5bdd8d0,
    0xd26e,
    0x11ce,
    { 0xa8, 0x9e, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 }
};

EXTERN_C const IID IID_ITextServices = {
    0x8d33f740,
    0xcf58,
    0x11ce,
    { 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 }
};

typedef HRESULT ( _stdcall * PCREATETEXTSERVICES ) ( IUnknown *, ITextHost *, IUnknown ** );

class TextHost : public ITextHost {
public:
    HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override {

        if (ppvObject == nullptr) {
            return E_POINTER;
        }

        if ((riid == IID_IUnknown) || (riid == IID_ITextHost)) {
            *ppvObject = this;
            return S_OK;
        }

        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }

    ULONG __stdcall AddRef(void) override {
        return 0;
    }

    ULONG __stdcall Release(void) override {
        return 0;
    }

    HDC TxGetDC() override {
        return nullptr;
    }

    INT TxReleaseDC(HDC hdc) override {
        return 0;
    }

    BOOL TxShowScrollBar(INT fnBar, BOOL fShow) override {
        return FALSE;
    }

    BOOL TxEnableScrollBar(INT fuSBFlags, INT fuArrowflags) override {
        return FALSE;
    }

    BOOL TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw) override {
        return FALSE;
    }

    BOOL TxSetScrollPos(INT fnBar, INT nPos, BOOL fRedraw) override {
        return FALSE;
    }

    void TxInvalidateRect(LPCRECT prc, BOOL fMode) override {

    }

    void TxViewChange(BOOL fUpdate) override {

    }

    BOOL TxCreateCaret(HBITMAP hbmp, INT xWidth, INT yHeight) override {
        return FALSE;
    }

    BOOL TxShowCaret(BOOL fShow) override {
        return FALSE;
    }

    BOOL TxSetCaretPos(INT x, INT y) override {
        return FALSE;
    }

    BOOL TxSetTimer(UINT idTimer, UINT uTimeout) override {
        return FALSE;
    }

    void TxKillTimer(UINT idTimer) override {

    }

    void TxScrollWindowEx(INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate, UINT fuScroll) override {

    }

    void TxSetCapture(BOOL fCapture) override {

    }

    void TxSetFocus() override {

    }

    void TxSetCursor(HCURSOR hcur, BOOL fText) override {

    }

    BOOL TxScreenToClient(LPPOINT lppt) override {
        return FALSE;
    }

    BOOL TxClientToScreen(LPPOINT lppt) override {
        return FALSE;
    }

    HRESULT TxActivate(LONG * plOldState) override {
        return E_NOTIMPL;
    }

    HRESULT TxDeactivate(LONG lNewState) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetClientRect(LPRECT prc) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetViewInset(LPRECT prc) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetCharFormat(const CHARFORMATW **ppCF) override {

        if (char_format_ == nullptr) {
            char_format_ = std::make_unique<CHARFORMATW>();
            char_format_->cbSize = sizeof(CHARFORMATW);
        }

        *ppCF = char_format_.get();
        return S_OK;
    }

    HRESULT TxGetParaFormat(const PARAFORMAT **ppPF) override {

        if (para_format_ == nullptr) {
            para_format_ = std::make_unique<PARAFORMAT>();    
            para_format_->cbSize = sizeof PARAFORMAT;
        }

        *ppPF = para_format_.get();
        return S_OK;
    }

    COLORREF TxGetSysColor(int nIndex) override {
        return GetSysColor(nIndex);
    }

    HRESULT TxGetBackStyle(TXTBACKSTYLE *pstyle) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetMaxLength(DWORD *plength) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetScrollBars(DWORD *pdwScrollBar) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetPasswordChar(_Out_ TCHAR *pch) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetAcceleratorPos(LONG *pcp) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetExtent(LPSIZEL lpExtent) override {
        return E_NOTIMPL;
    }

    HRESULT OnTxCharFormatChange(const CHARFORMATW * pCF) override {
        return E_NOTIMPL;
    }

    HRESULT OnTxParaFormatChange(const PARAFORMAT * pPF) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetPropertyBits(DWORD dwMask, DWORD *pdwBits) override {
        *pdwBits = 0;
        return S_OK;
    }

    HRESULT TxNotify(DWORD iNotify, void *pv) override {
        return E_NOTIMPL;
    }

    HIMC TxImmGetContext() override {
        return nullptr;
    }

    void TxImmReleaseContext(HIMC himc) override {

    }

    HRESULT TxGetSelectionBarWidth(LONG *lSelBarWidth) override {
        *lSelBarWidth = 0;
        return S_OK;
    }

private:
    std::unique_ptr<CHARFORMATW> char_format_;
    std::unique_ptr<PARAFORMAT> para_format_;
};

HB_FUNC( PRNSAYRTF )
{
   IUnknown * unknown;
   TextHost textHost;
   HMODULE hDLL = LoadLibrary( "riched20.dll" );
   PCREATETEXTSERVICES pCreateTextServices = ( PCREATETEXTSERVICES ) GetProcAddress( hDLL, "CreateTextServices" );
   ITextServices * pTextServices;
   RECT rect;

   rect.top = 0;
   rect.left = 0;
   rect.bottom = 200;
   rect.right  = 200;

   pCreateTextServices( nullptr, &textHost, &unknown );

   unknown->QueryInterface( IID_ITextServices, ( void ** ) &pTextServices );
   pTextServices->TxSetText( L"Yes, its working!" );
   pTextServices->TxDraw( DVASPECT_CONTENT, 0, nullptr, nullptr, ( HDC ) hb_parnl( 1 ),
                          nullptr, ( LPCRECTL ) &rect, nullptr, nullptr, nullptr, 0, 0 );

   FreeLibrary( hDLL );
}

#pragma ENDDUMP

Re: Printing RTF using CreateTextServices()

PostPosted: Sat Feb 05, 2022 8:11 am
by Antonio Linares
Enhanced version:

Code: Select all  Expand view
#include "FiveWin.ch"

function Main()

   local oWnd, cRTF

   TEXT INTO cRTF
{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang2057{\fonttbl{\f0\fswiss\fprq2\fcharset0 Arial Rounded MT Bold;}
{\f1\fnil\fcharset0 ARIAL;}}
{\colortbl ;\red0\green0\blue0;\red255\green0\blue0;\red0\green255\blue64;\red255\green255\blue0;}
{\*\generator Riched20 10.0.22000}\viewkind4\uc1
\pard\cf1\f0\fs28\lang3082 Printing \cf2 RTF\cf1  \i using\i0  \cf3 CreateTextServices\cf4 ()\cf0\f1\fs20\lang2057\par
}
   ENDTEXT

   DEFINE WINDOW oWnd

   ACTIVATE WINDOW oWnd ;
      ON PAINT PrnSayRTF( hDC, cRTF )

return nil

#pragma BEGINDUMP

#include <windows.h>
#include <hbapi.h>
#include <Richedit.h>
#include <TextServ.h>
#include <memory>

EXTERN_C const IID IID_ITextHost = {
    0xc5bdd8d0,
    0xd26e,
    0x11ce,
    { 0xa8, 0x9e, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 }
};

EXTERN_C const IID IID_ITextServices = {
    0x8d33f740,
    0xcf58,
    0x11ce,
    { 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 }
};

typedef HRESULT ( _stdcall * PCREATETEXTSERVICES ) ( IUnknown *, ITextHost *, IUnknown ** );

class TextHost : public ITextHost {
public:
    HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override {

        if (ppvObject == nullptr) {
            return E_POINTER;
        }

        if ((riid == IID_IUnknown) || (riid == IID_ITextHost)) {
            *ppvObject = this;
            return S_OK;
        }

        *ppvObject = nullptr;
        return E_NOINTERFACE;
    }

    ULONG __stdcall AddRef(void) override {
        return 0;
    }

    ULONG __stdcall Release(void) override {
        return 0;
    }

    HDC TxGetDC() override {
        return nullptr;
    }

    INT TxReleaseDC(HDC hdc) override {
        return 0;
    }

    BOOL TxShowScrollBar(INT fnBar, BOOL fShow) override {
        return FALSE;
    }

    BOOL TxEnableScrollBar(INT fuSBFlags, INT fuArrowflags) override {
        return FALSE;
    }

    BOOL TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw) override {
        return FALSE;
    }

    BOOL TxSetScrollPos(INT fnBar, INT nPos, BOOL fRedraw) override {
        return FALSE;
    }

    void TxInvalidateRect(LPCRECT prc, BOOL fMode) override {

    }

    void TxViewChange(BOOL fUpdate) override {

    }

    BOOL TxCreateCaret(HBITMAP hbmp, INT xWidth, INT yHeight) override {
        return FALSE;
    }

    BOOL TxShowCaret(BOOL fShow) override {
        return FALSE;
    }

    BOOL TxSetCaretPos(INT x, INT y) override {
        return FALSE;
    }

    BOOL TxSetTimer(UINT idTimer, UINT uTimeout) override {
        return FALSE;
    }

    void TxKillTimer(UINT idTimer) override {

    }

    void TxScrollWindowEx(INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate, UINT fuScroll) override {

    }

    void TxSetCapture(BOOL fCapture) override {

    }

    void TxSetFocus() override {

    }

    void TxSetCursor(HCURSOR hcur, BOOL fText) override {

    }

    BOOL TxScreenToClient(LPPOINT lppt) override {
        return FALSE;
    }

    BOOL TxClientToScreen(LPPOINT lppt) override {
        return FALSE;
    }

    HRESULT TxActivate(LONG * plOldState) override {
        return E_NOTIMPL;
    }

    HRESULT TxDeactivate(LONG lNewState) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetClientRect(LPRECT prc) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetViewInset(LPRECT prc) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetCharFormat(const CHARFORMATW **ppCF) override {

        if (char_format_ == nullptr) {
            char_format_ = std::make_unique<CHARFORMATW>();
            char_format_->cbSize = sizeof(CHARFORMATW);
        }

        *ppCF = char_format_.get();
        return S_OK;
    }

    HRESULT TxGetParaFormat(const PARAFORMAT **ppPF) override {

        if (para_format_ == nullptr) {
            para_format_ = std::make_unique<PARAFORMAT>();    
            para_format_->cbSize = sizeof PARAFORMAT;
        }

        *ppPF = para_format_.get();
        return S_OK;
    }

    COLORREF TxGetSysColor(int nIndex) override {
        return GetSysColor(nIndex);
    }

    HRESULT TxGetBackStyle(TXTBACKSTYLE *pstyle) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetMaxLength(DWORD *plength) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetScrollBars(DWORD *pdwScrollBar) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetPasswordChar(_Out_ TCHAR *pch) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetAcceleratorPos(LONG *pcp) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetExtent(LPSIZEL lpExtent) override {
        return E_NOTIMPL;
    }

    HRESULT OnTxCharFormatChange(const CHARFORMATW * pCF) override {
        return E_NOTIMPL;
    }

    HRESULT OnTxParaFormatChange(const PARAFORMAT * pPF) override {
        return E_NOTIMPL;
    }

    HRESULT TxGetPropertyBits(DWORD dwMask, DWORD *pdwBits) override {
        *pdwBits = 0;
        return S_OK;
    }

    HRESULT TxNotify(DWORD iNotify, void *pv) override {
        return E_NOTIMPL;
    }

    HIMC TxImmGetContext() override {
        return nullptr;
    }

    void TxImmReleaseContext(HIMC himc) override {

    }

    HRESULT TxGetSelectionBarWidth(LONG *lSelBarWidth) override {
        *lSelBarWidth = 0;
        return S_OK;
    }

private:
    std::unique_ptr<CHARFORMATW> char_format_;
    std::unique_ptr<PARAFORMAT> para_format_;
};

struct COOKIE
{
    bool isUnicode;
    union
    {
        char * ansi;
        WCHAR * unicode;
    };
    size_t cbSize, cbCount;
};

DWORD CALLBACK EditStreamInCallback( DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb )
{
    COOKIE * pCookie = ( COOKIE * ) dwCookie;

    if( pCookie->isUnicode )
   {
        if( ( pCookie->cbSize - pCookie->cbCount ) * sizeof( WCHAR ) < ( size_t ) cb )
            * pcb = LONG( pCookie->cbSize - pCookie->cbCount ) * sizeof( WCHAR );
        else
            * pcb = cb & ~1UL;
        memcpy( pbBuff, pCookie->unicode + pCookie->cbCount, * pcb );
        pCookie->cbCount += *pcb / sizeof( WCHAR );
    }
    else
   {
        if( pCookie->cbSize - pCookie->cbCount < ( DWORD ) cb )
            * pcb = LONG( pCookie->cbSize - pCookie->cbCount );
        else
            * pcb = cb;
        memcpy( pbBuff, pCookie->ansi + pCookie->cbCount, * pcb );
        pCookie->cbCount += * pcb;
    }

    return 0;
}

HB_FUNC( PRNSAYRTF )
{
   IUnknown * unknown;
   TextHost textHost;
   HMODULE hDLL = LoadLibrary( "riched20.dll" );
   PCREATETEXTSERVICES pCreateTextServices = ( PCREATETEXTSERVICES ) GetProcAddress( hDLL, "CreateTextServices" );
   ITextServices * pTextServices;
   RECT rect;
   COOKIE editCookie;
   EDITSTREAM editStream;
   LRESULT lResult = 0;

   rect.top = 0;
   rect.left = 0;
   rect.bottom = 200;
   rect.right  = 200;

   pCreateTextServices( nullptr, &textHost, &unknown );

   unknown->QueryInterface( IID_ITextServices, ( void ** ) &pTextServices );

    editCookie.isUnicode   = false;
    editCookie.ansi        = ( char * ) hb_parc( 2 );
    editCookie.cbSize      = hb_parclen( 2 );
    editCookie.cbCount     = 0;

   editStream.dwCookie    = ( DWORD_PTR ) &editCookie;
   editStream.dwError     = 0;
   editStream.pfnCallback = EditStreamInCallback;

   pTextServices->TxSendMessage( EM_STREAMIN, ( WPARAM ) SF_RTF, ( LPARAM ) &editStream, &lResult );
   pTextServices->TxDraw( DVASPECT_CONTENT, 0, nullptr, nullptr, ( HDC ) hb_parnl( 1 ),
                          nullptr, ( LPCRECTL ) &rect, nullptr, nullptr, nullptr, 0, 0 );

   FreeLibrary( hDLL );
}

#pragma ENDDUMP

Re: Printing RTF using CreateTextServices()

PostPosted: Sun Feb 06, 2022 10:03 am
by Antonio Linares
When we use SF_RTF it does not call the callback and does nothing. GetLastError() returns 2 which means "file not found" (???)
and dwError remains zero.

If we replace SF_RTF with SF_TEXT then it works but it is processed as standard text and not RTF.

I have placed a question in StackOverflow:
https://stackoverflow.com/questions/71005308/ptextservices-txsendmessage-em-streamin-wparam-sf-rtf-lparam-editst

Re: Printing RTF using CreateTextServices()

PostPosted: Thu Feb 10, 2022 11:41 pm
by Antonio Linares
Fixed and properly working thanks to Bruno Cantero (C3) :-)

tim.prg
Code: Select all  Expand view
#include "FiveWin.ch"

function Main()

   local oWnd

   DEFINE WINDOW oWnd

   ACTIVATE WINDOW oWnd ;
      ON PAINT PrnSayRTF( hDC )

return nil

#pragma BEGINDUMP

#include <hbapi.h>
#include <Richedit.h>
#include <textserv.h>

typedef struct
{
   char * szText;
   LONG lSize;
   LONG lCount;
} RTFTEXTINFO;

typedef HRESULT ( _stdcall * PCREATETEXTSERVICES ) ( IUnknown *, ITextHost *, IUnknown ** );

const IID IID_ITextServices = { 0x8d33f740, 0xcf58, 0x11ce, { 0xa8, 0x9d, 0x00, 0xaa, 0x00, 0x6c, 0xad, 0xc5 } };

class TTextHost : public ITextHost
{
   public:
      /* IUnknown */
      STDMETHOD( QueryInterface )( REFIID, PVOID * ppvObject ) { * ppvObject = NULL; return S_FALSE; };
      STDMETHOD_( ULONG, AddRef )( void ) { return 0; };
      STDMETHOD_( ULONG, Release )( void ) { return 0; };

      /* ITextHost */
      HDC TxGetDC( void ) { return NULL; };
      INT TxReleaseDC( HDC ) { return 1; };
      BOOL TxShowScrollBar( INT, BOOL ) { return FALSE; };
      BOOL TxEnableScrollBar( INT, INT ) { return FALSE; };
      BOOL TxSetScrollRange( INT, LONG, INT, BOOL ) { return FALSE; };
      BOOL TxSetScrollPos( INT, INT, BOOL ) { return FALSE; };
      void TxInvalidateRect( LPCRECT, BOOL ) {};
      void TxViewChange( BOOL ) {};
      BOOL TxCreateCaret( HBITMAP, INT, INT ) { return FALSE; };
      BOOL TxShowCaret( BOOL ) { return FALSE; };
      BOOL TxSetCaretPos( INT, INT ) { return FALSE; };
      BOOL TxSetTimer( UINT, UINT ) { return FALSE; };
      void TxKillTimer( UINT ) {};
      void TxScrollWindowEx( INT, INT, LPCRECT, LPCRECT, HRGN, LPRECT, UINT ) {};
      void TxSetCapture( BOOL ) {};
      void TxSetFocus( void ) {};
      void TxSetCursor( HCURSOR, BOOL ) {};
      BOOL TxScreenToClient( LPPOINT ) { return FALSE; };
      BOOL TxClientToScreen( LPPOINT ) { return FALSE; };
      HRESULT TxActivate( LONG * ) { return S_OK; };
      HRESULT TxDeactivate( LONG ) { return S_OK; };
      HRESULT TxGetClientRect( LPRECT prc ) { SetRectEmpty( prc ); return S_OK; };
      HRESULT TxGetViewInset( LPRECT prc ) { SetRectEmpty( prc ); return S_OK; };
      HRESULT TxGetCharFormat( const CHARFORMATW ** ppCF ) { * ppCF = &FCharFormat; return S_OK; };
      HRESULT TxGetParaFormat( const PARAFORMAT ** ppPF ) { * ppPF = &FParaFormat; return S_OK; };
      COLORREF TxGetSysColor( int iIndex ) { return GetSysColor( iIndex ); };
      HRESULT TxGetBackStyle( TXTBACKSTYLE * pstyle ) { * pstyle = TXTBACK_TRANSPARENT; return S_OK; };
      HRESULT TxGetMaxLength( DWORD * plength ) { * plength = INFINITE; return S_OK; };
      HRESULT TxGetScrollBars( DWORD * pdwScrollBar ) { * pdwScrollBar = 0; return S_OK; };
      HRESULT TxGetPasswordChar( _Out_ TCHAR * pch ) { return S_FALSE; };
      HRESULT TxGetAcceleratorPos( LONG * pcp ) { * pcp = -1; return S_OK; };
      HRESULT TxGetExtent( LPSIZEL ) { return E_NOTIMPL; };
      HRESULT OnTxCharFormatChange( const CHARFORMATW * pCF ) { memcpy( &FCharFormat, ( void * ) pCF, pCF->cbSize ); return S_OK; };
      HRESULT OnTxParaFormatChange( const PARAFORMAT * pPF ) { memcpy( &FParaFormat, ( void * ) pPF, pPF->cbSize ); return S_OK; };
      HRESULT TxGetPropertyBits( DWORD, DWORD * pdwBits ) { * pdwBits = TXTBIT_RICHTEXT | TXTBIT_MULTILINE | TXTBIT_WORDWRAP | TXTBIT_USECURRENTBKG; return S_OK; };
      HRESULT TxNotify( DWORD, void * ) { return S_OK; };
      HIMC TxImmGetContext( void ) { return NULL; };
      void TxImmReleaseContext( HIMC ) {};
      HRESULT TxGetSelectionBarWidth( LONG * lSelBarWidth ) { * lSelBarWidth = 100; return S_OK; };

      CHARFORMATW FCharFormat;
      PARAFORMAT  FParaFormat;
};

static DWORD CALLBACK EditStreamCallback( DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG * pcb )
{
   RTFTEXTINFO * pRtfTextInfo;

   pRtfTextInfo = ( RTFTEXTINFO * ) dwCookie;

   if( pRtfTextInfo->lSize - pRtfTextInfo->lCount < cb )
      * pcb = pRtfTextInfo->lSize - pRtfTextInfo->lCount;
   else
      * pcb = cb;

   memcpy( pbBuff, pRtfTextInfo->szText, * pcb );
   pRtfTextInfo->lCount += * pcb;

   return 0;
}

HB_FUNC( PRNSAYRTF )
{
   LRESULT lResult;
   HDC hDC = ( HDC ) hb_parnl( 1 );
   HMODULE hDLL;
   RECT stRect;
   EDITSTREAM stEditStream;
   PCREATETEXTSERVICES pCreateTextServices;
   RTFTEXTINFO sRtfTextInfo;
   IUnknown * pUnknown;
   ITextServices * pTextServices = NULL;
   TTextHost pTextHost;

   stRect = { 10, 10, 200, 200 };
   hDLL = LoadLibrary( "Riched20.dll" );

   pCreateTextServices = ( PCREATETEXTSERVICES ) GetProcAddress( hDLL, "CreateTextServices" );

   pCreateTextServices( NULL, &pTextHost, &pUnknown );
   pUnknown->QueryInterface( IID_ITextServices, ( void ** ) &pTextServices );
   pUnknown->Release();

   if( pTextServices != NULL )
   {
      sRtfTextInfo.szText = "{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1033{\\fonttbl{\\f0\\fswiss\\fprq2\\fcharset0 Tahoma;}{\\f1\\fswiss\\fcharset0 Arial;}}{\\colortbl ;\\red128\\green0\\blue0;\\red0\\green0\\blue128;\\red0\\green128\\blue0;}\\viewkind4\\uc1\\pard\\f0\\fs20 H\\fs24 E\\b L\\ul\\fs20 L\\i O\\ulnone\\b0\\i0   \\cf1 W\\b\\fs22 O\\cf2\\ul\\b0 R\\i\\fs28 L\\cf3\\ulnone\\b\\i0\\fs20 D\\cf0\\b0\\f1\\par}";
      sRtfTextInfo.lSize = lstrlen( sRtfTextInfo.szText );
      sRtfTextInfo.lCount = 0;
      stEditStream.dwCookie = ( DWORD_PTR ) &sRtfTextInfo;
      stEditStream.pfnCallback = EditStreamCallback;

      if( pTextServices->TxSendMessage( EM_STREAMIN, SF_RTF, ( LPARAM ) &stEditStream, &lResult ) == S_OK )
         pTextServices->TxDraw( DVASPECT_CONTENT, 0, NULL, NULL, hDC, NULL, ( RECTL * ) &stRect, NULL, NULL, NULL, 0, TXTVIEW_INACTIVE );

      pTextServices->Release();
   }

   FreeLibrary( hDLL );
}

#pragma ENDDUMP


Image

Re: Printing RTF using CreateTextServices()

PostPosted: Mon Feb 14, 2022 6:10 pm
by TimStone
How do we translate this to an actual printout. Going back to the original question, when using the Printer class to output a document, such as an invoice, most areas are not RTF. However, I need to include a section as part of the report that does use the RTF format. How can we use this solution to accomplish that in a printed document?

Re: Printing RTF using CreateTextServices()

PostPosted: Mon Feb 14, 2022 7:07 pm
by Antonio Linares
Dear Tim,

Now that we got it properly working we are implementing it in FWH.

Its coming, this time, for sure

Re: Printing RTF using CreateTextServices()

PostPosted: Mon Feb 14, 2022 7:39 pm
by TimStone
Thank you.