平民程序 - linghuye's blog

天下风云出我辈,一入江湖岁月催。皇图霸业谈笑中,不胜人生一场醉。提剑跨骑挥鬼雨,白骨如山鸟惊飞。尘事如潮人如水,只笑江湖几人回。

随笔 - 221, 文章 - 0, 评论 - 680, 引用 - 0
数据加载中……

按段落读取RTF富文本格式文件内容

最近写游戏公告服务器,需要按分段落读取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_CONTENT, -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))  &&  pTextRange != 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);
    }

}


SAFE_RELEASE(pRichDoc);
ctrlRichEdit.DestroyWindow();
FreeLibrary(hInstRich);
hInstRich 
= NULL;

posted on 2006-06-29 11:14 linghuye 阅读(1598) 评论(0)  编辑 收藏 引用 所属分类: 编程札记

只有注册用户登录后才能发表评论。