The model I used for integrating my openGL Sierpinski code with Windows comes from an article that is included on the Microsoft Developer Network Library CD-ROM: OpenGL I: Quick Start by Dale Rogerson. Like all Developer Network Library articles, this one comes packaged with the source code. For the PreCreateWindow and OnCreate class functions, which do window and graphics palette setup, I copied the code directly. I also followed Rogerson's scheme in setting up the OnIlde and OnDraw class functions. The OnIdle class function calls the openGL code that rotates the Sierpinski pyramid. The OnDraw class function calls the code that displays the Sierpinski pyramid.
The Serialize Function
The Microsoft Foundation Classes encapsulate a lot of the basic functionality needed to create a window application. Every Windows application built by the application wizard includes an instance of the CDocument class, which includes an implementation of the OnFileSaveAs function. When the user selects the SaveAs item from the file menu, the default implementation of OnFileSaveAs invokes the Microsoft file browser dialog, gets the file name from the user, issues a warning if the file already exists and opens the file. The application wizard also creates an instance of the Serialize class function for the application's class derived from CDocument. The Serialize function is called after the file is opened. The calling sequence is shown below.
CDocument::OnFileSaveAs() CDocument::DoSave(char *, int ) CDocument::OnSaveDocument(char * ) CSier2Doc::Serialize(CArchive & {...})
The Serialize function is passed a pointer to a CArchive object. A file pointer is returned by the GetFile class function of CArchive. This file pointer is for an unbuffered file. The code to write out the Sierpinski pyramid uses buffered POSIX style stream I/O. After spending a couple of hours searching throught the Developer Library CD-ROM, I found a rather obscure set of functions calls that can be used to convert the unbuffered file "handle" into a buffered file pointer. The Serialize function is included below.
void CSier2Doc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // storing // get the low level file pointer. CFile *cfile_fp = ar.GetFile(); // Get the operating system file handle int os_file_handle = cfile_fp->m_hFile; // Convert the operating system file handle into a handle that // is compatible with POSIX style stream I/O. This handle // is the same handle that is returned by the POSIX open() // call. Note that the file is opened "write only" int crt_handle = _open_osfhandle( os_file_handle, _O_WRONLY ); // Convert the unbuffered POSIX style handle into a buffered // file pointer. FILE *fp = _fdopen( crt_handle, "w" ); // Write the pyramid out in DXF format PyrPtr->pyr_write( fp ); // The close operation that is performed by MFC does a low // level close and does not flush the buffers, so flush them // here. fflush( fp ); } else { // loading // this should never happen AfxMessageBox("CSier2Doc::Serialize: no load function implemented"); } }
Windows Help
The most rapidly accessible reference I found on creating a help window that pops up in response to the "Help" menu item is in Inside Visual C++ by David J. Kruglinski. The "help" included with the program is very brief and does not include any hyper-links. The WinHelp call, shown below, executes the Microsoft help display program. This program is called with a tag argument that tells it where to start displaying the help document. Since the Sierpinski program is heavily CPU bound, a call to Sleep is included to give the help window a chance to come up.
void CMainFrame::OnDefaultHelp() { // marker in the help file where help should start const int HID_CONTENTS = 100; const int hang_time = 2000; // two seconds AfxGetApp()->WinHelp(HID_CONTENTS); Sleep(hang_time); }