]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/choice.cpp
Ensure there is valid context for DrawRectangle
[wxWidgets.git] / src / msw / choice.cpp
index 1cb3bd93869e414b56f3dc2775c68885e5203fa0..30dad609d01e46fe6f04b30b8b75e892e1af7c69 100644 (file)
@@ -200,12 +200,12 @@ wxChoice::~wxChoice()
     Clear();
 }
 
     Clear();
 }
 
-bool wxChoice::MSWGetComboBoxInfo(COMBOBOXINFO* info) const
+bool wxChoice::MSWGetComboBoxInfo(tagCOMBOBOXINFO* info) const
 {
     // TODO-Win9x: Get rid of this once we officially drop support for Win9x
     //             and just call the function directly.
 #if wxUSE_DYNLIB_CLASS
 {
     // TODO-Win9x: Get rid of this once we officially drop support for Win9x
     //             and just call the function directly.
 #if wxUSE_DYNLIB_CLASS
-    typedef BOOL (WINAPI *GetComboBoxInfo_t)(HWND, COMBOBOXINFO*);
+    typedef BOOL (WINAPI *GetComboBoxInfo_t)(HWND, tagCOMBOBOXINFO*);
     static GetComboBoxInfo_t s_pfnGetComboBoxInfo = NULL;
     static bool s_triedToLoad = false;
     if ( !s_triedToLoad )
     static GetComboBoxInfo_t s_pfnGetComboBoxInfo = NULL;
     static bool s_triedToLoad = false;
     if ( !s_triedToLoad )
@@ -631,6 +631,9 @@ wxSize wxChoice::DoGetSizeFromTextSize(int xlen, int ylen) const
     // and its child part. I.e. arrow, separators, etc.
     wxSize tsize(xlen, 0);
 
     // and its child part. I.e. arrow, separators, etc.
     wxSize tsize(xlen, 0);
 
+    // FIXME-VC6: Only VC6 needs this guard, see WINVER definition in
+    //            include/wx/msw/wrapwin.h
+#if defined(WINVER) && WINVER >= 0x0500
     WinStruct<COMBOBOXINFO> info;
     if ( MSWGetComboBoxInfo(&info) )
     {
     WinStruct<COMBOBOXINFO> info;
     if ( MSWGetComboBoxInfo(&info) )
     {
@@ -638,6 +641,7 @@ wxSize wxChoice::DoGetSizeFromTextSize(int xlen, int ylen) const
                     + info.rcItem.left + 3; // right and extra margins
     }
     else // Just use some rough approximation.
                     + info.rcItem.left + 3; // right and extra margins
     }
     else // Just use some rough approximation.
+#endif // WINVER >= 0x0500
     {
         tsize.x += 4*cHeight;
     }
     {
         tsize.x += 4*cHeight;
     }
@@ -736,9 +740,7 @@ bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
     /*
         The native control provides a great variety in the events it sends in
         the different selection scenarios (undoubtedly for greater amusement of
     /*
         The native control provides a great variety in the events it sends in
         the different selection scenarios (undoubtedly for greater amusement of
-        the programmers using it). For the reference, here are the cases when
-        the final selection is accepted (things are quite interesting when it
-        is cancelled too):
+        the programmers using it). Here are the different cases:
 
         A. Selecting with just the arrows without opening the dropdown:
             1. CBN_SELENDOK
 
         A. Selecting with just the arrows without opening the dropdown:
             1. CBN_SELENDOK
@@ -760,6 +762,12 @@ bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
         Admire the different order of messages in all of those cases, it must
         surely have taken a lot of effort to Microsoft developers to achieve
         such originality.
         Admire the different order of messages in all of those cases, it must
         surely have taken a lot of effort to Microsoft developers to achieve
         such originality.
+
+        Additionally, notice that CBN_SELENDCANCEL doesn't seem to actually
+        cancel anything, if we get CBN_SELCHANGE before it, as it happens in
+        the case (B), the selection is still accepted. This doesn't make much
+        sense and directly contradicts MSDN documentation but is how the native
+        comboboxes behave and so we do the same thing.
      */
     switch ( param )
     {
      */
     switch ( param )
     {
@@ -772,44 +780,40 @@ bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
             break;
 
         case CBN_CLOSEUP:
             break;
 
         case CBN_CLOSEUP:
-            // if the selection was accepted by the user, it should have been
-            // reset to wxID_NONE by CBN_SELENDOK, otherwise the selection was
-            // cancelled and we must restore the old one
-            if ( m_lastAcceptedSelection != wxID_NONE )
+            if ( m_pendingSelection != wxID_NONE )
             {
             {
-                SetSelection(m_lastAcceptedSelection);
-                m_lastAcceptedSelection = wxID_NONE;
+                // This can only happen in the case (B), so set the item
+                // selected in the drop down as our real selection.
+                SendSelectionChangedEvent(wxEVT_COMMAND_CHOICE_SELECTED);
+                m_pendingSelection = wxID_NONE;
             }
             break;
 
         case CBN_SELENDOK:
             }
             break;
 
         case CBN_SELENDOK:
-            // reset it to prevent CBN_CLOSEUP from undoing the selection (it's
-            // ok to reset it now as GetCurrentSelection() will now return the
-            // same thing anyhow)
-            m_lastAcceptedSelection = wxID_NONE;
-
-            {
-                const int n = GetSelection();
-
-                wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, m_windowId);
-                event.SetInt(n);
-                event.SetEventObject(this);
+            // Reset the variables to prevent CBN_CLOSEUP from doing anything,
+            // it's not needed if we do get CBN_SELENDOK.
+            m_lastAcceptedSelection =
+            m_pendingSelection = wxID_NONE;
 
 
-                if ( n > -1 )
-                {
-                    event.SetString(GetStringSelection());
-                    InitCommandEventWithItems(event, n);
-                }
-
-                ProcessCommand(event);
-            }
+            SendSelectionChangedEvent(wxEVT_COMMAND_CHOICE_SELECTED);
             break;
 
             break;
 
-        // don't handle CBN_SELENDCANCEL: just leave m_lastAcceptedSelection
-        // valid and the selection will be undone in CBN_CLOSEUP above
+        case CBN_SELCHANGE:
+            // If we get this event after CBN_SELENDOK, i.e. cases (A) or (C)
+            // above, we don't have anything to do. But in the case (B) we need
+            // to remember that the selection should really change once the
+            // drop down is closed.
+            if ( m_lastAcceptedSelection != wxID_NONE )
+                m_pendingSelection = GetCurrentSelection();
+            break;
 
 
-        // don't handle CBN_SELCHANGE neither, we don't want to generate events
-        // while the dropdown is opened -- but do add it if we ever need this
+        case CBN_SELENDCANCEL:
+            // Do not reset m_pendingSelection here -- it would make sense but,
+            // as described above, native controls keep the selection even when
+            // closing the drop down by pressing Escape or TAB, so conform to
+            // their behaviour.
+            m_lastAcceptedSelection = wxID_NONE;
+            break;
 
         default:
             return false;
 
         default:
             return false;