I have an MFC dialog based application created inside Visual Studio 2008.
CCalendarWindowDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
When I run the application, DoModal() asserts at very first line
INT_PTR CDialog::DoModal()
{
// can be constructed with a resource template or InitModalIndirect
ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL ||
m_lpDialogTemplate != NULL);
}
Can anyone please help?
For solving this in the Constructor of my Dialog class, I did something like
CCalendarWindowDlg::CCalendarWindowDlg ()
:CDialog(IDD)
{
}
Notice I am calling the constructor of the CDialog parent class with the resource ID of the form I want to present.
Seems like the resource template is missing or wrongly mapped.
Look at the IDD attribute at your CCalendarWindowDlg class and see whether you have the appropriate dialog present in the Resource View.
Are you using the satellite DLLs for localization or other purpose? or the CCalendarWindowDlg component resource DLL might be missing.
I had the same problem when just creating new dialog based MFC application using Visual Studio 2012. For me the solution was to use dialog construtor that takes dialog resource ID as parameter.
For instance:
CCalendarWindowDlg dlg(IDD_MYDIALOG);
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
Hope this helps.
Related
I am popping up a CDHtmlDialog box when user clicks inside a another dialog box. Here is the pseudo code
CMyClass{
CDHtmlDialog * m_htmlDialog;
}
CMyClass::OnInitDialog(){
m_htmlDialog = new CDHtmlDialog(IDD_DIALOG_EMAIL, IDR_HTML_SUBMIT_EMAIL);
}
CMyClass::OnBnClickSendEmail{
m_htmlDialog->Create(IDD_DIALOG_EMAIL);
//m_htmlDialog->DoModal();
m_htmlDialog->ShowWindow(SW_SHOWNORMAL);
}
The code runs fine when the DoModal is commented. But the problem is that the Html Dialog is not modal and I can click on the background forms and dialogs. I want the Html dialog to be modal and when I uncomment the DoModal() line the code crashes.
This is how I display a modal dialog, when it begins as a null pointer:
auto *pDlgEditor = new CSomeDlg(this);
if (pDlgEditor != nullptr)
{
pDlgEditor->DoModal();
delete pDlgEditor;
}
Notice that I am passing this which is the owner for the window.
The actual class itself specifies the dialogue resource:
CSomeDlg::CChristianLifeMinistryEditorDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_DIALOG_EXAMPLE, pParent))
I realise that my code doesn't show a CDHtmlDialog ... According to the documentation there are 3 constructors:
CDHtmlDialog();
CDHtmlDialog(
LPCTSTR lpszTemplateName,
LPCTSTR szHtmlResID,
CWnd *pParentWnd = NULL);
CDHtmlDialog(
UINT nIDTemplate,
UINT nHtmlResID = 0,
CWnd *pParentWnd = NULL);
The third parameter is the parent which defaults to NULL. Try passing this as the third parameter.
Now, if you are inside a popup modaless window when you do the above the parent will be the modaless window. But if you pass the modaless windows' parent then that will become the owner instead. We don't have full information so the above is just generic advice.
Note that the documentation states that if you leave the pParentWnd as the default (NULL):
If it is NULL, the dialog object's parent window is set to the main application window.
So, it might not necessarily use the parent you expect, which is why it is good to specify it yourself.
The below code, creating a Property Sheet, works without problem in an Application File.
.......
CProp_Sheet Pr_Sheet(_T("PS"));
CPr_Page_1 Pr_Page_1;
CPr_Page_2 Pr_Page_2;
Pr_Sheet.AddPage(&Pr_Page_1);
Pr_Sheet.AddPage(&Pr_Page_2);
m_pMainWnd = &Pr_Sheet;
int nResponse = Pr_Sheet.DoModal();
However, when I put the same code in a DLL, and call it from a menu item in another Application, m_pMainWnd cannot be used (the menu in the Application is to remain visible behind the Property Sheet).
I have tried to create a handle
CWnd* m_pWnd = &Pr_Sheet;
and use m_pWnd in the CProp_Sheet constructor, but although compiling correctly at run time failure always occurs at
CProp_Sheet::OnInitDialog().
Thanks in advance for any comments.
To preface we have a strange requirement that all dialogs must be modeless for an MFC application. There is a particular dialog using region drawing and some custom controls to select dates and times for viewing past and future data per view. I need to be able to close this window when it loses focus, the main app gets a system command, etc.
I figured the easiest way to do this would be to register the class like so:
// for CWnd::FindWindow
WNDCLASS wndcls;
SecureZeroMemory(&wndcls, sizeof(WNDCLASS));
wndcls.lpszClassName = L"CTransactionDialog";
wndcls.style = CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = AfxWndProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hIcon = NULL;
#ifndef _WIN32_WCE_NO_CURSOR
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
#else
wndcls.hCursor = 0;
#endif
wndcls.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
wndcls.lpszMenuName = NULL;
BOOL retVal = AfxRegisterClass(&wndcls);
if (!retVal)
AfxMessageBox(L"AfxRegisterClass(CTransactionDialog) Failed");
Then later in response to various event handlers and messages where I would want these modeless window or windows to be closed to do something simple like this:
CWnd* pFound = NULL;
while ((pFound = CWnd::FindWindow(L"CTransactionDialog", NULL)) != NULL)
pFound->DestroyWindow();
However despite the registration of the class succeeding and looking at GetRuntimeClass of the dialog in question in debug and seeing that is matches up as expected the FindWindow never seems to find or close these modeless dialogs as expected.
What am I doing wrong or is there a better way to go about this?
Update: This is how the dialog is created via a static method on the dialog class. The dialog resource for the id specified in create has the Popup property set which should resolve to WS_POPUP style under the MFC covers. The dialog shouldn't and doesn't have a parent as far as I knew.
CTransactionDialog* CTransactionDialog::ShowTransactionDialog(const CRect& crCtrlToFloatAbove, UINT dialogID, Itime defaultTime, Itime initialTime)
{
CTransactionDialog* pCTDialog = new CTransactionDialog(crCtrlToFloatAbove, dialogID, defaultTime, initialTime);
pCTDialog->Create(CTransactionDialog::IDD);
pCTDialog->ShowWindow(SW_SHOW);
return pCTDialog;
}
Update: Doh! FindWindowEx isn't finding anything either.
CWnd::FindWindowEx(AfxGetMainWnd()->GetSafeHwnd(), NULL, L"CTransactionDialog", NULL);
However I have a new plan. I'm just going to make my own window message and handle it on the main frame. I think I can get away with passing a pointer to the dialog as the lParam of the message and then casting it to a CWnd* then calling DestroyWindow. It will work for most cases in a very round about way. I may run into trouble with minimizing and maximizing of the main frame window for dialogs that nothing is holding a pointer too but we'll see.
FindWindow doesn't work with child windows. To find a child window, you can use FindWindowEx, passing the HWND of the parent window as the first parameter.
Class name denotes NOT the c++ class name - it denotes the window class name. This name was used to register the window by the OS and has nothing to do with the c++ class.
May MSDN enlight you...
CWnd::FindWindow does not search child windows.
Is it possible that the mode less window that you are creating has a parent set and that is the reason why FindWindow doesn't find it ?
Below is the simplest and cleanest solution I could come up with:
BOOL CTransactionDialog::OnNcActivate(BOOL bActive)
{
if (!bActive)
PostMessage(WM_CLOSE);
return CDialog::OnNcActivate(bActive);
}
Not 100% sure about this but I think you need to set your class name in the resource file. You are defining a windows class and creating a dialog class but you aren't linking them. Setting a class name in the WNDCLASS struct won't help unless you actually have a way of linking it to the dialog. If you use the resource file and define the dialog, and class name in there then it should work.
I'm trying to launch a modal dialog from a DLL loaded by an MFC application. I'm using VS2010 and both the EXE and DLL use MFC in a static library.
I call DoModal() in my DLL to launch the dialog, with the parent being a CWnd* pointing to the main window from the MFC app. The dialog resource is in the DLL.
This eventually leads to the MFC library function CWnd::CreateDlgIndirect, which has this debug check:
#ifdef _DEBUG
if ( AfxGetApp()->IsKindOf( RUNTIME_CLASS( COleControlModule ) ) )
{
TRACE(traceAppMsg, 0, "Warning: Creating dialog from within a COleControlModule application is not a supported scenario.\n");
}
#endif
AfxGetApp() returns NULL so the code in the debug check fails. If I compile in release, the dialog appears, but doesn't seem to work (all the fields are empty even though I set defaults, some button's don't appear).
I've tried adding AFX_MANAGE_STATE(AfxGetStaticModuleState()); to the top of the function that launches the dialog, and it doesn't make any difference.
What am I missing?
Edit: here's the code I use to call the dialog.
HMODULE oldResMod = AfxGetResourceHandle();
AFX_MANAGE_STATE(AfxGetStaticModuleState());
AfxSetResourceHandle(GetThisModule());
CWnd wndParent;
wndParent.Attach(parent);
CExportOptionsDlg dlg(&wndParent);
dlg.project_name = project->GetName();
if (dlg.DoModal() != IDOK)
{
wndParent.Detach();
AfxSetResourceHandle(oldResMod);
return false; // cancelled
}
// ... (get some data from the dialog members) ...
wndParent.Detach();
AfxSetResourceHandle(oldResMod);
return true; // OK
Check that you've actually created a CWinApp somewhere in your current module (DLL/EXE).
Every module should have one, and only one, CWinApp object. Typically, you would make the CWinApp object a global variable such that it is created and destroyed when the module is loaded and unloaded, respectively.
Can someone tell me how I could create a Non Modal Dialog in MFC's Visual c++ 6.0 and show it?
I wrote this code:
CDialog dialog;
if (dialog.init(initialization values...))
dialog.DoModal();
But it blocks my application from showing the dialog. I dont know if there exists any method or other way to do it.
Thanks
/* CChildDialog class is inherited from CDialog */
CChildDialog *m_pDialog = NULL;
// Invoking the Dialog
m_pDialog = new CChildDialog();
if (m_pDialog != NULL)
{
BOOL ret = m_pDialog->Create(IDD_CHILDDIALOG, this);
if (!ret) //Create failed.
{
AfxMessageBox(_T("Error creating Dialog"));
}
m_pDialog->ShowWindow(SW_SHOW);
}
// Delete the dialog once done
delete m_pDialog;
Use CDialog::Create and then use CDialog::ShowWindow. You now have a modeless dialog box.
You can call CDialog::Create and CWnd::ShowWindow like the others have suggested.
Also, keep in mind your dialog will be destroyed right after its creation if it is stored in a local variable.
In this case I find it most convenient to let it self-delete itself to handle the cleanup.
Often it's considered bad form to make "implicit" memory freeing from within a class, and not by what it created it, but I usually make exceptions for modeless dialog boxes.
That is;
Calling code:
#include "MyDialog.h"
void CMyApp::OpenDialog()
{
CMyDialog* pDlg = new CMyDialog(this);
if (pDlg->Create(IDD_MYDIALOG, this))
pDlg->ShowWindow(SW_SHOWNORMAL);
else
delete pDlg;
}
Dialog code:
void CMapBasicDlg::OnDestroy()
{
CDialog::OnDestroy();
delete this; // Shown as non-modal, we'll clean up ourselves
}
You need to call CDialog::Create instead. You will need to call DestroyWindow when you are finished with the dialog. You might also need to pass dialog messages onto the object but I can't remember if MFC handles this for you or not.
DoModal is blocking. You have to create your dialog on the heap or make it a member of your class (this is important), call Create then call ShowWindow.