Multiple Top-level Windows
Lance Lovette -- lovette@iftech.com
Wednesday, August 14, 1996
Environment: MSVC 4.2, NT 3.51 SP4
I would like to create an application that has multiple top-level
windows. (I'm not sure how to explain this so please bear with me.)
For example, when exploring 'My Computer' on Windows 95, (by default)
every time you open a directory, a new window is created that shows
the contents of that directory. Another example is DISPTEST, where
there are multiple windows for different functions. Sort of like
having multiple MDI child frame windows without the MDI parent frame
window.
My question is, how would you do this in MFC? Can you just create new
CFrameWnd's that are children of the desktop and have a "main" frame
window that m_pMainWnd points to? Or would you implement each as a
modeless dialog (then you would lose the ability to use views)? Does
the framework have any problems with multiple frame windows?
I looked for an example in the obvious places (which for me is the
Books Online, the MSDN CD, the MFC FAQ, and each of the four MFC books
I have on hand), but I can't find anything. Probably because I don't
know what terminology to use.
Thanks,
Lance
lovette@iftech.com
+-------------------------------------------------------------------+
Interface Technologies, Inc.
For a collection of free tutorials covering a variety of programming
and computer-related topics such as Visual C++, MFC, and Windows NT
check out the ITI On-line Training Center at http://www.iftech.com.
Don.Irvine@net-tel.co.uk
Friday, August 16, 1996
[Mini-digest: 8 responses]
> I would like to create an application that has multiple top-level
> windows. (I'm not sure how to explain this so please bear with me.)
> For example, when exploring 'My Computer' on Windows 95, (by default)
> every time you open a directory, a new window is created that shows
> the contents of that directory. Another example is DISPTEST, where
> there are multiple windows for different functions. Sort of like
> having multiple MDI child frame windows without the MDI parent frame
> window.
Stingray have an MFC extension class for MTI - you may want to checkout their
WEB page http://www.stingsoft.com/
Don
-----From: Deepak Saxena
Text item:
I'm doing this with my app and what I do is just create new CFrameWnd
derived windows dynamically. Basically your App becomes a manager for
all the windows and keeps a list of all windows that exist. Whenever a
top-level wnd is destroyed, it notifies the app. When all windows have
been closed, you can exit the app by posting a WM_QUIT message.
If a user closes the original top-level wnd but keeps another open, you
might have to watch out for what happens with CWinApp::m_pMainWnd, since
it will point to an invalid window.
Deepak
-----From: Jim Leavitt
Lance:
Stingray software has written the classes to accomplish the top level interface.
They are in their Objective Toolkit product.
Jim Leavitt
-----From: Hugh Robinson
This is not an advert, but if you value your time more than your bosses'
cash (!), you could investigate Objective Toolkit from Stingray Software
www.stingray.com. This includes some classes to do what you need with
very little code change from a regular MDI application.
Hugh Robinson
-----From: michael berganovsky
Hi, Lance
In general when you need another top-level window (in MFC app) you can
just derive a class from CFrameWnd or CWnd and go. Unfortunately if
you are planning to use MFC support for Doc-View-Frame staff (and when
you want MFC OLE support you have no other choice) picture becomes
much more complicated. Before you start - decide what will be your UI
model? How you want your COMMANDs to be processed. Are your menus in
the main (parent) frame and buttons on the main TOOLBAR depend on what
top-level window is currently active? Do you have main window at all?
Then if your application and resources model allows - you can buy
SEC++ from Stingray. SEC++ (if my memory doesn't fail me) supports
several UI models on top of MFC - like multiple SDI windows for
example. (You can also look into SEC++ source). On the other hand you
can take winfrm.cpp and winmdi.cpp out of MFC sources and modify them
- building you own UI model. I did that making my app look something
like VB - all windows are WS_POPUPs and forms are WS_OVERLAPPED and I
survived.
Good luck
--Michael Berganovsky
-----From: Dave Kolb
Go to Stingray Software's www.stingsoft.com and download the demos for =
Objective Toolkit. They have several MDI variations including TDI or Top =
Level Windows like VB has. I don't use OT yet but do use their Objective =
Grid product and am pretty happy with it.
Dave Kolb
PC Research and Development
SAS Institute Inc.
919-677-8000 x6827
-----From: "Rex Lam"
> Environment: MSVC 4.2, NT 3.51 SP4
There are several ways to do this. One is to create simple
modeless dialog or some CWnd-derived object. But I assume
that you probably has a frame window with client views with
menubars, toolbars, statusbars etc (the works)...
That requires just little more work.
The document-view architecture makes this simple and straight-
forward-- it allows mutliple doc-view templates within an app.
Here are the steps:
0. Create your additional docs, views and frame classes.
1. Add document templates to the app.
2. Write a handler to bring up the frame window.
Step 1:
-------
In your CMyApp::InitInstance() add all templates needed:
BOOL CMyApp::InitInstance()
{
...
// save the template pointers!!
m_pMainDocTemplate = new CSingleDocTemplate(IDR_MAINFRAME,
RUNTIME_CLASS(CMainDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMainView));
m_pMainDocTemplate2 = new CSingleDocTemplate(IDR_MAINFRAME2,
RUNTIME_CLASS(CMainDoc2),
RUNTIME_CLASS(CMainFrame2),
RUNTIME_CLASS(CMainView2));
m_pMainDocTemplate3 = new CSingleDocTemplate(IDR_MAINFRAME3,
RUNTIME_CLASS(CMainDoc3),
RUNTIME_CLASS(CMainFrame3),
RUNTIME_CLASS(CMainView3));
....
}
Step 2:
------
The trick is to call CDocTemplate::InitialUpdateFrame() to create the
new frame which indirectly creates the view. The documentation indicates
that the document should also get created by the framework. My experience
is that this is NOT the case. I had to create the document myself. It
took me a while to get it resolved. May be it is fixed in VC++ 4.2?
BOOL CMyApp::OnLaunchFrame(LPARAM lParam)
{
CSingleDocTemplate *pDocTemplate = NULL;
CDocument* pDoc = NULL;
if (lParam == FRAME2)
{
pDoc = new CMainDoc2();
pDocTemplate = pMainDocTemplate2;
}
if (lParam == FRAME3)
{
pDoc = new CMainDoc3();
pDocTemplate = pMainDocTemplate3;
}
ASSERT_VALID(pDocTemplate);
pFrame = pDocTemplate->CreateNewFrame(pDoc, NULL);
ASSERT_VALID(pFrame);
if (pFrame)
{ // frame successfully created frame
pDocTemplate->InitialUpdateFrame(pFrame, pDoc, 1); // update frame
to make visible
return TRUE;
}
return FALSE;
}
And that's it! The frame should come up and everything is working.
But keep in mind that there some abnomalities that you have to deal
with. The frame work will use your initial document template as
THE template. For example, this makes your first frame as the
parent window when display messageboxes e.g. But once you take
care of the little things, you'll be surprised how well it works!
Good luck...
-Rex Lam
Global Village Communications Inc.
Telephone: (408) 523-2040
Internet: Rex_Lam@globalvillage.com
-----From: tim
Environment: MSVC 4.1, NT 4.0 BETA
This may not answer you question, but the Stingray objective toolkit has just this sort of
thing and more. source is available. This is not an ad, I am using it in a project that
I am working on.
tim@mstus.com
Marconi Systems Technology
Reston, Virginia
Roger Onslow -- Roger_Onslow@compsys.com.au
Tuesday, August 20, 1996
>I would like to create an application that has multiple top-level
>windows. (I'm not sure how to explain this so please bear with me.)
This is what I did for similar functionality...
I had menu items Window|New, Window|Close to create/close new windows
In doc class had handlers for them as follows
ON_COMMAND(ID_WINDOW_NEW, OnWindowNew)
ON_UPDATE_COMMAND_UI(ID_WINDOW_CLOSE, OnUpdateWindowClose)
void CMyDoc::OnWindowNew() {
CDocTemplate* pDocTemplate = GetDocTemplate();
if (! pDocTemplate) {
ASSERT(FALSE);
return;
}
// create frame - set as main document frame
BOOL bAutoDelete = m_bAutoDelete;
m_bAutoDelete = FALSE; // don't destroy if something goes wrong
CFrameWnd* pMainFrame = pDocTemplate->CreateNewFrame(this,
(QIDMainFrame*)::AfxGetMainWnd());
m_bAutoDelete = bAutoDelete;
if (pMainFrame == NULL) {
ASSERT(FALSE);
// ::AfxMessageBox(::AFX_IDP_FAILED_TO_CREATE_DOC);
return;
}
pDocTemplate->InitialUpdateFrame(pMainFrame, this, TRUE);
m_nAdditionalFrames++; // my member var to count number of windows
pMainFrame->ShowWindow(SW_RESTORE);
// optional -- add an offset to each window so they "cascade"
CRect rect; pMainFrame->GetWindowRect(rect);
rect +=
CSize(m_nAdditionalFrames*::GetSystemMetrics(SM_CXMIN),m_nAdditionalFrames*::GetSystemMetrics(SM_CYMIN));
pMainFrame->MoveWindow(rect);
}
void CMyDoc::OnUpdateWindowClose(CCmdUI* pCmdUI) {
pCmdUI->Enable(m_nAdditionalFrames > 0);
}
void CMyDoc::CloseFrame(CMainFrame* pMainFrame) {
if (pMainFrame) pMainFrame->DestroyWindow();
pMainFrame = (CMainFrame*)::AfxGetMainWnd();
if (pMainFrame) pMainFrame->SetActiveWindow();
m_nAdditionalFrames--;
}
In my main frame class I had this...
ON_COMMAND(ID_WINDOW_CLOSE, OnWindowClose)
void CMainFrame::OnWindowClose() {
CMyDoc* pDoc = (CMyDoc*)GetActiveDocument();
if (pDoc) pDoc->CloseFrame(this);
}
Hope this gives you a starting point!!
Roger Onslow
Senior Software Engineer
Computer Systems Australia
RogerO@compsys.com.au
| Вернуться в корень Архива
|