15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту


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




| Вернуться в корень Архива |