CDHtmlDialog - make it modal? - c++

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.

Related

Where to initialize a rich edit control on another dialog?

I have an MFC dialog based application that has 2 Dialogs: Main Dialog CMyDlgand Second dialog CMyDlg2.
On the main Dialog I add a Button "Go dialog 2". So I added a handler for the button so that when clicked it pops up the second dialog. Everything works fine But on the second Dialog I have added a Rich Edit Control from toolbox. I Added for it a variable. I also added a class for the second dialog.
Now If I run the Application I get the dialog one and if I pressed "Go to dialog 2" I got what I want. But I need at some point to change the font of the rich edit control but my program crashes.
So I overrided OnInitDialog and inside it do some changes to the control but program crashes. After debugging I found that the handle of rich edit is null?!
So how and where can I change the color or do some initializations to the control?
(I called AfxInitRichEdit2() in OnInitInstance())
BOOL CMyDlg2::OnInitDialog() {
m_richEdit.SetWindowText("Hello there!"); // program crashes because the handle m_richEdit is null.
return TRUE;
}
And this is the handler of button that creates the Dialog2 and that contains the rich edit control:
void CMyDlg::OnBnClickedButton1(){
CMyDlg2 theDlg;
theDlg.DoModal();
// TODO: Add your control notification handler code here
}
If I create the rich edit control programmatically then everything works fine because I create it at OnInitDialog and then it works fine but I need the one that is I added using the wizard toolbox.
*** The thing is that if I write:
m_richEdit.SetWindowText(""); // program crashes but if I wirte:
GetDlgItem(IDC_RICHEDIT221).SetWindowText(""); it works fine?
You probably have the following code inserted by wizard:
void DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_RICHEDIT22, m_richEdit);
}
This tells the dialog to associate m_richEdit with the dialog control IDC_RICHEDIT22. But this association is not performed until the base class method CDialog::OnInitDialog(); is called.
BOOL CMyDlg2::OnInitDialog()
{
//this line should work:
GetDlgItem(IDC_RICHEDIT22)->SetWindowText("Hello");
//this line won't work:
//m_richEdit.SetWindowText("Hello there!"); <- richedit's handle is NULL
//this line will subclass m_richEdit
//plus run other initialization
CDialog::OnInitDialog();
//m_richEdit is ready
m_richEdit.SetWindowText("Hello there!");
return TRUE;
}
It's recommended to put CDialog::OnInitDialog() int the first line, to make sure the initialization is done.
GetDlgItem works because the control IDC_RICHEDIT22 exists in the dialog template and you have a valid dialog handle. You are basically making a simple call based on WinAPI's GetDlgItem:
HWND hedit = ::GetDlgItem(m_hWnd, IDC_RICHEDIT22);
::SetWindowText(hedit, "Hello world");
There is no additional initialization needed.
But m_richEdit is just a C++ object, declared as CRichEditCtrl m_richEdit; The constructor for this C++ class doesn't do much besides setting m_hWnd to NULL.
Once it's associated with a valid window handle, we can begin using its windows methods such as CRichEdit::SetWindowText

Float (or detach) the tabbed CMDIChildWndEx window from CMDIFrameWndEx,any idea?

In visual studio,all opened editor windows are tabbed in the workspace.when you right click one,there is a "float" option in the menu.if you float a window,the window is detached from the tab and you can drag it anywhere and after all you can dock it back to the tab.
i created a test mdi project,it's not a default behavior.
i overrided the ID_FILE_NEW command and followed the OpenDocumentFile routine,never found out where the framework add the newly created child frame window to the tab.
in the OpenDocumentFile routine,i bumped into a CMFCTabCtrl class and there is a AddTab function.
now the AddTab function:
virtual void AddTab(
CWnd* pTabWnd,
LPCTSTR lpszTabLabel,
UINT uiImageId = (UINT)-1,,
BOOL bDetachable = TRUE
);
virtual void AddTab(
CWnd* pTabWnd,
UINT uiResTabLabel,
UINT uiImageId = (UINT)-1,
BOOL bDetachable = TRUE
);
the Remarks:
If pTabWnd points to an object that is not derived from the CDockablePane Class and
if bDetachable is TRUE, the framework automatically creates a wrapper for the pTabWnd object.
The wrapper makes the pTabWnd object detachable.
By default, the wrapper is an instance of the CDockablePaneAdapter Class.
If the functionality offered by the default wrapper is unacceptable,
use the CMFCBaseTabCtrl::SetDockingBarWrapperRTC method to specify a different wrapper.
still no luck.
i did try to on the fly create a CView and attach it to the CDocument and put that CView in a CDockablePane.so i could switch the old tabbed one to the new dockable one. it's not working yet.
So any thoughts about floating the tabbed CMDIChildWndEx window from CMDIFrameWndEx?

MFC - Changing dialog item focus programmatically

I have a Modeless dialog which shows a bunch of buttons; some of these are customized to draw stuff with GDI.
Now, when the user clicks on a customized one under certain conditions, a message box appears to alert user of the error and this is fine.
The problem is that after accepting the Message Box (showed as MB_ICON_ERROR), everywhere I click in the dialog, I always get the error message as if the whole dialog send the message to the customized button and the only way to get rid this is to press tab and give the focus to another control.
This is a strange behaviour and knowing why happens wouldn't be bad, but a simple workaround for now should do the job.
Since the moment that is probably a matter of focus, I've tried to set it on another control (in the owner dialog) by doing:GetDlgItem( IDC_BTN_ANOTHER_BUTTON )->SetFocus();
and then, inside the customized control by adding:KillFocus( NULL );but had no results.
How should I use these functions?
Thanks in advance.
PS: if I comment the AfxMessageBox, the control does not show this bizarre behaviour.
EDITI'll show some code as requested.
// This is where Message Box is popping out. It is effectively inside the dialog code.
void CProfiloSuolaDlg::ProcessLBtnDownGraphProfilo(PNT_2D &p2dPunto)
{
// m_lboxProfiles is a customized CListBox
if(m_lboxProfiles.GetCurSel() == 0)
{
// This profile cannot be modified.
/*
CString strMessage;
strMessage.Format( _T("Default Profile cannot be edited.") );
AfxMessageBox( strMessaggio, MB_ICONERROR );
*/
return;
}
// Selecting a node from sole perimeter.
SelectNodo(p2dPoint);
}
Actually, the message is commented to keep the dialog working.
// This is inside the customization of CButton
void CMyGraphicButton::OnLButtonDown(UINT nFlags, CPoint point)
{
PNT_2D p2dPunto;
CProfiloSuolaDlg* pDlg = (CProfiloSuolaDlg*)GetParent();
m_pVD->MapToViewport(point,p2dPunto);
switch(m_uType)
{
case GRF_SEZIONE:
pDlg->ProcessLBtnDownGraphProfilo(p2dPunto);
break;
case GRF_PERIMETRO:
pDlg->ProcessLBtnDownGraphPerimetro(p2dPunto);
break;
}
CButton::OnLButtonDown(nFlags, point);
}
Since you are handling the button down event in the button handler for the custom control, you don't need to call the base class. Just comment out CButton::OnLButtonDown(nFlags, point).

Embedded dialog in Tab Control cannot work in second dialog, MFC

I have following code which works in the main dialog, but cannot work in the second (or third) dialog. The thing is that I want each page of the tab control can show a embedded dialog, it's similar to property page.
First I create two dialog, IDD_DIALOG1 and IDD_DIALOG2.Then I change the style of them to child and border to None. After that I add CDialog class to each of them.
In my MainDialog.h, I have the following code:
#include "Dialog1.h"
#include "Dialog2.h"
...
public:
CDialog1 m_para1;
CDialog2 m_para2;
CTabCtrl m_TabCtrl;
In my MainDialog.cpp, I use the following code to embed the dialo in the OnInitDialog:
m_TabCtrl.InsertItem(0, _T("TAB1"));
m_TabCtrl.InsertItem(1, _T("TAB2"));
m_para1.Create(IDD_DIALOG1,GetDlgItem(IDD_MAINDIALOG));
m_para2.Create(IDD_DIALOG2,GetDlgItem(IDD_MAINDIALOG));
CRect rs;
m_TabCtrl.GetClientRect(&rs);
rs.top+=37;
rs.bottom+=8;
rs.left+=13;
rs.right+=7;
m_para1.MoveWindow(&rs);
m_para2.MoveWindow(&rs);
m_para1.ShowWindow(TRUE);
m_para2.ShowWindow(FALSE);
m_TabCtrl.SetCurSel(1);
By using this way, It can work in this case. But if I want to use this method in my SecondDialog, the non-main dialog, it cannot work. Can someone help me out? Thanks in advance.
When you create a modeless dialog box, try this:
m_para1.Create(IDD_DIALOG1,&m_TabCtrl);
m_para2.Create(IDD_DIALOG2,&m_TabCtrl);
The second parameter of the Create function is a point to the parent window object (of type CWnd) to which the dialog object belongs. The return type of the GetDlgItem function is HWND.
See following:
http://msdn.microsoft.com/en-us/library/tc46f3be.aspx
http://msdn.microsoft.com/en-us/library/kc6x1ya0.aspx

Parent Window is NULL in CFormView (MFC)

I have a CFormView-derived class that has a button I am trying to call ShowWindow on. However, this call fails because the m_hWnd variable is null. Why is m_hWnd null? The dialog has the child style set in the properties window, and I'm associating the parent CFrameWnd with the form view. This view is intended to be modeless.
Code that creates view:
void CMainFrame::SwitchEditView(CRuntimeClass * pViewClass)
{
context.m_pNewViewClass=pViewClass;
context.m_pCurrentDoc=pDoc;
context.m_pNewDocTemplate=NULL;
context.m_pLastView=NULL;
context.m_pCurrentFrame=this;
m_subSplitter.CreateView(0,1,pViewClass,CSize(0,0), &context); // create new view and add it to the splitter window
}
The constructor for my CFormView-derived class:
CDFAManEditViewProject::CDFAManEditViewProject()
: CFormView(CDFAManEditViewProject::IDD)
{
// c_btnEdit is a CButton MFC control
c_btnEdit.ShowWindow(SW_SHOW); // this call fails on ASSERT(::IsWindow(m_hWnd) )
}
You are trying to access an edit control from the view constructor. But the view window has not been created yet when the constructor runs. That is why you have no m_hWnd and no edit control yet.
Move your initialization of controls into the view's OnInitialUpdate.