Tutorial Five - Dialog Child Window

 Download the WocDialogChild EXE (74KB) in compressed ZIP format.

 Download the WocDialogChild project files (7KB) in compressed ZIP format.

For this and all the tutorials you will need to download the WOC header and implementation files. I recommend that you unzip them into a folder named woc and locate it at the same level as (i.e. a sibling of) the project folders which use it. This is because the projects look for the WOC files at the path: ..\woc\ as we'll see later.


WinZip® brings the convenience of Windows to the use of Zip files and other compression formats. If you don't have "the most celebrated shareware app in the history of computing" already, use the above link to download it.
   
About the tutorial
The goal of this sample is to answer a frequently-asked question - how do I place an OpenGL window on an MFC dialog? I have broadened the answer to cover placing an OpenGL window as a child window of any other. When we say OpenGL window we mean one which renders onto an OpenGL rendering context. In this tutorial I am talking specifically about a CWocOGLWnd instance which is an OpenGL window and more.

The solution shown here will not take long to describe. In fact, the WOC class CWocFrameWnd has to create a child OpenGL window when its view is of type CWocOGLWnd. So this tutorial will show you how to do yourself what the frame window class does, and to do it anywhere you like.
 
   
The steps
1. You first need to set up a new project which should start life in the same state as the WocSkeleton project. Please perform the usual copying and renaming process except that this time we are replacing WocSkeleton with WocDialogChild.

2. You now have a renamed copy of the original skeleton project, so open it in Visual Studio and build and run it to check it's okay. Remember to consult the WOC Class Reference at any point if you need to.

Locate the dialog template resource for your About Box dialog and resize it to 230 units wide by 220 high or thereabouts. We just needed to make space on the dialog for the child window, so you can now close the resource: that's all we'll be doing to it. Next we need to derive a new class from CWocDialog to represent our About Box. Up to now a simple CWocDialog instance was sufficient, but this time we want to do something special. So, at the top of the file WocDialogChild.cpp, immediately after the includes, paste the following class definition:
class COGLDialog : public CWocDialog  
{
    CWocOGLWnd m_OGLWnd;
public:
    COGLDialog (UINT nTemplateId, CWocWnd* pParentCWocWnd = 0) :
        CWocDialog(nTemplateId, pParentCWocWnd){}

    virtual BOOL OnInitWocDialog ()
    {
        if (!m_OGLWnd.CreateEx(WS_EX_CLIENTEDGE,
                               NULL,
                               _T("OGLDialog"),
                               WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | CS_DBLCLKS,
                               30,70,400,330, this, 1))
        {   
            return -1;
        }
        return CWocDialog::OnInitWocDialog();
    }
};
Next, look in your frame window class CWocDialogChildFrameWnd at the OnMenuOrAcceleratorCommand method and find where dlgAbout is declared in the command handler for IDM_ABOUT. Change the type of dlgAbout from CWocDialog to our new class type COGLDialog. Just before you compile, why not change the view type of the main frame window for a bit of variety? This will also give the impression of an application which is not fundamentally OpenGL-oriented but simply uses it on one of its dialogs. Find where theApp is declared and change the line to this:
// The one and only application object.
CWocApp < CWocDialogChildFrameWnd < CWocWnd > > theApp;
That done, compile and run. Your main frame window will now show a standard CWocWnd instance as its view whose WM_PAINT handler simply lets you know that you haven't overriden it yet. Bring up the About Box and you'll see the default model spinning inside a child window. This OGLWnd behaves exactly like the others you've seen in these tutorials - try it.

If you look back at the class we defined - COGLDialog - you'll see that it has a private member variable of type CWocOGLWnd. In the class's WM_INITDIALOG handler (OnInitWocDialog), the CWocOGLWnd is created (note we are using CreateEx rather than the Create which the frame window uses because we want to give the child window a nice 3-D sunken edge as an extended style). The penultimate argument to CreateEx is the dialog object's this pointer which is used to obtain the dialog's HWND and so discover the parent window of the child window wrapped by the CWocOGLWnd. So long as the dialog class is derived from CWocWnd then this will compile fine. However, if your dialog class is an MFC CDialog then you will need pass this->GetSafeHwnd() instead of this to use the overloaded CreateEx which takes a HWND instead of a CWocWnd*. You can get into the habit of using this overload and always calling GetSafeHwnd because CWocWnd and derived classes also implement a member with that name and the same semantics. Of course, when the dialog's CWocOGLWnd member goes out of scope it will destroy the window it manages as normal.

That's the end of the tutorials now. If you'd like to see some more uses of WOC, you'll find that most of my Graphics Samples were written using it.
 
last updated: 4-oct-01