]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
Fixed wxApp::OnAssert signature.
[wxWidgets.git] / src / msw / window.cpp
index b99b966f66475765a73c88daeb5798fcbd0bf56e..cf7c4277ac81302bc7927295f17fa2eb48cf5f58 100644 (file)
@@ -179,7 +179,7 @@ static void TranslateKbdEventToMouse(wxWindowMSW *win,
 static TEXTMETRIC wxGetTextMetrics(const wxWindowMSW *win);
 
 // find the window for the mouse event at the specified position
-static wxWindowMSW *FindWindowForMouseEvent(wxWindow *win, int *x, int *y);
+static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y); //TW:REQ:Univ
 
 // wrapper around BringWindowToTop() API
 static inline void wxBringWindowToTop(HWND hwnd)
@@ -348,12 +348,12 @@ wxWindowMSW::~wxWindowMSW()
     // VS: make sure there's no wxFrame with last focus set to us:
     for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
     {
-        wxFrame *frame = wxDynamicCast(win, wxFrame);
+        wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
         if ( frame )
         {
             if ( frame->GetLastFocus() == this )
             {
-                frame->SetLastFocus((wxWindow*)NULL);
+                frame->SetLastFocus(NULL);
             }
             break;
         }
@@ -413,7 +413,10 @@ bool wxWindowMSW::Create(wxWindow *parent,
 
 #ifdef __WXUNIVERSAL__
     // no borders, we draw them ourselves
-    exstyle = 0;
+    exstyle &= ~(WS_EX_DLGMODALFRAME |
+                 WS_EX_STATICEDGE |
+                 WS_EX_CLIENTEDGE |
+                 WS_EX_WINDOWEDGE);
     msflags &= ~WS_BORDER;
 #endif // wxUniversal
 
@@ -1160,6 +1163,16 @@ WXDWORD wxWindowMSW::MSWGetStyle(long flags, WXDWORD *exstyle) const
                 *exstyle |= WS_EX_DLGMODALFRAME;
                 break;
         }
+
+        // wxUniv doesn't use Windows dialog navigation functions at all
+#ifndef __WXUNIVERSAL__
+        // to make the dialog navigation work with the nested panels we must
+        // use this style (top level windows such as dialogs don't need it)
+        if ( (flags & wxTAB_TRAVERSAL) && !IsTopLevel() )
+        {
+            *exstyle |= WS_EX_CONTROLPARENT;
+        }
+#endif // __WXUNIVERSAL__
     }
 
     return style;
@@ -1995,9 +2008,23 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
 
                                 return TRUE;
                             }
-                            //else: no default button
+                            else // no default button
+                            {
 #endif // wxUSE_BUTTON
-                            // treat Enter as TAB: pass to the next control
+                                // this is a quick and dirty test for a text
+                                // control
+                                if ( !(lDlgCode & DLGC_HASSETSEL) )
+                                {
+                                    // don't process Enter, the control might
+                                    // need it for itself and don't let
+                                    // ::IsDialogMessage() have it as it can
+                                    // eat the Enter events sometimes
+                                    return FALSE;
+                                }
+                                //else: treat Enter as TAB: pass to the next
+                                //      control as this is the best thing to do
+                                //      if the text doesn't handle Enter itself
+                            }
                         }
                     }
                     break;
@@ -2056,7 +2083,27 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
         // place edit control from being closed with Escape in a dialog
         if ( msg->message != WM_KEYDOWN || msg->wParam != VK_ESCAPE )
         {
-            if ( ::IsDialogMessage(GetHwnd(), msg) )
+            // ::IsDialogMessage() can enter in an infinite loop when
+            // WS_EX_CONTROLPARENT is specified and the currently focused
+            // window is disabled or hidden, so don't call it in this case
+            bool canSafelyCallIsDlgMsg = TRUE;
+
+            HWND hwndFocus = ::GetFocus();
+            while ( hwndFocus )
+            {
+                if ( !::IsWindowEnabled(hwndFocus) ||
+                        !::IsWindowVisible(hwndFocus) )
+                {
+                    // it would enter an infinite loop if we do this!
+                    canSafelyCallIsDlgMsg = FALSE;
+
+                    break;
+                }
+
+                hwndFocus = ::GetParent(hwndFocus);
+            }
+
+            if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
             {
                 // IsDialogMessage() did something...
                 return TRUE;
@@ -2407,9 +2454,15 @@ long wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam
                         y = GET_Y_LPARAM(lParam);
 
                     // redirect the event to a static control if necessary
-                    wxWindow *win = FindWindowForMouseEvent(this, &x, &y);
-
-                    processed = win->HandleMouseEvent(message, x, y, wParam);
+                    if (this == GetCapture())
+                    {
+                        processed = HandleMouseEvent(message, x, y, wParam);
+                    }
+                    else
+                    {
+                        wxWindowMSW *win = FindWindowForMouseEvent(this, &x, &y); //TW:REQ:Univ
+                        processed = win->HandleMouseEvent(message, x, y, wParam);
+                    }
                 }
             }
             break;
@@ -2880,6 +2933,11 @@ bool wxWindowMSW::MSWGetCreateWindowCoords(const wxPoint& pos,
     return nonDefault;
 }
 
+WXHWND wxWindowMSW::MSWGetParent() const
+{
+    return m_parent ? m_parent->GetHWND() : NULL;
+}
+
 bool wxWindowMSW::MSWCreate(const wxChar *wclass,
                             const wxChar *title,
                             const wxPoint& pos,
@@ -2891,41 +2949,10 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     int x, y, w, h;
     (void)MSWGetCreateWindowCoords(pos, size, x, y, w, h);
 
-    // find the correct parent HWND
-    wxWindow *parent = GetParent();
-    bool isChild = (style & WS_CHILD) != 0;
-    HWND hParent;
-    if ( GetWindowStyleFlag() & wxPOPUP_WINDOW )
-    {
-        // popup windows should have desktop as parent because they shouldn't
-        // be limited to the parents client area as child windows usually are
-        hParent = ::GetDesktopWindow();
-    }
-    else // !popup
-    {
-        if ( (isChild || HasFlag(wxFRAME_TOOL_WINDOW)) && parent )
-        {
-            // this is either a normal child window or a top level window with
-            // wxFRAME_TOOL_WINDOW style (see below)
-            hParent = GetHwndOf(parent);
-        }
-        else
-        {
-            // this is either a window for which no parent was specified (not
-            // much we can do then) or a frame without wxFRAME_TOOL_WINDOW
-            // style: we should use NULL parent HWND for it or it would be
-            // always on top of its parent which is not what we usually want
-            // (in fact, we only want it for frames with the special
-            // wxFRAME_TOOL_WINDOW as above)
-            hParent = NULL;
-        }
-
-    }
-
     // controlId is menu handle for the top level windows, so set it to 0
     // unless we're creating a child window
     int controlId;
-    if ( isChild )
+    if ( style & WS_CHILD )
     {
         controlId = GetId();
 
@@ -2952,17 +2979,17 @@ bool wxWindowMSW::MSWCreate(const wxChar *wclass,
     wxWindowCreationHook hook(this);
 
     m_hWnd = (WXHWND)::CreateWindowEx
-             (
-                extendedStyle,
-                className,
-                title ? title : wxT(""),
-                style,
-                x, y, w, h,
-                hParent,
-                (HMENU)controlId,
-                wxGetInstance(),
-                NULL                        // no extra data
-             );
+                       (
+                            extendedStyle,
+                            className,
+                            title ? title : wxT(""),
+                            style,
+                            x, y, w, h,
+                            (HWND)MSWGetParent(),
+                            (HMENU)controlId,
+                            wxGetInstance(),
+                            NULL                        // no extra data
+                       );
 
     if ( !m_hWnd )
     {
@@ -3086,8 +3113,31 @@ bool wxWindowMSW::HandleEndSession(bool endSession, long logOff)
 // window creation/destruction
 // ---------------------------------------------------------------------------
 
-bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT WXUNUSED(cs), bool *mayCreate)
+bool wxWindowMSW::HandleCreate(WXLPCREATESTRUCT cs, bool *mayCreate)
 {
+    // if we have WS_EX_CONTROLPARENT flag we absolutely *must* set it for our
+    // parent as well as otherwise several Win32 functions using
+    // GetNextDlgTabItem() to iterate over all controls such as
+    // IsDialogMessage() or DefDlgProc() would enter an infinite loop: indeed,
+    // all of them iterate over all the controls starting from the focus and
+    // stop iterating when they get back to the focus but unless all parents
+    // have WS_EX_CONTROLPARENT bit set, they would never get back to focus
+    if ( ((CREATESTRUCT *)cs)->dwExStyle & WS_EX_CONTROLPARENT )
+    {
+        // there is no need to do anything for the top level windows
+        const wxWindow *parent = GetParent();
+        if ( parent && !parent->IsTopLevel() )
+        {
+            LONG exStyle = ::GetWindowLong(GetHwndOf(parent), GWL_EXSTYLE);
+            if ( !(exStyle & WS_EX_CONTROLPARENT) )
+            {
+                // force the parent to have this style
+                ::SetWindowLong(GetHwndOf(parent), GWL_EXSTYLE,
+                                exStyle | WS_EX_CONTROLPARENT);
+            }
+        }
+    }
+
     // TODO: should generate this event from WM_NCCREATE
     wxWindowCreateEvent event((wxWindow *)this);
     (void)GetEventHandler()->ProcessEvent(event);
@@ -3954,6 +4004,7 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event,
 
     event.SetTimestamp(s_currentMsg.time);
     event.m_eventObject = this;
+    event.SetId(GetId());
 
 #if wxUSE_MOUSEEVENT_HACK
     m_lastMouseX = x;
@@ -3972,7 +4023,7 @@ void wxWindowMSW::InitMouseEvent(wxMouseEvent& event,
 // Notice that this is not done for the mouse move events because this could
 // (would?) be too slow, but only for clicks which means that the static texts
 // still don't get move, enter nor leave events.
-static wxWindowMSW *FindWindowForMouseEvent(wxWindow *win, int *x, int *y)
+static wxWindowMSW *FindWindowForMouseEvent(wxWindowMSW *win, int *x, int *y) //TW:REQ:Univ
 {
     wxCHECK_MSG( x && y, win, _T("NULL pointer in FindWindowForMouseEvent") );