Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- **Question**
- Why is `pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);` occasionally returning NULL in the CWnd::DestroyWindow() function causing an ASSERT statement to fail while trying to destroy a modal dialog?
- **Initial Information**
- I have an ActiveX control that implements an on screen keyboard.
- This keyboard accepts both touch/click events and keystroke events from an attached hardware keyboard.
- Input to the control is validated using an algorithm defined by the module that created the keyboard.
- Touching the buttons on screen generates input that follows
- OnButtonUP()->AddCharacter()->ValidateText()
- Typing on the physical keyboard generates input that follows
- PreTranslateMessage()->AddCharacter()->ValidateText()
- The ValidateText() function fires an event that is handled by the module that created the keyboard.
- I have added a try-catch block around the event firing to handle any errors that occur while the event is being processed.
- **Confusing Behavior**
- What I have found is that if an error is caused by using the USB Keyboard, when the user attempts to close the Keyboard a debug assert statement in CWnd::DestroyWindow() fails.
- If the same error is caused by using the touch screen interface, the assert statement succeeds.
- **Source Code Snippets**
- The code for firing the event is as follows:
- try
- {
- m_control->OnValidate(&text, &isValid);
- }
- catch (...)
- {
- LOG_CRITICAL_ERROR(/*Format(*/L"Keyboard::ValidateText: Error occured while validating"/*, badText.c_str()).c_str()*/);
- }
- Where the OnValidate() function is defined as:
- void OnValidate(BSTR* text, LONG* isValid)
- {
- FireEvent(eventidOnValidate, EVENT_PARAM(VTS_PBSTR VTS_PI4), text, isValid);
- }
- The CWnd::DestroyWindow() function is (With some bits preprocessor bits removed) :
- BOOL CWnd::DestroyWindow()
- {
- CWnd* pWnd;
- CHandleMap* pMap;
- HWND hWndOrig;
- BOOL bResult;
- if ((m_hWnd == NULL) && (m_pCtrlSite == NULL))
- return FALSE;
- bResult = FALSE;
- pMap = NULL;
- pWnd = NULL;
- hWndOrig = NULL;
- if (m_hWnd != NULL)
- {
- pMap = afxMapHWND();
- ENSURE(pMap != NULL);
- pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd); //<- This returns NULL before the Assert fails
- hWndOrig = m_hWnd;
- }
- if ((m_hWnd != NULL) || (m_pCtrlSite != NULL))
- {
- if (m_pCtrlSite == NULL)
- bResult = ::DestroyWindow(m_hWnd);
- else
- bResult = m_pCtrlSite->DestroyControl();
- }
- if (hWndOrig != NULL)
- {
- // Note that 'this' may have been deleted at this point,
- // (but only if pWnd != NULL)
- if (pWnd != NULL)
- {
- // Should have been detached by OnNcDestroy
- ASSERT(pMap->LookupPermanent(hWndOrig) == NULL);
- }
- else
- {
- ASSERT(m_hWnd == hWndOrig); //<-This is the ASSERT that fails!
- // Detach after DestroyWindow called just in case
- Detach();
- }
- }
- return bResult;
- }
- From what I have been able to obtain via tracepoints, when the assert fails, `pWnd = (CWnd*)pMap->LookupPermanent(m_hWnd);` returns NULL.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement