我已经实现了使用cricheditctrl
来隐藏rtf文本,并且在文件末尾遇到\par
的问题。写字板使用相同的生成器并执行相同的操作。 (Msftedit 5.41.21.2510)。
如果是I,其中wtrf是cricheditctrl:
const char* header = "this is a test header\r\n";
wrtf.SetWindowTextA(header);
生成的rtf为:
{\rtf1\ansi\ansicpg1252\deff0\deflang1033{\fonttbl{\f0\fswiss\fprq2\fcharset0 System;}}
{\*\generator Msftedit 5.41.21.2510;}\viewkind4\uc1\pard\b\f0\fs20 this is a test header\par
\par}
最后两个\par
。
总的来说,我正在使用rtf内容来做自己的事情。如果最后我不写双\par
,请执行以下操作:
std::string dest(_RichEditPreamble);
dest+= std::string("\\cf1 this is a test\\par\\par}";
SetRichText(wrtf,dest.c_str());
wrtf.SetSel(-1, -1); // Select last character
SetRichText(wrtf, more_rtf, SF_RTF | SFF_SELECTION);
我不会在两个条目之间使用段落分隔符。他们会互相对接。如果我输入一个简单的单词,请在记事本中输入
:test
使用一个换行符,我得到:
...\viewkind4\uc1\pard\sa120\cf1\f0\fs24 test\par
\f1\par
}
因此,至少,这在我的机器上始终是一致的。但是在Word 2007: Rich Text Format (RTF) Specification, version 1.9.1中找不到任何讨论。
我担心这不是恒定的行为,在其他计算机上可能会得到不同的结果。然后,也许我错过了有关如何正确结束RTF文档的知识。我确实从中搜索了。 谢谢。
更新: 我为这张图片感到抱歉,但我认为这很有帮助。只会变得更加混乱。
{rtf_stuff ... content\par}
并进入顶部窗口,您可以看到段落标记在起作用,只是一个。
sel= GetRichText( re, SF_RTF );
std::ofstream ts(R"(C:\cpp\ReserveAnalyst_14\StockCommentParser\test.txt)");
ts << sel;
test.txt具有:
{\rtf1\stuff ... asphalt sealing.\par
\par
}
现在有两个\par
。在第二个RTF窗口中,我将数据放置在其中:
SetRichText( pCommentFrm->GetRichCtrl( ), text, SF_RTF | SFF_SELECTION ); //todo ??
我最后有两个段落! (第二个rtf窗口)
以防万一,这是我使用了20年的回电:
DWORD CALLBACK EditStreamCallBack(
DWORD_PTR dwCookie, LPBYTE pbBuff, LONG cb, LONG *pcb )
{
_afxRichEditStreamCookie* pCookie = (_afxRichEditStreamCookie*)dwCookie;
CArchive& ar = pCookie->m_ar;
DWORD dw = 0;
*pcb = cb;
TRY
{
if ( ar.IsStoring( ) )
ar.GetFile( )->Write( pbBuff, cb );
else
*pcb = ar.GetFile( )->Read( pbBuff, cb );
}
CATCH( CFileException, e )
{
*pcb = 0;
pCookie->m_dwError = (DWORD)e->m_cause;
dw = 1;
e->Delete( );
}
AND_CATCH_ALL( e )
{
*pcb = 0;
pCookie->m_dwError = -1;
dw = 1;
e->Delete( );
}
END_CATCH_ALL
return dw;
}
UPDATE2 :现在,我必须相信它是控件中的缺陷。我看到了它,但是它没有在我的脑海中浮现。因此:
std::string source1(_RichEditPreamble);
source1 += "\\cf1 test 1\\par}";
SetRichText(wrtf,source1.c_str());
std::string source2(_RichEditPreamble);
source2 += "\\cf0 test 2\\par";
wrtf.SetSel(-1, -1); // Select last character
SetRichText(wrtf, source2.c_str(), SF_RTF | SFF_SELECTION);
auto result = GetRichText(wrtf);
std::ofstream ts("..\\rtf_io.rtf");
ts << result;
文件中的结果为:
{\rtf1\,,,\viewkind4\uc1\pard\sa120\cf1\f0\fs24 test 1\cf2 test 2\cf1\par}
wrtf.SetSel(-1, -1);
将插入点放在最后一个\par
的前面,而不是后面。提示是从第一次插入起,最后一个参数的颜色标签为\cf1
。在这种情况下,它会丢弃我的\par
中的一个,而在以前的情况中则不是,所以看起来我要多了\par
。它让我发疯! :)
答案 0 :(得分:1)
经过一些测试并使用CRichEditCtrl,我发现它不是用来连接RTF文档的。即使使用public
,它也会将插入视为插入。这意味着插入上方文本的所有特征都附加到文档的末尾。对我来说,我需要一个真正的附加文件,其中插入的末尾特征将位于文档末尾。我希望用户获得他们所看到的内容,如果他们要向文档中添加更多内容。我确实提出了我认为可以解决的问题。它可能并不总是有效,但至少在异常情况下不应结束。
SetSel(-1,-1)
这会删除文档末尾的所有格式,并且只留下几个BOOL AppendRichText( CRichEditCtrl& rtf, LPCTSTR buf )
{
rtf.SetSel(-1, -1);
if( ! SetRichText(rtf,buf, SF_RTF | SFF_SELECTION))
return FALSE;
auto buffer = GetRichText(rtf);
char* che= buffer.get();
for(; *che; ++che);//to end
char* ch= che;
for(; *ch != ' '; --ch);//back to first space
for(; *ch != '\\'; ++ch);//then to first '\', assumes not \\,\},\{ for now
if( ch + 10 > che )
return FALSE;//but it should fit....
auto re = R"(\par\par})"; // the replacement
for( size_t i= 0; i < 10; ++i)
*ch++ = *re++;
return SetRichText(rtf,buffer.get());
}
从这篇文章的标题中学到的另一件事是,要用段落标记结束文档,您必须用两个\par
控制字来结束文档。我重新检查了\par
。在以2007: Rich Text Format (RTF) Specification, version 1.9.1.
结尾的文档中,我找不到任何区别。而且,单个\par
没有段落属性,在文档末尾需要两个才能工作。我检查了写字板,MS Word和Open Office都做了。
我已经放置了控制台测试项目here和here的副本。这里使用了一个OLE无窗口CRichEditCtrl,您可能会觉得有用。