Link to home
Start Free TrialLog in
Avatar of captainkirk
captainkirk

asked on

CFormView and modeless dialogs...

I tried to create a modeless dialog as a child of a CFormView derived class and got an ASSERT in wincore.cpp:


#ifndef _AFX_NO_OCC_SUPPORT
BOOL CWnd::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO*)
{
      ASSERT(FALSE); // this class doesn't support dialog creation
      return FALSE;
}
#endif

Is it possible to do it? I'd like to achieve the effect of overlaying different dialog templates over the same form view -- the dialog template will change in the view based upon a user selection. I suppose I could create different view classes, but I'm trying to incorporate legacy code from a dialog-based app.

thanks, all...
Avatar of mikeblas
mikeblas


Anyway, it's certainly possible to create a modeless dialog as a child of a CFormView. You've done something wrong, so we need to figure out what that is.

To that end, please provide a stack trace leading ot the CWnd::SetOccDialogInfo() call where you say you've asserted.

Also, please let us know which version of MFC you're using.  Show some source code, too--how are you creating the involved windows?

..B ekiM

Avatar of captainkirk

ASKER

I'm using MFC version 6.00 (as defined in AFXVER_.H)

Here's the stack trace: (I installed symbols for debug, but somehow I can't trace into wincore.cpp)

The assert dialog points to wincore.cpp line 3535 which is the first assert in the function SetOccDialogInfo():

MFC42D! 5f43240e()
MFC42D! 5f433e68()
MFC42D! 5f433d40()
CPageDialog::Create(const char * 0x0000010d, CWnd * 0x0115f520 {CSystemStateInfoFormView hWnd=0x0003075e}, CRect {top=41 bottom=421 left=150 right=707}, unsigned int 0, unsigned long 1342177280) line 49 + 16 bytes
CSystemStateInfoFormView::OnActivateItem(tagNMHDR * 0x0012ee44, long * 0x0012eac0) line 295 + 88 bytes
MFC42D! 5f437616()
MFC42D! 5f437c2b()
MFC42D! 5f446045()
MFC42D! 5f42fc71()
MFC42D! 5f42edb0()
MFC42D! 5f42ece8()
MFC42D! 5f42c889()
MFC42D! 5f42cd25()
MFC42D! 5f4905fd()
COXLayoutManager::LayoutManagerProc(HWND__ * 0x0003075e, unsigned int 78, unsigned int 1095, long 1240644) line 873 + 24 bytes
COXLayoutManager::GlobalLayoutManagerProc(HWND__ * 0x0003075e, unsigned int 78, unsigned int 1095, long 1240644) line 843
USER32! 77e71ff1()
USER32! 77e725bc()
MFC42D! 5f4817c4()
COXShortcutBar::SendSHBNotification(_tagNMSHORTCUTBAR * 0x0012ee44) line 9234 + 23 bytes
COXSHBListCtrl::SendSHBNotification(_tagNMSHORTCUTBAR * 0x0012ee44) line 3734 + 15 bytes
COXSHBListCtrl::ActivateItem(int 0) line 3869 + 12 bytes
CSystemStateInfoFormView::OnInitialUpdate() line 238
CMainFrame::CreateView(int 14, CWnd * 0x002f7348 {CTVGSplitterWnd hWnd=???}, CCreateContext * 0x0012f0fc) line 413 + 16 bytes
CMainFrame::ChangeView(int 14) line 423 + 26 bytes
CMainFrame::OnNotify(unsigned int 101, long 1244240, long * 0x0012f274) line 376
MFC42D! 5f42edb0()
MFC42D! 5f42ece8()
COXMenuBarFrame<CFrameWnd,CDockBar>::WindowProc(unsigned int 78, unsigned int 101, long 1244240) line 1291
MFC42D! 5f42c889()
MFC42D! 5f42cd25()
MFC42D! 5f4905fd()
COXBitmapMenuOrganizer::MenuOrganizerProc(HWND__ * 0x00010730, unsigned int 78, unsigned int 101, long 1244240) line 832 + 24 bytes
COXBitmapMenuOrganizer::GlobalMenuOrganizerProc(HWND__ * 0x00010730, unsigned int 78, unsigned int 101, long 1244240) line 810
USER32! 77e727fe()
USER32! 77e72889()
COXHookWnd::WindowProc(unsigned int 78, unsigned int 101, long 1244240) line 273 + 89 bytes
COXCaptionPainter::WindowProc(unsigned int 78, unsigned int 101, long 1244240) line 733 + 20 bytes
HookWndProc(HWND__ * 0x00010730, unsigned int 78, unsigned int 101, long 1244240) line 330 + 25 bytes
USER32! 77e719d0()
USER32! 77e71982()
NTDLL! 77f763a3()
MFC42D! 5f483080()
COpConView::OnNotify(unsigned int 101, long 1244240, long * 0x0012f974) line 447
MFC42D! 5f42edb0()
MFC42D! 5f42ece8()
MFC42D! 5f42c889()
MFC42D! 5f42cd25()
MFC42D! 5f4905fd()
USER32! 77e71ff1()
USER32! 77e725bc()
MFC42D! 5f4817c4()
COXShortcutBar::SendSHBNotification(_tagNMSHORTCUTBAR * 0x0012fc50) line 9234 + 23 bytes
COXSHBListCtrl::SendSHBNotification(_tagNMSHORTCUTBAR * 0x0012fc50) line 3734 + 15 bytes
COXSHBListCtrl::OnLButtonUp(unsigned int 0, CPoint {x=62 y=152}) line 1325
MFC42D! 5f42f818()
MFC42D! 5f42ece8()
MFC42D! 5f42c889()
MFC42D! 5f42cd25()
MFC42D! 5f4905fd()
USER32! 77e71820()


1) The form view is created as the right pane of a splitter window

2) The form view creates a CPageDialog object as a result of clicking a custom button control:

void CSystemStateInfoFormView::OnActivateItem(NMHDR* pNotifyStruct, LRESULT* result)
{
      LPNMSHORTCUTBAR pNMSHB = (LPNMSHORTCUTBAR)pNotifyStruct;
      ASSERT(pNMSHB != NULL);

      if(pNMSHB->nItem != m_nActivePage && pNMSHB->nItem >= 0 && 
         pNMSHB->nItem < m_arrPages.GetSize())
      {
            CPageDialog* pPageDlg = NULL;
            
            if(m_nActivePage != -1)
            {
                  pPageDlg = m_arrPages[m_nActivePage].pPageDlg;
                  ASSERT(pPageDlg != NULL);
                  ASSERT(::IsWindow(pPageDlg->GetSafeHwnd()));
                  pPageDlg->ShowWindow(SW_HIDE);
            } // end if

            CRect rectFrame = GetPageRect();

            pPageDlg = m_arrPages[pNMSHB->nItem].pPageDlg;
            ASSERT(pPageDlg != NULL);
            
            if(::IsWindow(pPageDlg->GetSafeHwnd()))
            {
                  pPageDlg->ShowWindow(SW_SHOW);
                  pPageDlg->MoveWindow(rectFrame);
            } // end if
            else
            {
                  VERIFY(pPageDlg->Create(MAKEINTRESOURCE(m_arrPages[pNMSHB->nItem].nTemplateID),
                                                      this,
                                                      rectFrame,
                                                      pNMSHB->nItem));
                  
                  ASSERT(::IsWindow(pPageDlg->GetSafeHwnd()));
            } // end else

            pPageDlg->SetFocus();
            m_btnRefresh.EnableWindow(pPageDlg->IsRefreshAvailable());
            m_nActivePage = pNMSHB->nItem;
      } // end if

      ASSERT(m_shb.GetGroupListCtrl(pNMSHB->hGroup) != NULL);
      CString sTopic = m_shb.GetGroupListCtrl(pNMSHB->hGroup)->GetItemText(pNMSHB->nItem, 0);
      m_ctlTopic.SetWindowText(sTopic);

      *result = 0;
} // end OnActivateItem()







BOOL CPageDialog::Create(LPCTSTR lpszTemplateName, CWnd* pParentWnd, CRect rect,
                                     UINT nID, DWORD dwStyle/*=WS_VISIBLE|WS_CHILD*/)
{
      ASSERT(pParentWnd!=NULL);
      ASSERT(lpszTemplateName!=NULL);

      // initialize common controls
      VERIFY(AfxDeferRegisterClass(AFX_WNDCOMMCTLS_REG));

      // call PreCreateWindow to get prefered extended style
      CREATESTRUCT cs={ 0 };
      cs.style=dwStyle;
      if(!PreCreateWindow(cs))
            return FALSE;

      // create a modeless dialog
      if (!CreateDlg(lpszTemplateName, pParentWnd))
            return FALSE;

      // we use the style from the template - but make sure that
      //  the WS_BORDER bit is correct
      // the WS_BORDER bit will be whatever is in dwRequestedStyle
      ModifyStyle(WS_BORDER|WS_CAPTION,(cs.style&(WS_BORDER|WS_CAPTION))|WS_CHILD);
      ModifyStyleEx(WS_EX_CLIENTEDGE,(cs.dwExStyle&WS_EX_CLIENTEDGE));

      SetDlgCtrlID(nID);

      // initialize controls etc
      if (!ExecuteDlgInit(lpszTemplateName))
            return FALSE;

      OnInitDialog();

      // force the size requested
      SetWindowPos(NULL, rect.left, rect.top,
            rect.right - rect.left, rect.bottom - rect.top,
            SWP_NOZORDER|SWP_NOACTIVATE);

      // make visible if requested
      if (dwStyle & WS_VISIBLE)
            ShowWindow(SW_NORMAL);

      return TRUE;
}


The CreateDlg() call asserts...

This project is quite large to post all of the code, but if you need any more pieces, I'll try to ferret out the needed stuff...

Thanks...
> Here's the stack trace: (I installed symbols for debug,
 > but somehow I can't trace into wincore.cpp)

You need to get working symbols for the trace to be meaningful.  (I mean, I can decode it as it is, but that's far too much work to do for free.)

..B ekiM
Adjusted points from 150 to 200
Mike - I followed the instructions for installing debug symbols for NT SP5, but not all symbols are available. The documentation only showed procedure for earlier service packs, and the EXE used to install them were named differently, so I made an assumption about how to proceed based upon directory/exe names in the service pack install. Could you point me to a complete set of instructions for getting symbols set up properly for NT SP5??? I'm upping the points for you as well...

I mean, you can't change the assoziated dialog template of a form view at runtime. You should create a form view for each dialog version. For displaying another dialog you can use code similar to this:
CMainFrame *mf = (CMainFrame *)AfxGetMainWnd();
CView *currentView = mf->GetActiveView();
currentView->DestroyWindow();
mf->CreateView(...);
I'm not changing the template of the form view, just attempting to create a child of the form view which is modeless and will visually obscure the client area of the form view.

I can't seem to get a breakpoint set in wincore.cpp for some reason, although I have followed all of the instructions as to getting NT SP5 debug symbols set up...
I don't believe the NT symbols include the MFC symbols. Your problem is that you have an MFC42D.DLL that doesn't match your MFC42D.PDB file.  They should be from the exact same build and the exact same date, and they're not.

(You probably also have mismatches for the MFCO42D.*, MFCD42D.*, MFCS42D.*, and MFCN42D.* files.)

..B ekiM

Mike - I think you're right, and I have been trying to get them sync'd up by doing total reinstalls of VC++ 6.0 - this hasn't solved the problem, though... the IDE used to ask where certain PDB files were located and now I can't get that to happen. Is there a way to force VC++ to look in a particular place for the MFC debug info???
Mike - I think I've finally got the symbol thing straightened out - here's a more readable stack trace:

CWnd::SetOccDialogInfo(_AFX_OCC_DIALOG_INFO * 0x0012e740) line 3535 + 28 bytes
CWnd::CreateDlgIndirect(const DLGTEMPLATE * 0x00622988, CWnd * 0x0115f520 {CSystemStateInfoFormView hWnd=0x001c0158}, HINSTANCE__ * 0x00400000) line 284 + 18 bytes
CWnd::CreateDlg(const char * 0x0000010d, CWnd * 0x0115f520 {CSystemStateInfoFormView hWnd=0x001c0158}) line 238 + 20 bytes
CPageDialog::Create(const char * 0x0000010d, CWnd * 0x0115f520 {CSystemStateInfoFormView hWnd=0x001c0158}, CRect {top=41 bottom=421 left=150 right=707}, unsigned int 0, unsigned long 1342177280) line 49 + 16 bytes
CSystemStateInfoFormView::OnActivateItem(tagNMHDR * 0x0012ee44, long * 0x0012eac0) line 295 + 88 bytes
_AfxDispatchCmdMsg(CCmdTarget * 0x0115f520 {CSystemStateInfoFormView hWnd=0x001c0158}, unsigned int 1095, int 1152, void (void)* 0x00401280 CSystemStateInfoFormView::OnActivateItem(struct tagNMHDR *,long *), void * 0x0012e9d4, unsigned int 38, AFX_CMDHANDLERINFO * 0x00000000) line 118
CCmdTarget::OnCmdMsg(unsigned int 1095, int 1152, void * 0x0012e9d4, AFX_CMDHANDLERINFO * 0x00000000) line 302 + 39 bytes
CView::OnCmdMsg(unsigned int 1095, int 5112960, void * 0x0012e9d4, AFX_CMDHANDLERINFO * 0x00000000) line 159 + 24 bytes
CWnd::OnNotify(unsigned int 1095, long 1240644, long * 0x0012eac0) line 2114
CWnd::OnWndMsg(unsigned int 78, unsigned int 1095, long 1240644, long * 0x0012eb04) line 1609 + 40 bytes
CWnd::WindowProc(unsigned int 78, unsigned int 1095, long 1240644) line 1585 + 30 bytes
AfxCallWndProc(CWnd * 0x0115f520 {CSystemStateInfoFormView hWnd=0x001c0158}, HWND__ * 0x001c0158, unsigned int 78, unsigned int 1095, long 1240644) line 215 + 26 bytes
AfxWndProc(HWND__ * 0x001c0158, unsigned int 78, unsigned int 1095, long 1240644) line 368
AfxWndProcBase(HWND__ * 0x001c0158, unsigned int 78, unsigned int 1095, long 1240644) line 220 + 21 bytes
COXLayoutManager::LayoutManagerProc(HWND__ * 0x001c0158, unsigned int 78, unsigned int 1095, long 1240644) line 873 + 24 bytes
COXLayoutManager::GlobalLayoutManagerProc(HWND__ * 0x001c0158, unsigned int 78, unsigned int 1095, long 1240644) line 843
USER32! SendMessageWorker@20 + 154 bytes
USER32! SendMessageA@16 + 71 bytes
CWnd::SendMessageA(unsigned int 78, unsigned int 1095, long 1240644) line 39 + 75 bytes
COXShortcutBar::SendSHBNotification(_tagNMSHORTCUTBAR * 0x0012ee44) line 9234 + 23 bytes
COXSHBListCtrl::SendSHBNotification(_tagNMSHORTCUTBAR * 0x0012ee44) line 3734 + 15 bytes
COXSHBListCtrl::ActivateItem(int 0) line 3869 + 12 bytes
CSystemStateInfoFormView::OnInitialUpdate() line 238
CMainFrame::CreateView(int 14, CWnd * 0x002f7348 {CTVGSplitterWnd hWnd=???}, CCreateContext * 0x0012f0fc) line 413 + 16 bytes
CMainFrame::ChangeView(int 14) line 423 + 26 bytes
CMainFrame::OnNotify(unsigned int 101, long 1244240, long * 0x0012f274) line 376
CWnd::OnWndMsg(unsigned int 78, unsigned int 101, long 1244240, long * 0x0012f2b8) line 1609 + 40 bytes
CWnd::WindowProc(unsigned int 78, unsigned int 101, long 1244240) line 1585 + 30 bytes
COXMenuBarFrame<CFrameWnd,CDockBar>::WindowProc(unsigned int 78, unsigned int 101, long 1244240) line 1291
AfxCallWndProc(CWnd * 0x002f6df0 {CMainFrame hWnd=???}, HWND__ * 0x00030216, unsigned int 78, unsigned int 101, long 1244240) line 215 + 26 bytes
AfxWndProc(HWND__ * 0x00030216, unsigned int 78, unsigned int 101, long 1244240) line 368
AfxWndProcBase(HWND__ * 0x00030216, unsigned int 78, unsigned int 101, long 1244240) line 220 + 21 bytes
COXBitmapMenuOrganizer::MenuOrganizerProc(HWND__ * 0x00030216, unsigned int 78, unsigned int 101, long 1244240) line 832 + 24 bytes
COXBitmapMenuOrganizer::GlobalMenuOrganizerProc(HWND__ * 0x00030216, unsigned int 78, unsigned int 101, long 1244240) line 810
USER32! CallWindowProcAorW@24 + 41 bytes
USER32! CallWindowProcA@20 + 25 bytes
COXHookWnd::WindowProc(unsigned int 78, unsigned int 101, long 1244240) line 273 + 89 bytes
COXCaptionPainter::WindowProc(unsigned int 78, unsigned int 101, long 1244240) line 733 + 20 bytes
HookWndProc(HWND__ * 0x00030216, unsigned int 78, unsigned int 101, long 1244240) line 330 + 25 bytes
USER32! DispatchClientMessage@20 + 42 bytes
USER32! __fnDWORD@4 + 36 bytes
NTDLL! KiUserCallbackDispatcher@12 + 19 bytes
OPCON! @ILT+5310(?HookWndProc@@YGJPAUHWND__@@IIJ@Z) address 0x004024c3
USER32! SendNotifyMessageA@16 + 106 bytes

It looks like it's trying to create OLE controls in the dialog, of which there are none. Other form views in the application are intended to be containers, however. Maybe this will help shed a little light...

thanks...
Mike - here's another tidbit:  it seems that calling AfxEnableControlContainer() is the culprit. The next question is, as mentioned earlier, some of the form views contain ActiveX controls and others do not. In the present case, control containment seem to foul things up. It is recommended that AfxEnableControlContainer() be called in the InitInstance() function of the app. Is it possible to enable containment for the selected views and disable it for the others??
can you send the entire code so that i can look into the code and solve ur problem..
Mike - any ideas about previous comment??
What class is CPageDialog derived from?



It's derived directly from CWnd...
ASKER CERTIFIED SOLUTION
Avatar of cdepetris
cdepetris

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
cdpetris - the code is legacy stuff from a third party, designed to work in a dialog-based app, but I can try your suggestion. I'll get back to you...
cdpetris - I still haven't gotten back to this issue because of higher priority items on the plate, but I'm confident that the suggestion will work and so I'll go ahead and give you the points... Mike B: if you're still looking in on this one, I'll post another question to give you some points as well for the effort...

thanks, guys...
> Add the virtual function SetOccDialogInfo to your
 > CPageDialog class and return TRUE), or derive CPageDialog
 > from CDialog (Is there a reason you didn't?).

Err, that strikes me as a bit of a hack.  Can you explain _why_ you recommend doing that?

..B ekiM
It is somewhat of a hack, as it is using an undocumented virtual function from CWnd. I personally would have derived my class from CDialog, as I alluded to in the comment. I however do not know the reason that CWnd was used as a base class, and since by doing that he would not be able to use ActiveX controls on his dialogs anyway, the solution of overriding SetOccDialogInfo (undocumented as it may be) was a possible solution to his problem. If you disagree, I would like to know.

Chris
It is somewhat of a hack, as it is using an undocumented virtual function from CWnd. I personally would have derived my class from CDialog, as I alluded to in the comment. I however do not know the reason that CWnd was used as a base class, and since by doing that he would not be able to use ActiveX controls on his dialogs anyway, the solution of overriding SetOccDialogInfo (undocumented as it may be) was a possible solution to his problem. If you disagree, I would like to know.

Chris
This code is from a third party company that I am attempting to reuse within the formview - although now I'm looking atr WMI to do the same thing and may scrap this altogether...