StreamOut with large content
-
Hello all, When I use StreamOut feature of RichEditCtrl, I have a problem with large content. My StreamOut function always gets 2050 characters although my RichTextCtrl contains up to 300000 characters. Please take a look on my code below and tell me why.
DWORD __stdcall MyStreamOutCallback(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG *pcb) { USES_CONVERSION; LPWSTR lpUniText = T2W((LPTSTR)pbBuff); CString * psBuffer = (CString *)dwCookie; *psBuffer = CString(lpUniText); *pcb = wcslen(lpUniText); return 0; } CString GetSelText(CRichEditCtrl &rtf) { CString strOut; EDITSTREAM es; es.dwCookie = (DWORD)&strOut; es.pfnCallback = MyStreamOutCallback; rtf.StreamOut(SF_TEXT|SF_UNICODE,es); CHARRANGE cr; rtf.GetSel(cr); strOut = strOut.Mid(cr.cpMin,cr.cpMax-cr.cpMin-1); TRACE(_T("\ncpMax-cpMin-1 = %ld"),cr.cpMax-cr.cpMin-1); return strOut; } void CTestRTFView::OnButton1Click() { CRichEditCtrl &rtf = (CRichEditCtrl &)GetRichEditCtrl(); CHARRANGE cr; rtf.SetSel(0,-1); CString str = GetSelText(rtf); //str always contains 2050 characters. }
Is my StreamOut function correct? Please give me a way to use StreamOut with a large content. Thank you very much for your help. -
Hello all, When I use StreamOut feature of RichEditCtrl, I have a problem with large content. My StreamOut function always gets 2050 characters although my RichTextCtrl contains up to 300000 characters. Please take a look on my code below and tell me why.
DWORD __stdcall MyStreamOutCallback(DWORD dwCookie,LPBYTE pbBuff,LONG cb,LONG *pcb) { USES_CONVERSION; LPWSTR lpUniText = T2W((LPTSTR)pbBuff); CString * psBuffer = (CString *)dwCookie; *psBuffer = CString(lpUniText); *pcb = wcslen(lpUniText); return 0; } CString GetSelText(CRichEditCtrl &rtf) { CString strOut; EDITSTREAM es; es.dwCookie = (DWORD)&strOut; es.pfnCallback = MyStreamOutCallback; rtf.StreamOut(SF_TEXT|SF_UNICODE,es); CHARRANGE cr; rtf.GetSel(cr); strOut = strOut.Mid(cr.cpMin,cr.cpMax-cr.cpMin-1); TRACE(_T("\ncpMax-cpMin-1 = %ld"),cr.cpMax-cr.cpMin-1); return strOut; } void CTestRTFView::OnButton1Click() { CRichEditCtrl &rtf = (CRichEditCtrl &)GetRichEditCtrl(); CHARRANGE cr; rtf.SetSel(0,-1); CString str = GetSelText(rtf); //str always contains 2050 characters. }
Is my StreamOut function correct? Please give me a way to use StreamOut with a large content. Thank you very much for your help.Here's the methods that I use, which happily work for thousands of characters!
CString CRichEditViewEx::GetContent() { CString strContent = ""; EDITSTREAM es; CMemFile memFile; es.dwCookie = (DWORD) &memFile; es.pfnCallback = StreamOutCallback; GetRichEditCtrl().StreamOut(SF_RTF, es); memFile.SeekToBegin(); char szBuff[GETCONTENT_BUFFER + 1]; memset(szBuff, 0, GETCONTENT_BUFFER + 1); while(memFile.Read(szBuff, GETCONTENT_BUFFER) > 0) { strContent += CString(szBuff); memset(szBuff, 0, GETCONTENT_BUFFER + 1); } return strContent; } DWORD CRichEditViewEx::StreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) { CMemFile *memFile=(CMemFile *)dwCookie; memFile->WriteHuge(pbBuff,cb); *pcb = cb; return 0; }
Note that here I am getting the RTF - to just get the text, you need to change the flagSF_RTF
toSF_TEXT
, like you have in your code - and of course addSF_UNICODE
if required. If you want to get just the selected text, which is what the linestrOut=strOut.Mid(....)
seems to imply, then instead of doingCString::Mid()
, you can use the flagSFF_SELECTION
along withSF_TEXT
et al. -
Here's the methods that I use, which happily work for thousands of characters!
CString CRichEditViewEx::GetContent() { CString strContent = ""; EDITSTREAM es; CMemFile memFile; es.dwCookie = (DWORD) &memFile; es.pfnCallback = StreamOutCallback; GetRichEditCtrl().StreamOut(SF_RTF, es); memFile.SeekToBegin(); char szBuff[GETCONTENT_BUFFER + 1]; memset(szBuff, 0, GETCONTENT_BUFFER + 1); while(memFile.Read(szBuff, GETCONTENT_BUFFER) > 0) { strContent += CString(szBuff); memset(szBuff, 0, GETCONTENT_BUFFER + 1); } return strContent; } DWORD CRichEditViewEx::StreamOutCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb) { CMemFile *memFile=(CMemFile *)dwCookie; memFile->WriteHuge(pbBuff,cb); *pcb = cb; return 0; }
Note that here I am getting the RTF - to just get the text, you need to change the flagSF_RTF
toSF_TEXT
, like you have in your code - and of course addSF_UNICODE
if required. If you want to get just the selected text, which is what the linestrOut=strOut.Mid(....)
seems to imply, then instead of doingCString::Mid()
, you can use the flagSFF_SELECTION
along withSF_TEXT
et al. -
Hello, I have followed your code, but I have a Debug Assertion Failed at line 102 of file filemem.cpp when it executes to line:
while(memFile.Read(szBuff, GETCONTENT_BUFFER) > 0)
Can you tell me what happens. Thank you very much for your help.I'm confused. Delving into the CMemFile code, it looks like the internal CMemFile buffer is NULL, which means that (memory shortage problems aside) the rich edit control has never called the callback to write to the file. It might be worth putting a breakpoint before the offending line and taking a look at the memFile member variables to see if there is indeed a valid looking buffer in there! If there is no buffer, it could be down to where you are calling the function from - could it be at a point where the rich edit control might have already cleared down the content and started destroying itself? Just out of interest, what did you set GETCONTENT_BUFFER to? I set it to 4096. Sorry I can't be any more help!