询问者
Why the Windowless RichEditControl function TxMessage in ITextService return a value 0x8004000D?

问题
-
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
全部回复
-
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 YuMSDN 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. -
本意是想用 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方法实现。
- 已编辑 ChenTerry 2016年12月5日 11:33
-
Hi ChenTerry,
抱歉回复有些晚了。
>>fr参数我设置对了,同样的参数调用CRichEditCtrl的FormatRange函数,可以正确执行。但是上面 hr 返回是“无效的矩形”。目前我用隐藏的 richedit控件实现了相同的功能,总感觉比较勉强。。希望能用 windowless方法实现。
你可以尝试使用CRichEditCtrl::SetRect为无边框的CRichEditCtrl设置矩形范围。
详细内容参考以下文档。
https://msdn.microsoft.com/en-us/library/76a787xf.aspx#cricheditctrl__setrect
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.