Parent Window is NULL in CFormView (MFC) - c++

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.

Related

CDHtmlDialog - make it modal?

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.

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?

Creating a control in MFC application

How to Create a Button using CButton class inside the Client area. I have just tried but the control is not getting displayed in the client area.
Code i used to create button
void CcontrolsView::OnDraw(CDC* pDC)
{
CcontrolsDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CButton cb;
cb.Create(BS_PUSHBUTTON,CRect(20,20,100,100),this,10000);
// TODO: add draw code for native data here
}
1 Don't do it in the OnDraw() method. Add a message handler for WM_CREATE in there, and instead do it in there.
2 Don't use a stack based object to create the button. I would suggest adding a CButton member to your view class called m_Button (or whatever).
In your CcontrolsView::OnCreate() method add code like:
m_Button.Create(BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD,CRect(20,20,100,100),this,10000);
You need to construct a new CButton, then add it to the dialog by setting its parent or owner (I forget which - set both!) and other properties like a sensible position, and then call ShowWindow(SW_SHOW) on it.

CMFCButton::SetToolTip(str) not work in OnInitDialog() and

I want my CMFCButton to show tooltip when mouse over.
It doesn't work if I use SetToolTip() method in OnInitDialog
CMFCButton* bt = ((CMFCButton*)GetDlgItem(IDC_MFCBUTTON1));
bt->SetTooltip(_T("tooltip"));
BUT it does work if I put this code in message handle function like another button's click handle.
What I want is that the CMFCButton could show tooltip when the dialog is created, where should I put these code?
========================
By the way, The tooltip text I set in the Property view does not work for most time.
I just derived a class
class CMyButton : public CMFCButton
{
public:
void SetDelayFullTextTooltipSet(bool DelayFullTextTooltipSet)
{
m_bDelayFullTextTooltipSet = DelayFullTextTooltipSet;
}
};
Instead of a CMFCButton variable on the Dialog class I use the button, I now have a CMyButton.
And in the OnInitDialog, after the SetTooltip call, I do
button.SetDelayFullTextTooltipSet(FALSE);
Have you called the base class' OnInitDialog()? The main point is that the control needs to be created before you call SetToolTip() on it. Step into OnInitDialog() with the debugger and see if m_hWnd of the control has a value at the moment you call SetToolTip().

is there a function in dlg class as getdocument()?

I want to get a doc* in dlg class, and i know in view class we can get doc* like
doc* pdc=getdocument();
But how can i do it in dlg class?
There is no function in CDialog to retrieve a document pointer. To give your dialog access to the document, you can add a pointer or reference to the document as a member variable of the dialog class, and initialise it in the dialog's constructor.
CMyDocument* doc = GetDocument();
CMyDialog dialog(doc);
dialog.DoModal();
MFC's CDialog class does not have built-in CDocument's. You can implement a CFormView that is derived from CView (which are part of the Document/View architecture of MFC), but CFormView is not a dialog. However, CFormView's can hold controls like a dialog - you can actually assign a dialog template to a CFormView.
you can get document from dialog by doing as follows:
CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
CMyProjDoc* pDoc = (CMyProjDoc*)(pFrame->GetActiveDocument());
pDoc->m_item[i].name // use