-
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;
}
-
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).
-
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
-
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
-
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