Microsoft KB Archive/230377

= BUG: Find/Replace Assertions in an MDI MFC Application with CRichEditView-based Views =

Article ID: 230377

Article Last Modified on 11/21/2006

-

APPLIES TO

 Microsoft Foundation Class Library 4.2, when used with:  Microsoft Visual C++ 5.0 Enterprise Edition

 Microsoft Visual C++ 5.0 Professional Edition

 Microsoft Visual C++ 6.0 Enterprise Edition

 Microsoft Visual C++ 6.0 Professional Edition</li></ul>

 Microsoft Visual C++ 6.0 Standard Edition</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q230377

<div class="symptoms_section">

SYMPTOMS
When you use a Find/Replace dialog box in a multiple document interface (MDI) application with CRichEditView-based views, you may receive one of the following messages:

Debug Assertion Failed! Program: [Your.exe]. File: viewrich.cpp. Line: 1674.

User breakpoint called from code at [SomeAddress]. (CRichEditView::AssertValid will be on the stack)

<div class="cause_section">

CAUSE
Dialog box ownership is established statically when the dialog box is created. The view that handles the initial ID_EDIT_FIND or ID_EDIT_REPLACE command becomes the owner of the dialog box. The owner is the window that receives FINDMSGSTRING notifications.

When a Find/Replace dialog box survives its owner, all subsequent notifications are directed to a nonexistent window. The application is not aware that the dialog has been dismissed, which results in the assertions.

<div class="resolution_section">

RESOLUTION
WARNING: This resolution uses undocumented implementation features of the Microsoft Foundation Classes (MFC). Future versions of MFC may break programs that use this resolution.

To resolve this problem, you need to do two things:
 * Override the OnActivateView method to update the dialog box owner dynamically whenever a CRichEditView view becomes active.
 * Provide a WM_DESTROY handler to dismiss the dialog box.

See the sample code in the "More Information" section below for details.

<div class="status_section">

STATUS
Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.

<div class="moreinformation_section">

Steps to Reproduce Behavior
To reproduce this problem, perform the following steps:
 * 1) In Visual C++, use AppWizard to create a default MDI application. In the last AppWizard step, specify CRichEditView as the base class for the view.
 * 2) Compile and run the application.
 * 3) Open a Find/Replace dialog box, close the child frame that contains the dialog box's owner, close the dialog box, and then create a new child frame. You should receive an assertion.

-or-

Open a Find/Replace dialog box, close the child frame that contains the dialog box's owner, create a new child frame, and then close the dialog box. You should receive an assertion.

-or-

Open a Find/Replace dialog box, close the child frame that contains the dialog box's owner, create a new child frame, and then attempt to execute a search in the new frame. No search is executed.

Steps to Resolve the Problem
The following sample code illustrates how to override the OnActivateView method for CRichEditView-derived classes, and replace the WM_DESTROY handler:
 * 1) include <..\Src\AfxImpl.h>

void CRefindView::OnActivateView(BOOL bActivate, CView* pActivateView,                                 CView* pDeactiveView) { // Set owner of Find/Replace dialog box. _AFX_RICHEDIT_STATE* pEditState = _afxRichEditState; if (pEditState && pEditState->pFindReplaceDlg && (pActivateView == this)) pEditState->pFindReplaceDlg->m_fr.hwndOwner = m_hWnd;

CRichEditView::OnActivateView(bActivate, pActivateView, pDeactiveView); }

void CRefindView::OnDestroy { // Deactivate the item on destruction; // this is important when a splitter view is used. // CRichEditView::OnDestroy; COleClientItem* pActiveItem = GetDocument->GetInPlaceActiveItem(this); if (pActiveItem != NULL && pActiveItem->GetActiveView == this) {   pActiveItem->Deactivate; ASSERT(GetDocument->GetInPlaceActiveItem(this) == NULL); }

// Close Find/Replace dialog box if this is the last CRichEditView. _AFX_RICHEDIT_STATE* pEditState = _afxRichEditState; if (pEditState && pEditState->pFindReplaceDlg) {   CWinApp* pApp = AfxGetApp; // If there is no doc manager, there are no templates. if (pApp->m_pDocManager != NULL) {     // Walk all templates. CDocTemplate* pTemplate; POSITION pos = pApp->m_pDocManager->GetFirstDocTemplatePosition; while (pos != NULL) {       pTemplate = pApp->m_pDocManager->GetNextDocTemplate(pos); ASSERT(pTemplate);

// Walk all documents in the template. POSITION pos2 = pTemplate->GetFirstDocPosition; while (pos2) {          CDocument* pDoc = pTemplate->GetNextDoc(pos2); ASSERT(pDoc);

// Walk all views in the document. POSITION pos3 = pDoc->GetFirstViewPosition; while (pos3 != NULL) {            CView* pView = pDoc->GetNextView(pos3); ASSERT(pView); // If we find another CRichEditView, // skip the code that closes the Find/Replace dialog box. if (pView->IsKindOf(RUNTIME_CLASS(CRichEditView))               && pView != this && ::IsWindow(pView->GetSafeHwnd)) {               pEditState->pFindReplaceDlg->m_fr.hwndOwner = pView->m_hWnd; goto FoundRichEditView; }          }         }       }     }

if (::IsWindow(pEditState->pFindReplaceDlg->m_hWnd)) pEditState->pFindReplaceDlg->SendMessage(WM_CLOSE); pEditState->pFindReplaceDlg = NULL; }

FoundRichEditView: CRichEditView::OnDestroy; }

Additional query words: CRichEditView AssertValid Find Replace Assert

Keywords: kbbug kbcmndlg kbcmndlgfind kbcmndlgrepl kbpending kbrichedit KB230377

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.