按段落读取RTF富文本格式文件内容
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
最近写游戏公告服务器,需要按分段落读取RTF格式文本文件内容到内存中,然后下发客户端.
网络上没找到类似功能的代码,费了些功夫研究了一下,感觉在Windows下写些自由度较大的功能都像是在做hack.
// 创建一个临时RichEdit控件
HMODULE hInstRich = ::LoadLibrary("RICHED20.DLL");
ATLASSERT(hInstRich != NULL);
CRichEditCtrl ctrlRichEdit;
ctrlRichEdit.Create(NULL, NULL, NULL, WS_POPUP | ES_MULTILINE);
// 取得ITextDocument接口
IRichEditOle* pRichEditOle = ctrlRichEdit.GetOleInterface();
if(!pRichEditOle) return false;
ITextDocument* pRichDoc = NULL;
pRichEditOle->QueryInterface(__uuidof(ITextDocument), (LPVOID*)&pRichDoc);
SAFE_RELEASE(pRichEditOle);
if(!pRichDoc) return false;
// 打开RTF文件
CComVariant varFileName = szFileName;
HRESULT hr = pRichDoc->Open(&varFileName, tomReadOnly | tomRTF, 0);
if(FAILED(hr))
{
SAFE_RELEASE(pRichDoc);
return false;
}
// 读取RTF文件
CIntArray arrParas;
arrParas.push_back(0);
// 分析文章每个段的位置
int lineCount = ctrlRichEdit.GetLineCount();
for(int i = 0; i < lineCount; i++)
{
char szLineText[16] = { 0 };
int nLineBeginCharIndex = ctrlRichEdit.LineIndex(i);// 行首CharIndex
int nLineLength = ctrlRichEdit.LineLength(nLineBeginCharIndex);
if(nLineLength == 0) continue;
int nLineEndCharIndex = nLineBeginCharIndex + nLineLength;// 行末CharIndex
ctrlRichEdit.GetTextRange(nLineEndCharIndex, nLineEndCharIndex + 1, szLineText);
if(szLineText[0] == '\r')
{
arrParas.push_back(nLineEndCharIndex + 1);
}
}
// 读取每个段的内容到内存
FORMATETC fmtEtc = { RegisterClipboardFormat(CF_RTF), NULL, DVASPECT_CONTE NT, -1, TYMED_HGLOBAL };
for(uint32 i = 0; i < arrParas.size() - 1; i++)
{
ITextRange* pTextRange = NULL;
if(SUCCEEDED(pRichDoc->Range(arrParas[i], arrParas[i+1], &pTextRange)) && pText Range != NULL)
{
CComVariant varDataObject;
IDataObject* pDataObject = NULL;
varDataObject.vt = VT_UNKNOWN | VT_BYREF;
varDataObject.ppunkVal = (IUnknown**)&pDataObject;
hr = pTextRange->Copy(&varDataObject);
if(SUCCEEDED(hr) && pDataObject != NULL)
{
STGMEDIUM stgMedium = { TYMED_HGLOBAL, 0 };
hr = pDataObject->GetData(&fmtEtc, &stgMedium);
if(SUCCEEDED(hr) && stgMedium.hGlobal != NULL)
{
DWORD nLen = ::GlobalSize(stgMedium.hGlobal);
void* pData = (void*)::GlobalLock(stgMedium.hGlobal);
CMemChunkBase chunk(nLen);
chunk.WriteData(pData, nLen);
m_arrSysMsgs.push_back(chunk);
::GlobalUnlock(pData);
}
}
SAFE_RELEASE(pDataObject);
SAFE_RELEASE(pTextRange);