Msftedit在文件末尾处理段落标记(\ par)似乎不一致

问题描述 投票:1回答:1

我已经实现了使用cricheditctrl来连接rtf文本,并且我在文件末尾遇到了\par的问题。 Wordpad使用相同的生成器并执行相同的操作。 (Msftedit 5.41.21.2510)。

如果我,其中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);

我不会在两个条目之间得到段落分隔符。他们将彼此对接。在word pad中,如果我输入一个简单的:

test

有一个换行符,我得到:

...\viewkind4\uc1\pard\sa120\cf1\f0\fs24 test\par
\f1\par
}

所以,至少,这在我的机器上总是一致的。但是我在Word 2007: Rich Text Format (RTF) Specification, version 1.9.1找不到它。

我担心的是,这不是一成不变的行为,我可能会在其他机器上得到不同的结果。然后,也许我错过了一些关于如何正确结束RTF文档的内容。我确实搜索了这个。谢谢。

更新:我很抱歉这个形象,但我认为这有帮助。它变得更加混乱。

enter image description here所以我从数据库中提取内容,你可以看到内容是:

{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;
}

更新2:现在我不得不相信这是控制中的一个缺陷。我看到了它,但它没有记录在我的脑海里。所以这个:

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。这让我抓狂! :)

mfc richtextbox rtf cricheditctrl
1个回答
2
投票

经过一些测试并使用CRichEditCtrl后,我发现它不能连接RTF文档。即使使用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结束文档的任何区别。并且单个\par没有段落属性,它需要两个才能在doc的末尾工作。我检查了,Wordpad,MS Word和Open Office都这样做了。

我已经把我的控制台测试项目herehere的副本放在这里使用的OLE无窗口CRichEditCtrl你可能会觉得很有用。

© www.soinside.com 2019 - 2024. All rights reserved.