]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/window.cpp
applied patch 430963 (fix for wxRegConfig::SetPath("//foo")
[wxWidgets.git] / src / msw / window.cpp
index 11a6da140e97fc263a63dc80d6458afad498e0e5..fb93646628c802b691625b186f58fbf2f217bb73 100644 (file)
@@ -84,7 +84,7 @@
 
 #include <string.h>
 
-#ifndef __GNUWIN32_OLD__
+#if !defined(__GNUWIN32_OLD__) || defined(__CYGWIN10__)
     #include <shellapi.h>
     #include <mmsystem.h>
 #endif
@@ -93,7 +93,7 @@
     #include <windowsx.h>
 #endif
 
-#if !defined(__GNUWIN32_OLD__) && !defined(__TWIN32__)
+#if (!defined(__GNUWIN32_OLD__) && !defined(__TWIN32__)) || defined(__CYGWIN10__)
     #ifdef __WIN95__
         #include <commctrl.h>
     #endif
@@ -289,11 +289,26 @@ wxWindow::~wxWindow()
 
     MSWDetachWindowMenu();
 
-    if ( m_parent )
-        m_parent->RemoveChild(this);
+    // 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);
+        if ( frame )
+        {
+            if ( frame->GetLastFocus() == this )
+                frame->SetLastFocus((wxWindow*)NULL);
+            break;
+        }
+    }
 
+    // VS: destroy children first and _then_ detach *this from its parent.
+    //     If we'd do it the other way around, children wouldn't be able
+    //     find their parent frame (see above).
     DestroyChildren();
 
+    if ( m_parent )
+        m_parent->RemoveChild(this);
+
     if ( m_hWnd )
     {
         // VZ: test temp removed to understand what really happens here
@@ -431,7 +446,11 @@ bool wxWindow::Show(bool show)
 // Raise the window to the top of the Z order
 void wxWindow::Raise()
 {
+#ifdef __WIN16__
     ::BringWindowToTop(GetHwnd());
+#else // Win32
+    ::SetForegroundWindow(GetHwnd());
+#endif
 }
 
 // Lower the window to the bottom of the Z order
@@ -1469,6 +1488,23 @@ void wxWindow::GetCaretPos(int *x, int *y) const
 // popup menu
 // ---------------------------------------------------------------------------
 
+// yield for WM_COMMAND events only, i.e. process all WM_COMMANDs in the queue
+// immediately, without waiting for the next event loop iteration
+//
+// NB: this function should probably be made public later as it can almost
+//     surely replace wxYield() elsewhere as well
+static void wxYieldForCommandsOnly()
+{
+    // peek all WM_COMMANDs (it will always return WM_QUIT too but we don't
+    // want to process it here)
+    MSG msg;
+    while ( ::PeekMessage(&msg, (HWND)0, WM_COMMAND, WM_COMMAND, PM_REMOVE)
+                && msg.message != WM_QUIT )
+    {
+        wxTheApp->DoMessage((WXMSG *)&msg);
+    }
+}
+
 bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
 {
     menu->SetInvokingWindow(this);
@@ -1482,7 +1518,16 @@ bool wxWindow::DoPopupMenu(wxMenu *menu, int x, int y)
     ::ClientToScreen(hWnd, &point);
     wxCurrentPopupMenu = menu;
     ::TrackPopupMenu(hMenu, TPM_RIGHTBUTTON, point.x, point.y, 0, hWnd, NULL);
-    wxYieldIfNeeded();
+
+    // we need to do it righ now as otherwise the events are never going to be
+    // sent to wxCurrentPopupMenu from HandleCommand()
+    //
+    // note that even eliminating (ugly) wxCurrentPopupMenu global wouldn't
+    // help and we'd still need wxYieldForCommandsOnly() as the menu may be
+    // destroyed as soon as we return (it can be a local variable in the caller
+    // for example) and so we do need to process the event immediately
+    wxYieldForCommandsOnly();
+
     wxCurrentPopupMenu = NULL;
 
     menu->SetInvokingWindow(NULL);
@@ -2246,13 +2291,7 @@ long wxWindow::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
                 wxPoint pt(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
 
                 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetId(), pt);
-                GetEventHandler()->ProcessEvent(evtCtx);
-
-                // set processed to true even if the event is not handled
-                // because if we don't windows will propogate the
-                // WM_CONTEXTMENU up the parent window chain, which we have
-                // already done ourselves.
-                processed = true;
+                processed = GetEventHandler()->ProcessEvent(evtCtx);
             }
             break;
 #endif // __WIN32__
@@ -2923,19 +2962,20 @@ bool wxWindow::MSWOnDrawItem(int id, WXDRAWITEMSTRUCT *itemStruct)
 
         wxCHECK( pMenuItem->IsKindOf(CLASSINFO(wxMenuItem)), FALSE );
 
-        // prepare to call OnDrawItem()
-        wxDC dc;
-        dc.SetHDC((WXHDC)pDrawStruct->hDC, FALSE);
+        // prepare to call OnDrawItem(): notice using of wxDCTemp to prevent
+        // the DC from being released
+        wxDCTemp dc((WXHDC)pDrawStruct->hDC);
         wxRect rect(pDrawStruct->rcItem.left, pDrawStruct->rcItem.top,
                     pDrawStruct->rcItem.right - pDrawStruct->rcItem.left,
                     pDrawStruct->rcItem.bottom - pDrawStruct->rcItem.top);
 
         return pMenuItem->OnDrawItem
-                          (
-                            dc, rect,
-                            (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
-                            (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
-                          );
+               (
+                dc,
+                rect,
+                (wxOwnerDrawn::wxODAction)pDrawStruct->itemAction,
+                (wxOwnerDrawn::wxODStatus)pDrawStruct->itemState
+               );
     }
 
     wxWindow *item = FindItem(id);
@@ -3103,9 +3143,8 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc)
     if ( ::IsIconic(GetHwnd()) )
         return TRUE;
 
-    wxDC dc;
+    wxDCTemp dc(hdc);
 
-    dc.SetHDC(hdc);
     dc.SetWindow(this);
     dc.BeginDrawing();
 
@@ -3114,8 +3153,9 @@ bool wxWindow::HandleEraseBkgnd(WXHDC hdc)
     bool rc = GetEventHandler()->ProcessEvent(event);
 
     dc.EndDrawing();
+
+    // must be called manually as ~wxDC doesn't do anything for wxDCTemp
     dc.SelectOldObjects(hdc);
-    dc.SetHDC((WXHDC) NULL);
 
     return rc;
 }
@@ -3425,6 +3465,9 @@ bool wxWindow::HandleMouseWheel(WXWPARAM wParam, WXLPARAM lParam)
     return GetEventHandler()->ProcessEvent(event);
 
 #else
+    (void) wParam;
+    (void) lParam;
+
     return FALSE;
 #endif
 }