From: martin@iastate.edu (Martin R Calsyn)
Subject: Re: Borland C++ OWL; want hybrid of MDI child and Dialog box
Organization: Iowa State University, Ames, IA
Distribution: comp.os.ms-windows.programmer.misc
Date: Sun, 27 Dec 1992 19:30:59 GMT

In article <1992Dec26.213715.6956@cuug.ab.ca> terbergd@cuug.ab.ca (Denis Terberg 283-8245) writes:
>I want to create an MDI child window with some (but not all)
>of the properties of a Dialog Box.
> [...]

I think the following should fit the bill.  I've mentioned this here
before and mailed it out extensively.

What follows are three files:
	TMDIDLOG.H		The interface for modeless MDI-child dialogs.
	TMDIDLOG.CPP		The implementation of same
	EXAMPLE.CPP		An (partial) example of using the
				TMDIDLOG classes.

You need to sub-class TMDIDialogWindow in order to give your MDI child a
unique icon, etc (not shown in the example) and to implement the
CreateChildDialog abstract method.  And, of course, you need to
sub-class TMDIDialog in order to establish a transfer structure,
interface objects and all the things you usually do with sub-classes of
TDialog.

The classes included below work by presenting the dialog as a child of a
TBWindow which is itself a child of the MDI.  These classes are based on
tips and suggestions offered by the Borland advisor line.

The transfer of this technique to MS MFC is trivial.

----------------------------- TMDIDLOG.H ---------------------------------

// -*- C -*-
#ifndef __tmdidlog_h__
#define __tmdidlog_h__
//
//  Copyright 1992 Software Innovations, Incorporated
//
//  $Source: C:\MDIDLOG\tmdidlog.h-v $
//  $Author: martin $
//  $Date: 92/12/27 13:05:35 $
//  $Revision: 1.1 $
//

#include <owl.h>
#include <bwindow.h>

_CLASSDEF(TMDIDialog)
_CLASSDEF(TMDIDialogWindow)

class TMDIDialog : public TDialog
{
public:
    TMDIDialog(PTWindowsObject AParent,LPSTR AName,PTModule AModule=NULL) :
    TDialog(AParent, AName, AModule) {};
    TMDIDialog(PTWindowsObject AParent,int ResourceId,PTModule AModule=NULL):
    TDialog( AParent, ResourceId, AModule ) {};
    virtual void WMSetFocus( RTMessage Msg ) = [WM_FIRST + WM_SETFOCUS];
    virtual void CloseWindow( int ret );
    virtual void CloseWindow();
    virtual void Cancel( RTMessage msg ) = [ID_FIRST + IDCANCEL];

    friend class TMDIDialogWindow;

protected:
    TMDIDialogWindow	*mdiw;
};

class TMDIDialogWindow : public TBWindow
{
public:
    TMDIDialogWindow(PTWindowsObject aParent,LPSTR aName,
                     PTModule aModule = NULL);
    virtual void WMMDIActivate( RTMessage Msg ) = [WM_FIRST + WM_MDIACTIVATE];
    virtual void WMSetFocus( RTMessage Msg ) = [WM_FIRST + WM_SETFOCUS];
    virtual void WMSize( RTMessage Msg ) = [WM_FIRST + WM_SIZE];
    virtual void SetupWindow();
    virtual LPSTR GetClassName() { return "_TMDIDialogWindow"; };
    virtual void GetWindowClass( WNDCLASS& aWndClass );
    virtual void WMGetMinMaxInfo( RTMessage msg ) = [WM_FIRST + WM_GETMINMAXINFO];
    virtual TMDIDialog *CreateChildDialog() = 0;

private:
    PTMDIDialog dlog;
};

#endif

------------------------------ TMDIDLOG.CPP -------------------------------

// -*- C -*-
//
//  Copyright 1992 Software Innovations, Incorporated
//
//  $Source: C:\MDIDLOG\tmdidlog.c-v $
//  $Author: martin $
//  $Date: 92/12/27 13:05:09 $
//  $Revision: 1.1 $
//

#include "tmdidlog.h"

TMDIDialogWindow::TMDIDialogWindow(PTWindowsObject aParent,
			 LPSTR aName,
			 PTModule aModule) :
	     TBWindow(aParent,aName,aModule)
{
    dlog = NULL;
    GetApplication()->SetKBHandler( this );
    SetFlags( WB_KBHANDLER, FALSE );
}

void TMDIDialogWindow::WMMDIActivate( RTMessage Msg )
{
    TWindow::WMMDIActivate( Msg );

    if ( Msg.WParam == TRUE ) {
        GetApplication()->SetKBHandler(this);
        if (dlog!=NULL)
            SetFocus(((PTDialog)dlog)->HWindow );
    }
}

void TMDIDialogWindow::GetWindowClass( WNDCLASS& aWndClass )
{
    TWindow::GetWindowClass(aWndClass);
}

void TMDIDialogWindow::WMSetFocus(RTMessage Msg)
{
    PostMessage(HWindow, WM_MDIACTIVATE, TRUE, 0L );
    DefWndProc(Msg);
}

void TMDIDialogWindow::SetupWindow()
{
    TWindow::SetupWindow();

    dlog = CreateChildDialog();
    if (dlog) {
        dlog->mdiw = this;
        RECT r;
        GetApplication()->MakeWindow(dlog);
        SetFocus(dlog->HWindow);
        GetWindowRect(HWindow,&r);
        Attr.X = r.left;
        Attr.Y = r.top;
        GetWindowRect(dlog->HWindow,&r);
        AdjustWindowRect(&r,WS_CAPTION|WS_BORDER,0);
        Attr.W = r.right - r.left;
        Attr.H = r.bottom - r.top;
        MoveWindow(HWindow,Attr.X, Attr.Y, Attr.W, Attr.H, 1);
    }
}

void TMDIDialogWindow::WMGetMinMaxInfo( RTMessage msg )
{
    if (dlog) {
        MINMAXINFO *lpmmi = (MINMAXINFO *)msg.LParam;
        RECT r;
        POINT pt1,pt2;
        GetWindowRect(HWindow,&r);
        pt1.x = r.left;
        pt1.y = r.top;
        GetWindowRect(dlog->HWindow,&r);
        AdjustWindowRect(&r,WS_CAPTION|WS_BORDER,0);
        pt2.x = r.right - r.left;
        pt2.y = r.bottom - r.top;
        lpmmi->ptMaxSize = pt2;
        lpmmi->ptMaxPosition = pt1;
        lpmmi->ptMinTrackSize = pt2;
        lpmmi->ptMaxTrackSize = pt2;
    }
}

void TMDIDialogWindow::WMSize( RTMessage Msg )
{
    RECT r;
    TWindow::WMSize( Msg );
    if (!IsIconic(HWindow)) {
        GetWindowRect(dlog->HWindow,&r);
        AdjustWindowRect(&r,WS_CAPTION|WS_BORDER,0);
        Attr.W = r.right - r.left;
        Attr.H = r.bottom - r.top;
        MoveWindow(HWindow, Attr.X, Attr.Y, Attr.W, Attr.H, 1);
    }
}

//
//  TMDIDialog methods...
//

void TMDIDialog::WMSetFocus( RTMessage Msg )
{
    GetApplication()->SetKBHandler( this );
    DefWndProc( Msg );
}

void TMDIDialog::CloseWindow(int ret)
{
    TDialog::CloseWindow(ret);
    mdiw->CloseWindow();
}

void TMDIDialog::CloseWindow()
{
    TDialog::CloseWindow();
    mdiw->CloseWindow();
}

void TMDIDialog::Cancel(RTMessage msg)
{
    CloseWindow(IDCANCEL);
}

------------------------------- EXAMPLE.CPP -------------------------------

//
//  #include owl, tmdidlog.h and others as needed
//

//
//  ChildDialog is a dialog box defined in the RC file under
//    the name 'MY_DLOG'.  The definition of MY_DLOG is pretty plain
//    except that it should have the following attributes:
//              STYLE WS_CHILD | WS_VISIBLE
//    and optionally CLASS "BORDLG"
//  That is, it should have no caption, sys menu, or border of any type.
//   It should also have an origin of 0,0 otherwise it will be offset
//   within the MDI child window.
//
//  An instance of ClientDialog can be created as a modeless MDI client
//   by doing : `new ChildDialogWindow(this, "Title", NULL)' from your
//   MDI frame object or other appropriate place.
//

class ChildDialog : public TMDIDialog
{
public:
    ChildDialog(PTWindowsObject aParent,
                 LPSTR aName, PTModule aModule = NULL);

};

ChildDialogWindow::ChildDialogWindow(PTWindowsObject aParent,LPSTR aName,
                                       PTModule aModule)
		: TMDIDialogWindow(aParent,aName,aModule)
{
    obj_id = object_id;
}

TMDIDialog* ChildDialogWindow::CreateChildDialog()
{
    return (TMDIDialog*)new ChildDialog(this,(LPSTR)"MY_DLOG",NULL);
}

ChildDialog::ChildDialog(PTWindowsObject aParent,
                           LPSTR aName, PTModule aModule)
		: TMDIDialog(aParent,aName,aModule)
{
    // The usual stuff:  Initialize the transfer structure, create
    //  interface objects, etc.

}

--------------------------------- The End ------------------------------

Newsgroups: comp.os.ms-windows.programmer.misc