c++ - Why Is the DestroyWindow() Function Failing an Assert and Why is the PreTranslateMessage() Function of My ActiveX Control not Being Called? -


question

why pwnd = (cwnd*)pmap->lookuppermanent(m_hwnd); returning null in cwnd::destroywindow() function causing assert statement fail while trying destroy modal dialog?

furthermore, between causing issue , attempting destroy window, why pretranslatemessage() function stop getting called?

initial information

i have activex control implements on screen keyboard. keyboard accepts both touch/click events , keystroke events attached hardware keyboard. input control validated using algorithm defined module created keyboard.

touching buttons on screen generates input follows

onbuttonup()->addcharacter()->validatetext() 

typing on physical keyboard generates input follows

pretranslatemessage()->addcharacter()->validatetext() 

the validatetext() function fires event handled module created keyboard.

i have added try-catch block around event firing handle errors occur while event being processed.

confusing behavior

what have found if error caused using usb keyboard, when user attempts close keyboard debug assert statement in cwnd::destroywindow() fails. if same error caused using touch screen interface, assert statement succeeds.

i have discovered if error caused using usb keyboard, pretranslatemessage() function activex control stops being called. confirmed setting breakpoint on first line of function , spying on messages being sent window. after causing error there still large number of messages (mainly wm_mousemoves) breakpoint no longer caused program break.

source code snippets

the code firing event 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 onvalidate() function defined as:

void onvalidate(bstr* text, long* isvalid) {     fireevent(eventidonvalidate, event_param(vts_pbstr vts_pi4), text, isvalid); } 

the cwnd::destroywindow() function (with 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); //<- returns null before 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 'this' may have been deleted @ point,         //  (but if pwnd != null)         if (pwnd != null)         {             // should have been detached onncdestroy             assert(pmap->lookuppermanent(hwndorig) == null);         }         else         {             assert(m_hwnd == hwndorig); //<-this assert fails!         // detach after destroywindow called in case             detach();         }     }      return bresult; } 

from have been able obtain via tracepoints, when assert fails, pwnd = (cwnd*)pmap->lookuppermanent(m_hwnd); returns null.

using information tracepoints, destroywindow() call keyboard control seems follow:

when works (error caused touch input handled)

  • start destroying keyboard: m_hwnd = non-null, hwndorig = non-null, pwnd = non-null
  • recurse destroying keyboard buttons: m_hwnd = non-null, hwndorig = non-null, pwnd = non-null
  • return destroying buttons: m_hwnd = null, hwndorig = non-null, pwnd = non-null
  • assert(pmap->lookuppermanent(hwndorig) == null); called , succeeds.

when breaks (error caused hardware input handled)

  • start destroying keyboard: m_hwnd = non-null, hwndorig = non-null, pwnd = null
  • recurse destroying keyboard buttons: m_hwnd = non-null, hwndorig = non-null, pwnd = non-null
  • return destroying buttons: m_hwnd = null, hwndorig = non-null, pwnd = null
  • assert(m_hwnd == hwndorig); called , fails.


Comments