感谢我的朋友 Bruno Cantero 先生 (C3),修复并正常工作
#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 ) { _bcopy( FCharFormat, ( void * ) pCF, pCF->cbSize ); return S_OK; };
HRESULT OnTxParaFormatChange( const PARAFORMAT * pPF ) { _bcopy( 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;
}
extern "C" void SayRTF( void )
{
LRESULT lResult;
HDC hDC;
HFONT hFont;
HMODULE hDLL;
RECT stRect;
LOGFONT stLogFont;
EDITSTREAM stEditStream;
PCREATETEXTSERVICES pCreateTextServices;
CHARFORMATW stCharFormat;
PARAFORMAT stParaFormat;
RTFTEXTINFO sRtfTextInfo;
IUnknown * pUnknown;
ITextServices * pTextServices;
TTextHost * pTextHost;
/* HDC donde dibujar. */
hDC = ( HDC ) hb_parnl( 1 ); // the hDC where you want to show the RTF
// Comentamos para probar la transperencia Rectangle( hDC, 9, 9, 202, 202 );
stRect = { 10, 10, 200, 200 };
hDLL = LoadLibrary( "Riched20.dll" );
if( hDLL == NULL )
return;
pCreateTextServices = ( PCREATETEXTSERVICES ) GetProcAddress( hDLL, "CreateTextServices" );
if( pCreateTextServices == NULL )
{
FreeLibrary( hDLL );
return;
}
/* Obtenemos las características de la fuente del HDC. */
hFont = ( HFONT ) SelectObject( hDC, GetStockObject( SYSTEM_FONT ) );
GetObject( hFont, sizeof( LOGFONT ), &stLogFont );
SelectObject( hDC, hFont );
/* Creamos el formato de la fuente por defecto. */
memset( &stCharFormat, 0, sizeof( CHARFORMATW ) );
stCharFormat.cbSize = sizeof( CHARFORMATW );
stCharFormat.dwEffects = CFM_EFFECTS | CFE_AUTOBACKCOLOR;
stCharFormat.dwEffects &= ~( CFE_PROTECTED | CFE_LINK | CFE_AUTOCOLOR );
if( stLogFont.lfWeight < FW_BOLD )
stCharFormat.dwEffects &= ~CFE_BOLD;
if( !stLogFont.lfItalic )
stCharFormat.dwEffects &= ~CFE_ITALIC;
if( !stLogFont.lfUnderline )
stCharFormat.dwEffects &= ~CFE_UNDERLINE;
if( !stLogFont.lfStrikeOut )
stCharFormat.dwEffects &= ~CFE_STRIKEOUT;
stCharFormat.dwMask = CFM_ALL | CFM_BACKCOLOR | CFM_STYLE;
stCharFormat.bCharSet = stLogFont.lfCharSet;
stCharFormat.bPitchAndFamily = stLogFont.lfPitchAndFamily;
stCharFormat.yHeight = -stLogFont.lfHeight * 1440 / GetDeviceCaps( hDC, LOGPIXELSY );
MultiByteToWideChar( CP_ACP, 0, stLogFont.lfFaceName, LF_FACESIZE, stCharFormat.szFaceName, LF_FACESIZE );
/* Creamos el formato de párrafo por defecto. */
memset( &stParaFormat, 0, sizeof( PARAFORMAT ) );
stParaFormat.cbSize = sizeof( PARAFORMAT );
stParaFormat.dwMask = PFM_ALL;
stParaFormat.wAlignment = PFA_LEFT;
stParaFormat.cTabCount = 1;
stParaFormat.rgxTabs[ 0 ] = lDefaultTab;
/* Instanciamos nuestro objeto host. */
pTextHost = new TTextHost;
pTextHost->FCharFormat = &stCharFormat;
pTextHost->FParaFormat = &stParaFormat;
/* Creamos el objeto IUnknown y lo asociamos a nuestro objeto TTextHost. */
if( pCreateTextServices( NULL, pTextHost, &pUnknown ) != S_OK )
{
delete pTextHost;
FreeLibrary( hDLL );
return;
}
/* Obtenemos el interface ITextServices. */
pTextServices = NULL;
pUnknown->QueryInterface( IID_ITextServices, ( void ** ) &pTextServices );
/* Liberamos el objeto IUnknown. */
pUnknown->Release();
if( pTextServices != NULL )
{
// sRtfTextInfo.szText = "Plaint Text";
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_TEXT, ( LPARAM ) &stEditStream, &lResult ) == S_OK )
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 );
/* Liberamos el objeto ITextServices. */
pTextServices->Release();
}
delete pTextHost;
FreeLibrary( hDLL );
}