How to open a SDI window at run-time?

When you start to build an application from Microsoft's Visual studio, there are three interface options: Single document (SDI), Multiple documents(MDI), and Dialog based (DBI).

These choices stay at the very beginning. Later, you may want, for example, to create a new window by choosing a menu item, or a toolbar click, and you want the window looks exactly like the SDI with top menu, floating toobar, and an indicator on the bottom. This example shows how it can be done.

  • Step 1: Create a dialog-based application with a button, by which you want open a SDI.
  • Step 2: In ClassView, New classes: myFrame and myView from CFrameWnd and Cview.
  • Step 3: In ResourceView, Insert myMenu and myToolbar.
  • Step 4: Add Windows Message Handler: OnCreate
    /////////////////////////////////////////////////////////////////////////////
    // myFrame message handlers
    
    int myFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) 
    {
    	if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
    		return -1;
    
    	// create a view to occupy the client area of the frame
    	if (!m_myView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW,
    		CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
    	{
    		TRACE0("Failed to create view window\n");
    		return -1;
    	}
    	
    	if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
    		| CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
    		!m_wndToolBar.LoadToolBar(IDR_MY_TOOLBAR))
    	{
    		TRACE0("Failed to create toolbar\n");
    		return -1;      // fail to create
    	}
    
    	if (!m_wndStatusBar.Create(this) ||
    		!m_wndStatusBar.SetIndicators(indicators,
    		  sizeof(indicators)/sizeof(UINT)))
    	{
    		TRACE0("Failed to create status bar\n");
    		return -1;      // fail to create
    	}
    
    	m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
    	EnableDocking(CBRS_ALIGN_ANY);
    	DockControlBar(&m_wndToolBar);
    	
    	return 0;
    }
    /////////////////////////////////////////////////////////////////////////////
    
  • Step 5: Overload myFrame::OnCmdMsg to dispatch messages (otherwise the menu and toolbar will not work in CView). Overload myFrame::PreCreateWindow to specify window size. (not important)
  • Step 6: Change CView to CWnd in myView, and kill pDoc.
  • Step 7: Handle button click
    void CDlg2sdiDlg::OnOpenSdi() 
    {
    	if( m_pFrm->GetSafeHwnd() == (void*)(0xdddddddd)) 
    		m_pFrm = NULL; // memory already been released
    
    	if(!m_pFrm)
    	{
    		m_pFrm = new myFrame(this);
    
    		m_pFrm->LoadFrame(IDR_MY_MENU,
    			WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,NULL);
    
    		m_pFrm->SetWindowText("myFrmView");
    	}
    
    	if(m_pFrm)
    	{
    		m_pFrm->ShowWindow(SW_SHOW);
    		m_pFrm->UpdateWindow();
    	}
    }
    

Now, you are free to open a new window at anytime anywhere in your project.



Code | Dlg2Sdi.exe