RTF (Rich Text Format) is a document file format widely supported by most text processing software (Microsoft® Word®, Apache OpenOffice™ and so on). It is able to store all core text properties (size, font, color, style, justification, paragraph and so on). This format is also supported natively by the Microsoft Windows® clipboard, so client applications are able to access RTF content from other applications.
Teigha Drawings has an OdDbMText entity that can parse RTF content and set up the multiline text format using a single call from the OdDbMText class method:
int setContentsRTF(const OdString& text);
Working with RTF content
There are two main ways to access existing RTF content:
- from the Windows clipboard
- from an .rtf file
Getting RTF content from the Windows clipboard
This example demonstrates how to get existing RTF data from the Windows clipboard. This code works only on the Microsoft Windows operating system. For other platforms, clipboard methods can differ.
OdString rtfContents;
{ // Extract RTF contents from Windows clipboard
UINT formatId = ::RegisterClipboardFormat(CF_RTF);
// Check that RTF format available in clipboard
if (::IsClipboardFormatAvailable(formatId))
{ // Read RTF contents from clipboard
if (::OpenClipboard(NULL))
{
HGLOBAL hDataPtr = ::GetClipboardData(formatId);
if (hDataPtr)
{
LPSTR pStr = (LPSTR)::GlobalLock(hDataPtr);
if (pStr)
{
rtfContents = pStr;
::GlobalUnlock(hDataPtr);
}
}
::CloseClipboard();
}
}
}
This code first checks the availability of RTF content in the Windows clipboard and copies the content into a Teigha OdString using Windows API functions.
Next we can create an MText entity using the available RTF data:
if (!rtfContents.isEmpty())
{ // Create MText finally
OdDbMTextPtr pMText = OdDbMText::createObject();
pMText->setDatabaseDefaults(pDb);
pMText->setContentsRTF(rtfContents);
OdDbBlockTableRecord::cast(pDb->getActiveLayoutBTRId().safeOpenObject(OdDb::kForWrite))->appendOdDbEntity(pMText);
}
Using this code, a client application can paste the RTF content that was copied to the Windows clipboard by another application.
Here is an example of pasting RTF clipboard content from Microsoft Word into the OdaMfcApp sample application:
Another application that supports RTF clipboard content is Microsoft Visual Studio. You can similarly copy selected parts of text and copy them to the OdaMfcApp sample application (Microsoft Visual Studio uses a different color scheme for viewing Clipboard contents, so the resulting colors can differ):
Getting RTF content from a file
You can also read RTF content directly from a file. The Teigha API provides cross-platform functionality to work with RTF files.
The following example reads an RTF file as an ASCII string for further parsing to an MText entity:
OdString rtfContents;
if (!fileName.isEmpty())
{
OdStreamBufPtr pBuf = ::odSystemServices()->createFile(fileName);
if (!pBuf.isNull())
{ // Load ASCII data from file
OdAnsiCharArray asciiData;
asciiData.resize(pBuf->length());
pBuf->getBytes(asciiData.asArrayPtr(), pBuf->length());
asciiData.push_back(0);
// Convert to string
rtfContents = asciiData.getPtr();
}
}
After, you can create an MText entity using similar code from the previous section in this article.
Full command source code
This is the full source code for the command that creates an OdDbMText entity using RTF content from a file or from the Windows clipboard:
class OdExMTextRtfContentsCmd : public OdEdCommand
{
public:
const OdString groupName() const
{
return OD_T("Test Commands");
}
const OdString globalName() const
{
return OD_T("ExMTextRtfContents");
}
void execute(OdEdCommandContext* pCmdCtx)
{ // Get required command interfaces
OdDbCommandContextPtr pDbCmdCtx(pCmdCtx);
OdDbDatabasePtr pDb = pDbCmdCtx->database();
OdSmartPtr<OdDbUserIO> pIO = pDbCmdCtx->userIO();
OdString rtfContents;
if (pDbCmdCtx->userIO()->getKeyword(OD_T("Extract RTF contents from File or Clipboard [File Clipboard]?"), OD_T("File Clipboard")) == 0)
{ // Extract RTF contents from file
OdString fileName = pIO->getFilePath(OD_T("Select file to open"), OdEd::kGfpForOpen,
OD_T("Select file to open"), OD_T("rtf"), OD_T(""), "RTF files (*.rtf)|*.rtf");
if (!fileName.isEmpty())
{
OdStreamBufPtr pBuf = ::odSystemServices()->createFile(fileName);
if (!pBuf.isNull())
{ // Load ASCII data from file
OdAnsiCharArray asciiData;
asciiData.resize(pBuf->length());
pBuf->getBytes(asciiData.asArrayPtr(), pBuf->length());
asciiData.push_back(0);
// Convert to string
rtfContents = asciiData.getPtr();
}
}
}
else
{ // Extract RTF contents from Windows clipboard
UINT formatId = ::RegisterClipboardFormat(CF_RTF);
// Check that RTF format available in clipboard
if (::IsClipboardFormatAvailable(formatId))
{ // Read RTF contents from clipboard
if (::OpenClipboard(NULL))
{
HGLOBAL hDataPtr = ::GetClipboardData(formatId);
if (hDataPtr)
{
LPSTR pStr = (LPSTR)::GlobalLock(hDataPtr);
if (pStr)
{
rtfContents = pStr;
::GlobalUnlock(hDataPtr);
}
}
::CloseClipboard();
}
}
}
if (rtfContents.isEmpty())
{
pIO->putString(OD_T("Rtf contents doesn't found."));
return;
}
OdGePoint3d insertionPoint = pIO->getPoint(OD_T("Specify MText insertion point:"));
// Create MText finally
OdDbMTextPtr pMText = OdDbMText::createObject();
pMText->setDatabaseDefaults(pDb);
pMText->setLocation(insertionPoint);
pMText->setContentsRTF(rtfContents);
OdDbBlockTableRecord::cast(pDb->getActiveLayoutBTRId().safeOpenObject(OdDb::kForWrite))->appendOdDbEntity(pMText);
}
};
static OdStaticRxObject<OdExMTextRtfContentsCmd> g_OdExMTextRtfContentsCmd;
Conclusion
Internally, conversion between Rich Text Format and MText isn’t a simple thing (look at the RTF data stored by Microsoft Word, in Notepad for example). Teigha parses all tags from RTF content and represents the data inside an OdDbMText entity using specific MText keys. But this functionality is very simple to use in a client application because all the work is done internally, and client code can access the RTF content using just one simple method call.