News | Articles | Libraries | Developer Tools | Books | Forum Links | Search   
Sections:
 

QA: How do I embed a Pocket Word document in my application?

By Joao Paulo Figueira, January 28, 2004.
Print version

Question

How can I view or edit a Pocket Word document in my application?

Answer

Pocket Word documents can be read and edited in a RichInk control. The RichInk control knows how to read from and to a Pocket Word document, as well as to convert between several document types (ASCII, Unicode, RTF and Pocket Word).

This QA illustrates how to use this control in order to read from and write to files. Along the way we implement the latest version of the CFileOpenDlg (check sample application) and discuss the fine details of implementing and hosting a RichInk control under MFC.

CRichInkCtrl

The RichInk control is implemented by the CRichInkCtrl class, derived from CWnd. By looking at the code, you will see that its implementation is trivial. I chose to use the ::CreateWindowEx / SubclassWindow method of creation to make sure MFC does not change the window class style bits (see an article about this here).

On the sample application, the CChildView is derived from CRichInkCtrl instead of CWnd.

Creating the RichInk

The CRichInkCtrl child window is created on CMainFrame::OnCreate as usual (see the sample application source code). Note that I'm using an edit box style (ES_MULTILINE).

In order to make the control work properly on the CMainFrame, note the overriding of the OnCommand handler:

BOOL CMainFrame::OnCommand(WPARAM wParam, LPARAM lParam) { UINT nID = LOWORD(wParam); HWND hWndCtrl = (HWND)lParam; int nCode = HIWORD(wParam); // This can be deleted // // Avoid nasty ASSERT on debug mode // if(!(nID == 0 || ::IsWindow(hWndCtrl))) return FALSE; return CFrameWnd::OnCommand(wParam, lParam); }

This code is needed in order to avoid an assertion triggered by the debug version of MFC. Without this you will not be able to host a RichInk (or an InkX) control in a frame.

Loading and Saving Files

The RichInk control serializes its contents when you send the EM_STREAMIN and EM_STREAMOUT messages. These take as parameters the content format and a pointer to a structure (EDITSTREAM) that contain a pointer to loading or saving call back function, a 'cookie' and an error value.

Callback functions are used in order to abstract away the details of the storage. This way you can serialize to files, databases, the Internet or whatever other medium you desire. The 'cookie' is a generic piece of data that is used by the callback function. It can be a pointer to an object, a handle, a counter, ...

The sample code implements two very simple callback functions that load and save to a regular file. Saving and loading are achieved through calls to WriteFile and ReadFile respectively. These functions are called by the control an unknown number of times until all the information is serialized.

// LoadCallback // // Reader callback // static DWORD CALLBACK LoadCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb ) { HANDLE hFile = (HANDLE)dwCookie; ReadFile(hFile, pbBuff, cb, (DWORD*)pcb, NULL); return 0; } // SaveCallback // // Writer callback // static DWORD CALLBACK SaveCallback(DWORD dwCookie, LPBYTE pbBuff, LONG cb, LONG* pcb) { HANDLE hFile = (HANDLE)dwCookie; WriteFile(hFile, pbBuff, cb, (DWORD*)pcb, NULL); return 0; }

Note that here we store the file handle in the 'cookie'.

CFileOpenDlg

The sample application also implements the latest version of the CFileOpenDlg. This dialog may be handy for your own applications. Using it is quite simple, as you can see from the OnFileOpen handler:

// CChildView::OnFileOpen // // Opens a file // void CChildView::OnFileOpen() { CFileOpenDlg dlg; dlg.SetFilter(_T("*.psw")); if(dlg.DoModal() == IDOK) { HANDLE hFile; m_strFileName = dlg.GetPath(); m_strFileName += dlg.GetFileName(); hFile = CreateFile( m_strFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile) { EDITSTREAM eds; // // Prepare the structure // eds.dwCookie = (DWORD) hFile; eds.dwError = 0; eds.pfnCallback = LoadCallback; // // Read in the file // StreamIn(SF_PWI, &eds); CloseHandle(hFile); } } }

And that's it.

Sample

You can download a sample here - WordView.zip (81K).

Related resources:

Discuss

Discuss this article. Here you can write your comments and read comments of other developers.
Rate this article:     Poor Excellent    
 12345 
© 2001-2005 Pocket PC Developer Network, a division of Spb Software House