I have a VC++ 6.0 MDI project that uses a class derived from CPreviewView to provide some mildly enhanced Print Preview functions. The class is invoked according to the MSDN documentation by calling DoPrintPreview. In Visual Studio 2005 the program asserts in Debug mode at the last line of this fragment from winfrm.cpp:
void CFrameWnd::OnSetPreviewMode(BOOL bPreview, CPrintPreviewState* pState) {
...etc...
if (bPreview)
{
// Entering Print Preview
ASSERT(m_lpfnCloseProc == NULL); // no chaining
m_lpfnCloseProc = pState->lpfnCloseProc;
// show any modeless dialogs, popup windows, float tools, etc
ShowOwnedWindows(FALSE);
// Hide the main pane
HWND hWnd = ::GetDlgItem(m_hWnd, pState->nIDMainPane);
ASSERT(hWnd != NULL); // must be one that we are hiding!
The program asserts because in Visual Studio 2005 the handle returned by ::GetDlgItem is NULL. If I ignore the assertion the program continues normally. I have checked our project's behaviour under the same conditions on Visual C++ 6.0 and the ::GetDlgItem function returns a valid window handle. In Release mode the assertion is disregarded and the program behaves as expected.
Is there a fix/workaround for this issue

CFrameWnd::OnSetPreviewMode ASSERTs in VC 2005 but not VC 6.0
NKovner
You can't modify the MFC sources without recompiling the MFC libraries, and I'm not really sure that this is something Microsoft really supports. You could have found a bug in MFC however, and if you can get it into a reproable case to submit the bug, you ought to do that so that the bug can get fixed in SP1.
I'd recommend looking for a way to workaround the problem. If you can break down the VC6 behavior in terms of a sequence of Win32 API calls (use m_hWnd on the Windows APIs, e.g. GetDlgItem), then you ought to be able to make those calls in your VS2005 version.
Brian
Asif fattah
Show us the call stack.
What ID (pState->nIDMain) is searched for in VC6 and VC2005
forwheeler
Fixed with the assistance of Microsoft
assumption in VC6 + assumption in my software = assertion
Thanks to everyone for their input
Omer TR
It doesn't make much sense to ask why m_hWnd "points" to a CView instead of the frame window. The member can only belong to class (a certain CWnd derived class). I think you need to be clearer in your observations. If the organization of your app's windows have changed in VS2005 such that a certain window ID is no longer a child of a certain Window type, then you need to confirm this (I don't see a confirmation here, only some additional confusion.) Then use the debugger to see how that certain child got created by its certain parent under VC6, and determine what's different by debugging the same under VS2005.
Note that HWND values will change between runs, but the relationships (parentage) and IDs should not.
Brian
MMTech1
Can anyone help with this
I've tested it using the default implementation CView::OnFilePrintPreview and the assertion in CFrameWnd::OnSetPreviewMode is the same.
I've tried different IDs for CPrintPreviewState* pState->nIDMainPane but ::GetDlgItem (m_hWnd, pState->nIDMainPane) always returns NULL.
Any suggestions are very welcome.
Marcus2
Call stack as follows:
mfc80d.dll!CFrameWnd::OnSetPreviewMode(int bPreview=1, CPrintPreviewState * pState=0x01738f40) Line 1882 + 0x19 bytes C++
mfc80d.dll!CView::DoPrintPreview(unsigned int nIDResource=236, CView * pPrintView=0x016f2838, CRuntimeClass * pPreviewViewClass=0x0060fb8c, CPrintPreviewState * pState=0x01738f40) Line 103 C++
WS98.exe!CWS98ProgramView::OnPrintPreview() Line 2899 + 0x1b bytes C++
mfc80d.dll!_AfxDispatchCmdMsg(CCmdTarget * pTarget=0x016f2838, unsigned int nID=32848, int nCode=0, void (void)* pfn=0x004a7ad4, void * pExtra=0x00000000, unsigned int nSig=56, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 82 C++
mfc80d.dll!CCmdTarget::OnCmdMsg(unsigned int nID=32848, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 381 + 0x27 bytes C++
mfc80d.dll!CView::OnCmdMsg(unsigned int nID=32848, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 158 + 0x18 bytes C++
mfc80d.dll!CFrameWnd::OnCmdMsg(unsigned int nID=32848, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000) Line 887 + 0x23 bytes C++
mfc80d.dll!CWnd::OnCommand(unsigned int wParam=32848, long lParam=0) Line 2300 C++
mfc80d.dll!CFrameWnd::OnCommand(unsigned int wParam=32848, long lParam=0) Line 318 C++
mfc80d.dll!CWnd::OnWndMsg(unsigned int message=273, unsigned int wParam=32848, long lParam=0, long * pResult=0x0012fa34) Line 1755 + 0x1e bytes C++
mfc80d.dll!CWnd::WindowProc(unsigned int message=273, unsigned int wParam=32848, long lParam=0) Line 1741 + 0x20 bytes C++
mfc80d.dll!AfxCallWndProc(CWnd * pWnd=0x016f0b10, HWND__ * hWnd=0x000908a2, unsigned int nMsg=273, unsigned int wParam=32848, long lParam=0) Line 240 + 0x1c bytes C++
mfc80d.dll!CMDIFrameWnd::OnCommand(unsigned int wParam=32848, long lParam=0) Line 48 + 0x23 bytes C++
WS98.exe!CMainFrame::OnCommand(unsigned int wParam=32848, long lParam=0) Line 699 C++
mfc80d.dll!CWnd::OnWndMsg(unsigned int message=273, unsigned int wParam=32848, long lParam=0, long * pResult=0x0012fc94) Line 1755 + 0x1e bytes C++
mfc80d.dll!CWnd::WindowProc(unsigned int message=273, unsigned int wParam=32848, long lParam=0) Line 1741 + 0x20 bytes C++
mfc80d.dll!AfxCallWndProc(CWnd * pWnd=0x014b0300, HWND__ * hWnd=0x00280592, unsigned int nMsg=273, unsigned int wParam=32848, long lParam=0) Line 240 + 0x1c bytes C++
mfc80d.dll!AfxWndProc(HWND__ * hWnd=0x00280592, unsigned int nMsg=273, unsigned int wParam=32848, long lParam=0) Line 389 C++
mfc80d.dll!AfxWndProcBase(HWND__ * hWnd=0x00280592, unsigned int nMsg=273, unsigned int wParam=32848, long lParam=0) Line 407 + 0x15 bytes C++
The ID is 59648 (e900h) in both VC 6 & VC 2005
Jonathan Finkbiner
I'll try and illustrate the hierarchy:
VC6:
Handle 0002110A "My App"
The m_hWnd value of CFrameWnd is 0002110A - My App
VS2005:
Handle 000606DC "My App"
The m_hWnd value of CFrameWnd is 000906B2 - My Frame
It seems strange in VC6 that the m_hWnd value is that of the top-level window
The relationships between the windows hasn't changed - I only needed to address some deprecated string-handling routines to get the project to build and run on VS2005.
Werner_001
I think I have found the problem - there are some subtle differences in Microsoft's viewprev.cpp and winfrm.cpp between VC6 and VS2005.
My question now is: how do I modify viewprev.cpp and winfrm.cpp and use the modified versions in my project instead of the originals
J B Li
Thanks for your great advice, Brian. I used Spy++ and it revealed a difference but I'm not sure what it means.
In VC6, m_hWnd is the handle of my project's top-level window, and the ID 59648/E900/AFX_IDW_PANE_FIRST is, predictably, the ID of an MDI client which is the container for the CView I'm trying to Preview.
In VS2005, m_hWnd is the handle of the CView I'm trying to Preview
The MDI client container ID is still AFX_IDW_PANE_FIRST but of course the CView I'm previewing doesn't have any items with the AFX_IDW_PANE_FIRST identifier.
My problem now is why (in VS2005) the m_hWnd handle in CFrameWnd::OnSetPreviewMode points to the CView instead of the top-level window as it does in VC6
Mauro Regio
guardian653
Hey,
I am having this exact same problem converting a VS6 project to 2005. I can see that the view needs the AFX_IDW_PANE_FIRST ID for the print preview, but I can't seem to accomplish it correctly. If you have the steps that you went through to fix this they would be much appreciated.
Thanks,
BC.
old_nick12
I don't think you're going to get an good answer, so you're going to have to dig in a bit more.
Use Spy++ to gather more information. Set a breakpoint on the line for GetDlgItem, get the value of m_hWnd and pState->nIDMainPane.
Then use Spy++ to locate the m_hWnd (there is a Find Window tool). Then see if it has a child with the aforementioned ID. Is it there. Do you see the pane, and it has a different ID
Do this in VC6 and compare.
These might be clues that can lead you back to the cause of the problem. If you end up deciding there a bug in MFC 8.0, then you can submit a bug report.
Brian
ffederico
Basics: I have a VC6 MDI project with multiple views of every document. The views are inter-related (like Property Pages) but have the functionality of CFormView-derived views. Some of them have multiple panes/splitters. It sounds like a nightmare but hey it is the perfect solution for the application and has sold all over the world since 1998.
The problem I experienced was related to the windows that are hidden when the print preview window starts.
VC6 has a somewhat unsubtle approach and hides every window within the main frame. This causes some interesting effects within the main frame which I am sure you are all aware of.
VS2005 hides only the view that is being previewed.
In VC6, CView::DoPrintPreview uses AfxGetMainWnd () as the starting point for hiding windows, but VS2005 uses GetParentFrame (), and only uses AfxMainWnd () if GetParentFrame () isn't a CFrameWnd. CFrameWnd::OnSetPreviewMode () then hides the DlgItem of this window that has the ID of AFX_IDW_PANE_FIRST.
To try and bring some kind of order to my multi-viewed, multi-document project, I had inserted a CWnd-derived 'container' class within CChildFrame to provide a tabbed-window effect for the multiple views on each document.
I had assigned an ID to the container which wasn't AFX_IDW_PANE_FIRST.
In VC6, this didn't matter because of its 'top down' approach to hiding windows. But VS2005's more elegant approach was torpedoed by my container window.
BC - if your VC6 CChildFrame is 'plain vanilla' then your problem is not the same as mine, but I simply changed the ID of my container to AFX_IDW_PANE_FIRST and now it's OK. Although it works in my project I'm a somewhat cautious about suggesting that this is the 'answer' but all the same, feel free to post if there are any specifics I may be able to help you with.
AlbertoD
What was the assumption you've made that caused this assertion, and how did you discover this
(Giving answers is part of the civic duty here... free help, free answers
)
Brian