Neulich bei einem Codereview, lief mir Code in den beiden nachfolgenden Formen über meinen Monitor:
BOOL CMyDialog::PreTranslateMessage(MSG *pMsg)
{
// Translate Messages (ON_KEYDOWN -> ON_COMMAND)
TranslateAccelerator(m_hWnd,m_hAccel,pMsg);
// Let the ToolTip process this message.
m_tooltip.RelayEvent(pMsg);
return __super::PreTranslateMessage(pMsg);
}
– bzw. –
BOOL CMyWnd::PreTranslateMessage(MSG *pMsg)
{
BOOL bResult = __super::PreTranslateMessage(pMsg);
DoSomething();
return bResult;
}
Sieht OK aus, aber hier tritt ein grundsätzliches Problem auf:
In beiden Funktionen wird evtl. eine Nachricht behandelt. Allerdings wird in diesem Fall nicht umgehend die Funktion verlassen. Durch das Behandeln der Nachricht kann nämlich das Fenster/Objekt, zu dem PreTranslateMessage gehört, bereits zerstört sein. In diesem Fall kehrt PreTranslateMessage zurück und der this Zeiger ist bereits ungültig.
Es ist also imminent wichtig in dem Moment in dem erkannt wird, dass die Nachricht behandelt wurde, auch umgehend die Funktion mit TRUE zu verlassen und keine weitere Memberfunktion oder gar Membervariable mehr zu nutzen. Beides könnte zu einem üblen Crash führen.
Der korrekte Code sähe also so aus:
BOOL CMyDialog::PreTranslateMessage(MSG *pMsg)
{
// Translate Messages (ON_KEYDOWN -> ON_COMMAND)
if (TranslateAccelerator(m_hWnd,m_hAccel,pMsg))
return TRUE;
// Let the ToolTip process this message.
m_tooltip.RelayEvent(pMsg);
return __super::PreTranslateMessage(pMsg);
}
– oder –
BOOL CMyWnd::PreTranslateMessage(MSG *pMsg)
{
if (__super::PreTranslateMessage(pMsg))
return TRUE;
DoSomething();
return FALSE;
}
PS: Beide Codeteile wurden durch Crashdumps aus WinQual gefunden. Regelmäßig, alle 2 Monate schaue ich mir Dumps an, von den Top-Crashes, die dort verzeichnet sind, und mache entsprechende Code-Reviews.
Der erste Code, stammte aus einem speziellen nicht modalen Dialog, der durch Drücken bestimmter Tastenkombinationen geschlossen und zerstört wurde.
Der zweite Code stammte aus einem Popup-Fenster, dass auch durch Mausaktivitäten oder Tastendrücke zerstört wurde.
Ich kann jedem nur raten WinQual auch zu nutzen, es dient der Qualtitätssicherung und man findet viele kleine Bugs, die manchen User ärgern, die aber nie sonst gemeldet würden.