none
Why the Windowless RichEditControl function TxMessage in ITextService return a value 0x8004000D? RRS feed

  • 问题

  • Hi, Everyone,

    I am making use of the windowless RichEdit Control in VS2008, and my problem is, 

    Before I  call TxSendMessage function in ITextServices,  I've filled a FORMATRANGE struct with the memory device's settings (hdc and hdcTarget is the same DC which is the memory DC, rect and rectPage are the coordinates of my position in TWIPS). When I'm trying to calculate the text index for the pages to my DC by using the following call: 

    HRESULT hr = m_spTextServices->TxSendMessage(EM_FORMATRANGE, (WPARAM)FALSE, (LPARAM)&fr, &lResult); 

    it always returns OLE_E_INVALIDATE (0x8004000D). 

    Is there any way to solve this problem? Thanks!


    • 已编辑 ChenTerry 2016年12月3日 16:23 Not clear
    2016年12月3日 16:20

全部回复

  • Hi ChenTerry,

    感谢在MSDN论坛发帖。

    实际上error code 0x8004000D 指的是无效的矩形。请检查你的rect,rectPage 参数是否正确有效。或者上传更详细的上下文代码,方便我们查找准确的原因。详细内容参考以下文档。

    https://msdn.microsoft.com/en-us/library/windows/desktop/dd542643(v=vs.85).aspx

    该论坛为中文论坛,如需发帖请使用中文。

    谢谢你的支持与合作。

    -----

    Actually the Error Code 0x8004000D means Invalid rectangle, please check if your rect, rectPage variables are correct. Or you could provide more detail codes about this, so that we could find the root cause of this problem. For more information please refer to this document below.

    https://msdn.microsoft.com/en-us/library/windows/desktop/dd542643(v=vs.85).aspx

    If your Mother tongue is English, please post to Visual C++ English forum.

    Your understanding and cooperation will be grateful.

    Best Regards,
    Sera Yu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2016年12月5日 7:47
  • 本意是想用 windowless RichEdit 控件实现RTF文档的分页功能, 我的代码如下:


    //
    // RichTextFormatDrawer.h
    //
    #ifndef __RICH_TEXT_FORMAT_DRAWER_H__
    #define __RICH_TEXT_FORMAT_DRAWER_H__
    #include <richedit.h>
    #include <imm.h> 
    #pragma comment(lib, "imm32.lib")
    
    #include <Unknwn.h>
    #include <TextServ.h>
    #pragma comment(lib, "Riched20.lib")
    
    #ifndef LY_PER_INCH
    #define LY_PER_INCH   1440
    #define HOST_BORDER 0
    #endif
    
    typedef struct _RTF_DATA 
    {
        CStringA data;
        int length;
        int pos;
    } RTF_DATA;
    
    class CRichTextFormatDrawer : public ITextHost
    {
    public:
        CRichTextFormatDrawer();
        ~CRichTextFormatDrawer();
    
        // common COM interface
        HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject);
        ULONG STDMETHODCALLTYPE AddRef(void);
        ULONG STDMETHODCALLTYPE Release(void);
    
        // ITextHost
        HDC TxGetDC();
        INT TxReleaseDC(HDC hdc);
        BOOL TxShowScrollBar(INT fnBar, BOOL fShow);
        BOOL TxEnableScrollBar(INT fuSBFlags, INT fuArrowflags);
        BOOL TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw);
        BOOL TxSetScrollPos(INT fnBar, INT nPos, BOOL fRedraw);
        void TxInvalidateRect(LPCRECT prc, BOOL fMode);
        void TxViewChange(BOOL fUpdate);
        BOOL TxCreateCaret(HBITMAP hbmp, INT xWidth, INT yHeight);
        BOOL TxShowCaret(BOOL fShow);
        BOOL TxSetCaretPos(INT x, INT y);
        BOOL TxSetTimer(UINT idTimer, UINT uTimeout);
        void TxKillTimer(UINT idTimer);
        void TxScrollWindowEx(INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate, UINT fuScroll);
        void TxSetCapture(BOOL fCapture);
        void TxSetFocus();
        void TxSetCursor(HCURSOR hcur, BOOL fText);
        BOOL TxScreenToClient(LPPOINT lppt);
        BOOL TxClientToScreen(LPPOINT lppt);
        HRESULT	TxActivate(LONG * plOldState);
        HRESULT	TxDeactivate(LONG lNewState);
        HRESULT	TxGetClientRect(LPRECT prc);
        HRESULT	TxGetViewInset(LPRECT prc);
        HRESULT TxGetCharFormat(const CHARFORMATW **ppCF);
        HRESULT	TxGetParaFormat(const PARAFORMAT **ppPF);
        COLORREF TxGetSysColor(int nIndex);
        HRESULT	TxGetBackStyle(TXTBACKSTYLE *pstyle);
        HRESULT	TxGetMaxLength(DWORD *plength);
        HRESULT	TxGetScrollBars(DWORD *pdwScrollBar);
        HRESULT	TxGetPasswordChar(TCHAR *pch);
        HRESULT	TxGetAcceleratorPos(LONG *pcp);
        HRESULT	TxGetExtent(LPSIZEL lpExtent);
        HRESULT OnTxCharFormatChange(const CHARFORMATW * pcf);
        HRESULT	OnTxParaFormatChange(const PARAFORMAT * ppf);
        HRESULT	TxGetPropertyBits(DWORD dwMask, DWORD *pdwBits);
        HRESULT	TxNotify(DWORD iNotify, void *pv);
        HIMC TxImmGetContext();
        void TxImmReleaseContext(HIMC himc);
        HRESULT	TxGetSelectionBarWidth(LONG *lSelBarWidth);
    
        // custom function
        HRESULT SetRtfString(CStringA &rtfStr);
        HRESULT GetRtfString(CStringA &rtfStr);
    
        static DWORD CALLBACK RtfStrSetCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
        static DWORD CALLBACK RtfStrGetCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb);
        HRESULT Draw(HDC hDc, CRect &rcBox);
        HRESULT Draw2(HDC hDc, CRect &rcBox);
        HRESULT CalNaturalSize(HDC hDC, LONG &width, LONG &height);
        HRESULT CalNaturalSize2(HDC hDC, LONG &width, LONG &height);
    
        HRESULT CharFormatFromHFONT(CHARFORMAT2* pCF, HFONT hFont);
        HRESULT InitDefaultParaFormat();
        HRESULT DeleteTheLastChar();
    	HRESULT DeleteRangeChars(int start, int end);
    
        HRESULT GetTextLengthEx(int &lengh);
        HRESULT GetExTextSel(int &min, int &max);
        HRESULT SetExTextSel(int min, int max);
        HRESULT ReplaceSel(CString csa);
    
        HRESULT TxSendMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT *pLresult);
    
    private:
        HMODULE m_hModule;
        IUnknown *m_pUnknow;
        ITextServices *m_pTextServices;
    
        RECT			m_rcClient;			// Client Rect
        RECT			m_rcViewInset;		// view rect inset
        SIZEL			m_sizelExtent;		// Extent array
    
        int				nPixelsPerInchX;    // Pixels per logical inch along width
        int				nPixelsPerInchY;    // Pixels per logical inch along height
    
        DWORD m_dwPropertyBits;
        CHARFORMAT2 m_charFormat;
        PARAFORMAT2 m_paraFormat;
    };
    
    #endif
    


    //
    // RichTextFormatDrawer.cpp
    //
    #include "stdafx.h"
    #include "RichTextFormatDrawer.h"
    
    CRichTextFormatDrawer::CRichTextFormatDrawer()
    {
        HRESULT hr;
        IID *pIID;
        HDC hdcScreen;
    
        hdcScreen = GetDC(NULL);
        nPixelsPerInchX = GetDeviceCaps(hdcScreen, LOGPIXELSX);
        nPixelsPerInchY = GetDeviceCaps(hdcScreen, LOGPIXELSY);
        ReleaseDC(NULL, hdcScreen);
    
        SetRectEmpty(&m_rcClient);
        SetRectEmpty(&m_rcViewInset);
        CharFormatFromHFONT(&m_charFormat, NULL);
    
        m_dwPropertyBits = TXTBIT_RICHTEXT | TXTBIT_MULTILINE | TXTBIT_WORDWRAP | TXTBIT_USECURRENTBKG;
    
        m_hModule = LoadLibrary(TEXT("Msftedit.dll"));
        hr = CreateTextServices(NULL, this, &m_pUnknow);
        if (FAILED(hr))
        {
            hr = NULL;
        }
    
        pIID = (IID *)(VOID *)GetProcAddress(m_hModule, "IID_ITextServices");
        hr = m_pUnknow->QueryInterface(*pIID, (void **)&m_pTextServices);
    }
    
    HRESULT CRichTextFormatDrawer::CharFormatFromHFONT(CHARFORMAT2 *pCF, HFONT hFont)
    // Takes an HFONT and fills in a CHARFORMAT2W structure with the corresponding info
    {
    
        HWND hWnd;
        LOGFONT lf;
        HDC hDC;
        LONG yPixPerInch;
    
        // Get LOGFONT for default font
        if (!hFont)
            hFont = (HFONT) GetStockObject(SYSTEM_FONT);
    
        // Get LOGFONT for passed hfont
        if (!GetObject(hFont, sizeof(LOGFONT), &lf))
            return E_FAIL;
    
        // Set CHARFORMAT structure
        memset(pCF, 0, sizeof(CHARFORMAT2W));
        pCF->cbSize = sizeof(CHARFORMAT2W);
    
        hWnd = GetDesktopWindow();
        hDC = GetDC(hWnd);
        yPixPerInch = GetDeviceCaps(hDC, LOGPIXELSY);
        pCF->yHeight = -lf.lfHeight * LY_PER_INCH / yPixPerInch;
        ReleaseDC(hWnd, hDC);
    
        pCF->yOffset = 0;
        pCF->crTextColor = 0;
    
        pCF->dwEffects = CFM_EFFECTS | CFE_AUTOBACKCOLOR;
        pCF->dwEffects &= ~(CFE_PROTECTED | CFE_LINK | CFE_AUTOCOLOR);
    
        if(lf.lfWeight < FW_BOLD)
            pCF->dwEffects &= ~CFE_BOLD;
    
        if(!lf.lfItalic)
            pCF->dwEffects &= ~CFE_ITALIC;
    
        if(!lf.lfUnderline)
            pCF->dwEffects &= ~CFE_UNDERLINE;
    
        if(!lf.lfStrikeOut)
            pCF->dwEffects &= ~CFE_STRIKEOUT;
    
        pCF->dwMask = CFM_ALL | CFM_BACKCOLOR | CFM_STYLE;
        pCF->bCharSet = lf.lfCharSet;
        pCF->bPitchAndFamily = lf.lfPitchAndFamily;
    
    #ifdef UNICODE
        _tcscpy(pCF->szFaceName, lf.lfFaceName);
    #else
        MultiByteToWideChar(CP_ACP, 0, lf.lfFaceName, LF_FACESIZE, pCF->szFaceName, LF_FACESIZE);
    #endif
    
        return S_OK;
    }
    
    HRESULT CRichTextFormatDrawer::InitDefaultParaFormat()
    {
        memset(&m_paraFormat, 0, sizeof(PARAFORMAT2));
        m_paraFormat.cbSize = sizeof(PARAFORMAT2);
        m_paraFormat.dwMask = PFM_ALL;
        m_paraFormat.wAlignment = PFA_LEFT;
        m_paraFormat.cTabCount = 1;
        m_paraFormat.rgxTabs[0] = lDefaultTab;
    
        return S_OK;
    }
    
    HRESULT CRichTextFormatDrawer::DeleteTheLastChar()
    {
        int cnt;
        HRESULT hr;
        LRESULT lr;
        CHARRANGE cr;
        TCHAR str[1] = TEXT("");
        BSTR bstr1;
        BSTR bstr2;
    
        cr.cpMin = -1;
        cr.cpMax = -1;
    
        m_pTextServices->TxGetText(&bstr1);
    
        cnt = 0;
        hr = m_pTextServices->TxSendMessage(WM_KEYDOWN, (WPARAM)VK_RIGHT, (LPARAM)1, &lr);
        
        // 将光标定位到最后
        while (S_MSG_KEY_IGNORED != hr)
        {
            cnt++;
            hr = m_pTextServices->TxSendMessage(WM_KEYDOWN, (WPARAM)VK_RIGHT, (LPARAM)1, &lr);
        }
    
        if (!SUCCEEDED(hr))
        {
            return E_FAIL;
        }
    
        // 删除最后一个字符
        hr = m_pTextServices->TxSendMessage(WM_KEYDOWN, (WPARAM)VK_BACK, (LPARAM)1, &lr);
    
        m_pTextServices->TxGetText(&bstr2);
    
        if (!SUCCEEDED(hr))
        {
            return E_FAIL;
        }
        else
        {
            return S_OK;
        }
    }
    
    HRESULT CRichTextFormatDrawer::DeleteRangeChars(int start, int end)
    {
    	int cnt;
    	HRESULT hr;
    	LRESULT lr;
    	CHARRANGE cr;
    	TCHAR str[1] = TEXT("");
    	BSTR bstr1;
    	BSTR bstr2;
    
    	cr.cpMin = -1;
    	cr.cpMax = -1;
    
    	m_pTextServices->TxGetText(&bstr1);
    
    	// 移动光标
    	cnt = 0;
    	hr = m_pTextServices->TxSendMessage(WM_KEYDOWN, (WPARAM)VK_RIGHT, (LPARAM)1, &lr);
    
    	// 将光标定位到最后
    	while (S_MSG_KEY_IGNORED != hr)
    	{
    		cnt++;
    		hr = m_pTextServices->TxSendMessage(WM_KEYDOWN, (WPARAM)VK_RIGHT, (LPARAM)1, &lr);
    	}
    
    	if (!SUCCEEDED(hr))
    	{
    		return E_FAIL;
    	}
    
    	// 删除最后一个字符
    	hr = m_pTextServices->TxSendMessage(WM_KEYDOWN, (WPARAM)VK_BACK, (LPARAM)1, &lr);
    
    	m_pTextServices->TxGetText(&bstr2);
    
    	if (!SUCCEEDED(hr))
    	{
    		return E_FAIL;
    	}
    	else
    	{
    		return S_OK;
    	}
    }
    
    HRESULT CRichTextFormatDrawer::GetTextLengthEx(int &lengh)
    {
        HRESULT hr;
        LRESULT lr;
        GETTEXTLENGTHEX info;
    
        lengh = 0;
    
        info.flags = GTL_DEFAULT;
        info.codepage = CP_ACP;
        hr = m_pTextServices->TxSendMessage(EM_GETTEXTLENGTHEX, (WPARAM)&info, (LPARAM)0, &lr);
        
        lengh = (int)lr;
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::GetExTextSel(int &min, int &max)
    {
        HRESULT hr;
        LRESULT lr;
        CHARRANGE range;
    
        min = 0;
        max = 0;
    
        hr = m_pTextServices->TxSendMessage(EM_EXGETSEL, (WPARAM)0, (LPARAM)&range, &lr);
    
        if (SUCCEEDED(hr))
        {
            min = range.cpMin;
            max = range.cpMax;
        }
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::SetExTextSel(int min, int max)
    {
        HRESULT hr;
        LRESULT lr;
        CHARRANGE range;
    
        range.cpMin = min;
        range.cpMax = max;
        hr = m_pTextServices->TxSendMessage(EM_EXSETSEL, (WPARAM)0, (LPARAM)&range, &lr);
    
        return hr;
    }
    
    CRichTextFormatDrawer::~CRichTextFormatDrawer()
    {
        FreeLibrary(m_hModule);
    }
    
    HRESULT CRichTextFormatDrawer::QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::QueryInterface\n"));
    
        *ppvObject = NULL;
    
        return S_FALSE;
    }
    
    ULONG CRichTextFormatDrawer::AddRef(void)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::AddRef\n"));
    
        return 0;
    }
    
    
    ULONG CRichTextFormatDrawer::Release(void)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::Release\n"));
    
        return 0;
    }
    
    HDC CRichTextFormatDrawer::TxGetDC()
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetDC\n"));
    
        return NULL;
    }
    
    INT CRichTextFormatDrawer::TxReleaseDC(HDC hdc)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxReleaseDC\n"));
    
        return 1;
    }
    
    BOOL CRichTextFormatDrawer::TxShowScrollBar(INT fnBar, BOOL fShow)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxShowScrollBar\n"));
    
        return FALSE;
    }
    
    BOOL CRichTextFormatDrawer::TxEnableScrollBar(INT fuSBFlags, INT fuArrowflags)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxEnableScrollBar\n"));
    
        return FALSE;
    }
    
    BOOL CRichTextFormatDrawer::TxSetScrollRange(INT fnBar, LONG nMinPos, INT nMaxPos, BOOL fRedraw)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxSetScrollRange\n"));
    
        return FALSE;
    }
    
    BOOL CRichTextFormatDrawer::TxSetScrollPos(INT fnBar, INT nPos, BOOL fRedraw)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxSetScrollPos\n"));
    
        return FALSE;
    }
    
    void CRichTextFormatDrawer::TxInvalidateRect(LPCRECT prc, BOOL fMode)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxInvalidateRect\n"));
    }
    
    void CRichTextFormatDrawer::TxViewChange(BOOL fUpdate)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxViewChange\n"));
    }
    
    BOOL CRichTextFormatDrawer::TxCreateCaret(HBITMAP hbmp, INT xWidth, INT yHeight)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxCreateCaret\n"));
    
        return FALSE;
    }
    
    BOOL CRichTextFormatDrawer::TxShowCaret(BOOL fShow)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxShowCaret\n"));
        return FALSE;
    }
    
    BOOL CRichTextFormatDrawer::TxSetCaretPos(INT x, INT y)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxSetCaretPos\n"));
        return FALSE;
    }
    
    BOOL CRichTextFormatDrawer::TxSetTimer(UINT idTimer, UINT uTimeout)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxSetTimer\n"));
        return FALSE;
    }
    
    void CRichTextFormatDrawer::TxKillTimer(UINT idTimer)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxKillTimer\n"));
    }
    
    void CRichTextFormatDrawer::TxScrollWindowEx(INT dx, INT dy, LPCRECT lprcScroll, LPCRECT lprcClip, HRGN hrgnUpdate, LPRECT lprcUpdate, UINT fuScroll)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxScrollWindowEx\n"));
    }
    
    void CRichTextFormatDrawer::TxSetCapture(BOOL fCapture)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxSetCapture\n"));
    }
    
    void CRichTextFormatDrawer::TxSetFocus()
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxSetFocus\n"));
    }
    
    void CRichTextFormatDrawer::TxSetCursor(HCURSOR hcur, BOOL fText)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxSetCursor\n"));
    }
    
    BOOL CRichTextFormatDrawer::TxScreenToClient(LPPOINT lppt)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxScreenToClient\n"));
        return FALSE;
    }
    
    BOOL CRichTextFormatDrawer::TxClientToScreen(LPPOINT lppt)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxClientToScreen\n"));
        return FALSE;
    }
    
    HRESULT	CRichTextFormatDrawer::TxActivate(LONG * plOldState)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxActivate\n"));
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxDeactivate(LONG lNewState)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxDeactivate\n"));
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetClientRect(LPRECT prc)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetClientRect\n"));
        //*prc = m_rcClient;
        *prc = CRect(0, 0, 0, 0);
        
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetViewInset(LPRECT prc)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetViewInset\n"));
        //*prc = m_rcViewInset;
        *prc = CRect(0, 0, 0, 0);
    
        return S_OK;
    }
    
    HRESULT CRichTextFormatDrawer::TxGetCharFormat(const CHARFORMATW **ppCF)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetCharFormat\n"));
        *ppCF = &m_charFormat;
    
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetParaFormat(const PARAFORMAT **ppPF)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetParaFormat\n"));
        *ppPF = &m_paraFormat;
    
        return S_OK;
    }
    
    COLORREF CRichTextFormatDrawer::TxGetSysColor(int nIndex)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetSysColor\n"));
        return GetSysColor(nIndex);
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetBackStyle(TXTBACKSTYLE *pstyle)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetBackStyle\n"));
        *pstyle = TXTBACK_TRANSPARENT;
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetMaxLength(DWORD *plength)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetMaxLength\n"));
        //*plength = m_dwMaxLength;
        *plength = 8*1024*1024;
        
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetScrollBars(DWORD *pdwScrollBar)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetScrollBars\n"));
        //*pdwScrollBar = m_dwScrollbar;
        *pdwScrollBar = 0;
        
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetPasswordChar(TCHAR *pch)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetPasswordChar\n"));
        return S_FALSE;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetAcceleratorPos(LONG *pcp)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetAcceleratorPos\n"));
        *pcp = -1;
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetExtent(LPSIZEL lpExtent)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetExtent\n"));
        return E_NOTIMPL;
    }
    
    HRESULT CRichTextFormatDrawer::OnTxCharFormatChange(const CHARFORMATW *pcf)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::OnTxCharFormatChange\n"));
        memcpy(&m_charFormat, pcf, pcf->cbSize);
    
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::OnTxParaFormatChange(const PARAFORMAT *ppf)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::OnTxParaFormatChange\n"));
        memcpy(&m_paraFormat, ppf, ppf->cbSize);
    
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetPropertyBits(DWORD dwMask, DWORD *pdwBits)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetPropertyBits\n"));
        *pdwBits = m_dwPropertyBits;
        
        return S_OK;
    }
    
    HRESULT	CRichTextFormatDrawer::TxNotify(DWORD iNotify, void *pv)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxNotify\n"));
        if (iNotify == EN_REQUESTRESIZE)
        {
            int x;
    
            x = 0;
        }
    
        return S_OK;
    }
    
    HIMC CRichTextFormatDrawer::TxImmGetContext()
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxImmGetContext\n"));
        return NULL;
    }
    
    void CRichTextFormatDrawer::TxImmReleaseContext(HIMC himc)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxImmReleaseContext\n"));
        //
    }
    
    HRESULT	CRichTextFormatDrawer::TxGetSelectionBarWidth(LONG *lSelBarWidth)
    {
        //TRACE(TEXT("CRichTextFormatDrawer::TxGetSelectionBarWidth\n"));
        *lSelBarWidth = 0;
    
        return S_OK;
    }
    
    HRESULT CRichTextFormatDrawer::Draw(HDC hDc, CRect &rcBox)
    {
        HRESULT hr;
        RECTL rcBound;
    
        rcBound.left = rcBox.left;
        rcBound.top = rcBox.top;
        rcBound.right = rcBox.right;
        rcBound.bottom = rcBox.bottom;
    
        hr = m_pTextServices->TxDraw(
            DVASPECT_CONTENT,  		// Draw Aspect
            0,						// Lindex
            NULL,					// Info for drawing optimization
            NULL,					// target device information
            hDc,				    // Draw device HDC
            NULL,			 	   	// Target device HDC
            &rcBound,               // Bounding client rectangle
            NULL,                   // Clipping rectangle for metafiles
            NULL,   			    // Update rectangle
            NULL, 	   				// Call back function
            NULL,					// Call back parameter
            TXTVIEW_INACTIVE);		// What view of the object could be TXTVIEW_ACTIVE
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::Draw2(HDC hDc, CRect &rcBox)
    {
        HRESULT hr;
        RECTL rcBound;
    
        rcBound.left = rcBox.left;
        rcBound.top = rcBox.top;
        rcBound.right = rcBox.right;
        rcBound.bottom = rcBox.bottom;
    
        hr = m_pTextServices->TxDraw(
            DVASPECT_CONTENT,       // Draw Aspect
            0,                      // Lindex
            NULL,					// Info for drawing optimization
            NULL,					// target device information
            hDc,				    // Draw device HDC
            NULL,			 	   	// Target device HDC
            &rcBound,	            // Bounding client rectangle
            NULL,					// Clipping rectangle for metafiles
            NULL,   			    // Update rectangle
            NULL, 	   				// Call back function
            NULL,					// Call back parameter
            TXTVIEW_INACTIVE);		// What view of the object could be TXTVIEW_ACTIVE
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::CalNaturalSize(HDC hDC, LONG &width, LONG &height)
    {
        HRESULT hr;
        SIZEL sizeExt = {-1, -1};
        SIZE sizeRtf;
    
        height = 0;
    
        hr = m_pTextServices->TxGetNaturalSize(
            DVASPECT_CONTENT,
            hDC,
            NULL,
            NULL,
            TXTNS_FITTOCONTENT,
            &sizeExt,
            &width,
            &height
            );
    
        sizeRtf.cx = width;
        sizeRtf.cy = height;
    
        ASSERT(S_OK == hr);
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::CalNaturalSize2(HDC hDC, LONG &width, LONG &height)
    {
        HRESULT hr;
        SIZEL sizeExt = {-1, -1};
        SIZE sizeRtf;
    
        hr = m_pTextServices->TxGetNaturalSize(
            DVASPECT_CONTENT,
            hDC,
            NULL,
            NULL,
            TXTNS_ROUNDTOLINE,
            &sizeExt,
            &width,
            &height
            );
    
        sizeRtf.cx = width;
        sizeRtf.cy = height;
    
        ASSERT(S_OK == hr);
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::SetRtfString(CStringA &rtfStr)
    {
        HRESULT hr;
        LRESULT lr;
        RTF_DATA data;
    
        data.data = rtfStr;
        data.length = rtfStr.GetLength();
        data.pos = 0;
    
        EDITSTREAM es = {(DWORD_PTR)&data, 0, RtfStrSetCallBack};
    
        hr = m_pTextServices->TxSendMessage(EM_STREAMIN, (WPARAM)(SF_RTF), (LPARAM)(&es), &lr);
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::GetRtfString(CStringA &rtfStr)
    {
        HRESULT hr;
        LRESULT lr;
        RTF_DATA data;
    
        data.length = 0;
        data.pos = 0;
    
        EDITSTREAM es = {(DWORD)&data, 0, RtfStrGetCallBack};
    
        hr = m_pTextServices->TxSendMessage(EM_STREAMOUT, (WPARAM)(SF_RTF), (LPARAM)(&es), &lr);
        
        if (SUCCEEDED(hr))
        {
            rtfStr = data.data;
        }
        else
        {
            rtfStr = _T("");
        }
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::ReplaceSel(CString csa)
    {
        HRESULT hr;
        LRESULT lr;
        LPCTSTR pStr;
    
        pStr = (LPCTSTR)csa;
        hr = m_pTextServices->TxSendMessage(EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)pStr, &lr);
    
        return hr;
    }
    
    HRESULT CRichTextFormatDrawer::TxSendMessage(UINT msg, WPARAM wp, LPARAM lp, LRESULT *pLresult)
    {
        return m_pTextServices->TxSendMessage(msg, wp, lp, pLresult);
    }
    
    DWORD CRichTextFormatDrawer::RtfStrSetCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
    {
        RTF_DATA *pRtfData = (RTF_DATA *)dwCookie;
    
        if (pRtfData != NULL)
        {
            if (pRtfData->pos < pRtfData->length)
            {
                if (pRtfData->pos + cb <= pRtfData->length)
                {
                    memcpy(pbBuff, pRtfData->data.GetBuffer(0) + pRtfData->pos, cb);
                    pRtfData->pos += cb;
                    *pcb = cb;
                    pRtfData->data.ReleaseBuffer();
                }
                else
                {
                    memcpy(pbBuff, pRtfData->data.GetBuffer(0) + pRtfData->pos, pRtfData->length - pRtfData->pos);
                    *pcb = pRtfData->length - pRtfData->pos;
                    pRtfData->data.ReleaseBuffer();
                }
            }
            else
            {
                *pcb = 0;
            }
        }
    
        return 0;
    }
    
    DWORD CRichTextFormatDrawer::RtfStrGetCallBack(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb)
    {
        INT length;
        RTF_DATA *pstr = (RTF_DATA *)dwCookie;
    
        if (pstr != NULL)
        {
            length = pstr->data.GetLength();
            length += cb;
            pstr->data.GetBufferSetLength(length + 1);
            memcpy(pstr->data.GetBuffer(0) + length - cb, pbBuff, cb);
            *(pstr->data.GetBuffer(0) + length) = '\0';
            pstr->data.ReleaseBuffer();
        }
    
        return 0;
    }

    调用的地方如下:

    LRESULT lr;
    HRESULT hr;

    m_pRichTextFmtDrawer->SetRtfString(m_rtfDocInfo.m_rtfText);
    hr = m_pRichTextFmtDrawer->TxSendMessage(EM_FORMATRANGE, FALSE, (WPARAM)&fr, &lr);

    fr参数我设置对了,同样的参数调用CRichEditCtrl的FormatRange函数,可以正确执行。但是上面 hr 返回是“无效的矩形”。目前我用隐藏的 richedit控件实现了相同的功能,总感觉比较勉强。。希望能用 windowless方法实现。




    2016年12月5日 11:28
  • Hi ChenTerry,

    抱歉回复有些晚了。

    >>fr参数我设置对了,同样的参数调用CRichEditCtrl的FormatRange函数,可以正确执行。但是上面 hr 返回是“无效的矩形”。目前我用隐藏的 richedit控件实现了相同的功能,总感觉比较勉强。。希望能用 windowless方法实现。

    你可以尝试使用CRichEditCtrl::SetRect为无边框的CRichEditCtrl设置矩形范围。

    详细内容参考以下文档。

    https://msdn.microsoft.com/en-us/library/76a787xf.aspx#cricheditctrl__setrect

    Best Regards,
    Sera Yu


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2016年12月13日 1:26