+#if wxUSE_MSGBOX_HOOK
+
+// there can potentially be one message box per thread so we use a hash map
+// with thread ids as keys and (currently shown) message boxes as values
+//
+// TODO: replace this with wxTLS once it's available
+WX_DECLARE_HASH_MAP(unsigned long, wxMessageDialog *,
+ wxIntegerHash, wxIntegerEqual,
+ wxMessageDialogMap);
+
+namespace
+{
+
+wxMessageDialogMap& HookMap()
+{
+ static wxMessageDialogMap s_Map;
+
+ return s_Map;
+}
+
+} // anonymous namespace
+
+/* static */
+WXLRESULT wxCALLBACK
+wxMessageDialog::HookFunction(int code, WXWPARAM wParam, WXLPARAM lParam)
+{
+ // Find the thread-local instance of wxMessageDialog
+ const DWORD tid = ::GetCurrentThreadId();
+ wxMessageDialogMap::iterator node = HookMap().find(tid);
+ wxCHECK_MSG( node != HookMap().end(), false,
+ wxT("bogus thread id in wxMessageDialog::Hook") );
+
+ wxMessageDialog * const wnd = node->second;
+
+ const HHOOK hhook = (HHOOK)wnd->m_hook;
+ const LRESULT rc = ::CallNextHookEx(hhook, code, wParam, lParam);
+
+ if ( code == HCBT_ACTIVATE )
+ {
+ // we won't need this hook any longer
+ ::UnhookWindowsHookEx(hhook);
+ wnd->m_hook = NULL;
+ HookMap().erase(tid);
+
+ wnd->SetHWND((HWND)wParam);
+
+ // update the labels if necessary: we need to do it before centering
+ // the dialog as this can change its size
+ if ( wnd->HasCustomLabels() )
+ wnd->AdjustButtonLabels();
+
+ // centre the message box on its parent if requested
+ if ( wnd->GetMessageDialogStyle() & wxCENTER )
+ wnd->Center(); // center on parent
+ //else: default behaviour, center on screen
+
+ // there seems to be no reason to leave it set
+ wnd->SetHWND(NULL);
+ }
+
+ return rc;
+}
+
+namespace
+{
+
+// helper of AdjustButtonLabels(): set window position expressed in screen
+// coordinates, whether the window is child or top level
+void MoveWindowToScreenRect(HWND hwnd, RECT rc)
+{
+ if ( const HWND hwndParent = ::GetAncestor(hwnd, GA_PARENT) )
+ {
+ // map to parent window coordinates (notice that a RECT is laid out as
+ // 2 consecutive POINTs)
+ ::MapWindowPoints(HWND_DESKTOP, hwndParent,
+ reinterpret_cast<POINT *>(&rc), 2);
+ }
+
+ ::MoveWindow(hwnd,
+ rc.left, rc.top,
+ rc.right - rc.left, rc.bottom - rc.top,
+ FALSE);
+}
+
+// helper of AdjustButtonLabels(): move the given window by dx
+//
+// works for both child and top level windows
+void OffsetWindow(HWND hwnd, int dx)
+{
+ RECT rc = wxGetWindowRect(hwnd);
+
+ rc.left += dx;
+ rc.right += dx;
+
+ MoveWindowToScreenRect(hwnd, rc);
+}
+
+} // anonymous namespace
+
+void wxMessageDialog::AdjustButtonLabels()