Thread: Using CWnd::Create()

  1. #1
    Registered User
    Join Date
    Dec 2004
    Posts
    205

    Using CWnd::Create()

    Hi,
    I am experimenting with the
    CWnd::Create() function. I tried to make an about box pop up using the create function but it does not work. It works fine with DoModal though and I was wondering if someone could take a look at it and tell me what I am doing wrong. The part where I use Create is in bold. Thanks I appreciate it,
    Amish

    Code:
    // TabExample1Dlg.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "TabExample1.h"
    #include "TabExample1Dlg.h"
    
    #ifdef _DEBUG
    #define new DEBUG_NEW
    #undef THIS_FILE
    static char THIS_FILE[] = __FILE__;
    #endif
    
    /////////////////////////////////////////////////////////////////////////////
    // CAboutDlg dialog used for App About
    
    class CAboutDlg : public CDialog
    {
    public:
    	CAboutDlg();
    
    // Dialog Data
    	//{{AFX_DATA(CAboutDlg)
    	enum { IDD = IDD_ABOUTBOX };
    	//}}AFX_DATA
    
    	// ClassWizard generated virtual function overrides
    	//{{AFX_VIRTUAL(CAboutDlg)
    	protected:
    	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    	//}}AFX_VIRTUAL
    
    // Implementation
    protected:
    	//{{AFX_MSG(CAboutDlg)
    	//}}AFX_MSG
    	DECLARE_MESSAGE_MAP()
    };
    
    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
    {
    	//{{AFX_DATA_INIT(CAboutDlg)
    	//}}AFX_DATA_INIT
    }
    
    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CAboutDlg)
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
    	//{{AFX_MSG_MAP(CAboutDlg)
    		// No message handlers
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CTabExample1Dlg dialog
    
    CTabExample1Dlg::CTabExample1Dlg(CWnd* pParent /*=NULL*/)
    	: CDialog(CTabExample1Dlg::IDD, pParent)
    {
    	//{{AFX_DATA_INIT(CTabExample1Dlg)
    		// NOTE: the ClassWizard will add member initialization here
    	//}}AFX_DATA_INIT
    	// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
    	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    }
    
    void CTabExample1Dlg::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    	//{{AFX_DATA_MAP(CTabExample1Dlg)
    	DDX_Control(pDX, IDC_TABCTRL1, m_tbCtrl);
    	//}}AFX_DATA_MAP
    }
    
    BEGIN_MESSAGE_MAP(CTabExample1Dlg, CDialog)
    	//{{AFX_MSG_MAP(CTabExample1Dlg)
    	ON_WM_SYSCOMMAND()
    	ON_WM_PAINT()
    	ON_WM_QUERYDRAGICON()
    	//}}AFX_MSG_MAP
    END_MESSAGE_MAP()
    
    /////////////////////////////////////////////////////////////////////////////
    // CTabExample1Dlg message handlers
    
    BOOL CTabExample1Dlg::OnInitDialog()
    {
    	CDialog::OnInitDialog();
    
    	// Add "About..." menu item to system menu.
    
    	// IDM_ABOUTBOX must be in the system command range.
    	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
    	ASSERT(IDM_ABOUTBOX < 0xF000);
    
    	CMenu* pSysMenu = GetSystemMenu(FALSE);
    	if (pSysMenu != NULL)
    	{
    		CString strAboutMenu;
    		strAboutMenu.LoadString(IDS_ABOUTBOX);
    		if (!strAboutMenu.IsEmpty())
    		{
    			pSysMenu->AppendMenu(MF_SEPARATOR);
    			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
    		}
    	}
    
    	// Set the icon for this dialog.  The framework does this automatically
    	//  when the application's main window is not a dialog
    	SetIcon(m_hIcon, TRUE);			// Set big icon
    	SetIcon(m_hIcon, FALSE);		// Set small icon
    	
    	// TODO: Add extra initialization here
    	m_tbCtrl.InsertItem(0,"Sample Tab 1");
    	m_tbCtrl.InsertItem(1,"Sample Tab 2");
    
    	m_tbCtrl.ActivateTabDialogs();
    	
    	return TRUE;  // return TRUE  unless you set the focus to a control
    }
    
    void CTabExample1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
    {
    	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
    	{
    		CAboutDlg dlgAbout;
    		//dlgAbout.DoModal();
    		dlgAbout.Create(IDD_ABOUTBOX,NULL);
    		dlgAbout.ShowWindow(SW_SHOWNORMAL);
    	}
    	else
    	{
    		CDialog::OnSysCommand(nID, lParam);
    	}
    }
    
    // If you add a minimize button to your dialog, you will need the code below
    //  to draw the icon.  For MFC applications using the document/view model,
    //  this is automatically done for you by the framework.
    
    void CTabExample1Dlg::OnPaint() 
    {
    	if (IsIconic())
    	{
    		CPaintDC dc(this); // device context for painting
    
    		SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
    
    		// Center icon in client rectangle
    		int cxIcon = GetSystemMetrics(SM_CXICON);
    		int cyIcon = GetSystemMetrics(SM_CYICON);
    		CRect rect;
    		GetClientRect(&rect);
    		int x = (rect.Width() - cxIcon + 1) / 2;
    		int y = (rect.Height() - cyIcon + 1) / 2;
    
    		// Draw the icon
    		dc.DrawIcon(x, y, m_hIcon);
    	}
    	else
    	{
    		CDialog::OnPaint();
    	}
    }
    
    // The system calls this to obtain the cursor to display while the user drags
    //  the minimized window.
    HCURSOR CTabExample1Dlg::OnQueryDragIcon()
    {
    	return (HCURSOR) m_hIcon;
    }

  2. #2
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Tries to explain reason....

    A modal dialog runs until exited by user. The app then continues from the line after DoModal().

    A modeless dialog is created and then the app continues (while the dialog is running as well).

    The local variable used to hold the dialog (dlgAbout) only exists while the function (OnSysCommand) runs.

    As soon as OnSysCommand ends the variable is freed (looses 'scope'). So the dialog disappears (never appears to be created).



    To fix problem.......

    For modeless dialogs in general....

    Add a member variable to the parent dialogs class (CTabExample1Dlg)
    ie
    CAboutDlg m_dlgAbout;

    this will have scope while the parent (CTabExample1Dlg) is active. Use this to create your about box (instead of the local one used for a modal dialog).
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

  3. #3
    Registered User
    Join Date
    Dec 2004
    Posts
    205
    Hi,
    your explanation totally makes sense. Thanks. Another question related to create(). Do I need to include any explicit function for when the dialog box is destroyed such as when I click on the OK button. When I ran the program and opened, closed and tried to reopen the dialog box, I got an assertion error. Thanks
    Amish

  4. #4
    Registered User
    Join Date
    Dec 2004
    Posts
    205
    I tried overloading the PostNcDestroy and OnCancel functions like this:
    Code:
    // testdialog.cpp : implementation file
    //
    
    #include "stdafx.h"
    #include "TabExample1.h"
    #include "testdialog.h"
    #include ".\testdialog.h"
    
    
    // testdialog dialog
    
    IMPLEMENT_DYNAMIC(testdialog, CDialog)
    testdialog::testdialog(CWnd* pParent /*=NULL*/)
    	: CDialog(testdialog::IDD, pParent)
    {
    }
    
    testdialog::~testdialog()
    {
    }
    
    void testdialog::DoDataExchange(CDataExchange* pDX)
    {
    	CDialog::DoDataExchange(pDX);
    }
    
    
    BEGIN_MESSAGE_MAP(testdialog, CDialog)
    	ON_BN_CLICKED(IDC_BUTTON1, OnBnClickedButton1)
    END_MESSAGE_MAP()
    
    
    // testdialog message handlers
    
    void testdialog::OnBnClickedButton1()
    {
    	// TODO: Add your control notification handler code here
    AfxMessageBox("Dialog closed successfully");
    }
    
    
    void testdialog::PostNcDestroy()
    { 
    	CDialog::PostNcDestroy();
    	delete this;
    }
    
    void testdialog::OnCancel()
    {
    	DestroyWindow();
    }
    but everytiime I press the EXC key, I get a degub assertion error:
    File:dbgheap.c
    Line:1132
    Expression:_CrtIsValidHeapPointer(pUserData)

    Can anybody help and tell me why it's that way. Thanks
    Amish

  5. #5
    train spotter
    Join Date
    Aug 2001
    Location
    near a computer
    Posts
    3,868
    Try adding a handler for the WM_CLOSE msg.

    Call this when you need to close the dialog ie from both OK and Cancel, then MFC will make the call to DestroyWindow().



    When creating a dialog I run a test to see if there is currently one active.

    Code:
    if(m_SomeDlg.GetSafeHwnd() != NULL)// dlg has been created so...
            m_SomeDlg.ShowWindow(SW_SHOW);//show hidden dlg
    
    else//create the dlg
    "Man alone suffers so excruciatingly in the world that he was compelled to invent laughter."
    Friedrich Nietzsche

    "I spent a lot of my money on booze, birds and fast cars......the rest I squandered."
    George Best

    "If you are going through hell....keep going."
    Winston Churchill

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 1
    Last Post: 07-08-2005, 07:44 AM