]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/choice.cpp
Added ability to execute more code after the widget is created
[wxWidgets.git] / src / msw / choice.cpp
index 4d1df2c1a42f6313348740c7a820ca0d5ffd33ea..5f49fcd97d6e72cc6b3b4c95e64bd17aa0bc4ee1 100644 (file)
@@ -52,7 +52,7 @@ wxBEGIN_FLAGS( wxChoiceStyle )
     wxFLAGS_MEMBER(wxBORDER_RAISED)
     wxFLAGS_MEMBER(wxBORDER_STATIC)
     wxFLAGS_MEMBER(wxBORDER_NONE)
     wxFLAGS_MEMBER(wxBORDER_RAISED)
     wxFLAGS_MEMBER(wxBORDER_STATIC)
     wxFLAGS_MEMBER(wxBORDER_NONE)
-    
+
     // old style border flags
     wxFLAGS_MEMBER(wxSIMPLE_BORDER)
     wxFLAGS_MEMBER(wxSUNKEN_BORDER)
     // old style border flags
     wxFLAGS_MEMBER(wxSIMPLE_BORDER)
     wxFLAGS_MEMBER(wxSUNKEN_BORDER)
@@ -76,26 +76,26 @@ wxEND_FLAGS( wxChoiceStyle )
 IMPLEMENT_DYNAMIC_CLASS_XTI(wxChoice, wxControl,"wx/choice.h")
 
 wxBEGIN_PROPERTIES_TABLE(wxChoice)
 IMPLEMENT_DYNAMIC_CLASS_XTI(wxChoice, wxControl,"wx/choice.h")
 
 wxBEGIN_PROPERTIES_TABLE(wxChoice)
-       wxEVENT_PROPERTY( Select , wxEVT_COMMAND_CHOICE_SELECTED , wxCommandEvent )
+    wxEVENT_PROPERTY( Select , wxEVT_COMMAND_CHOICE_SELECTED , wxCommandEvent )
 
 
-    wxPROPERTY( Font , wxFont , SetFont , GetFont  , , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+    wxPROPERTY( Font , wxFont , SetFont , GetFont  , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
     wxPROPERTY_COLLECTION( Choices , wxArrayString , wxString , AppendString , GetStrings , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
     wxPROPERTY_COLLECTION( Choices , wxArrayString , wxString , AppendString , GetStrings , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
-       wxPROPERTY( Selection ,int, SetSelection, GetSelection, , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
-    wxPROPERTY_FLAGS( WindowStyle , wxChoiceStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
+    wxPROPERTY( Selection ,int, SetSelection, GetSelection, EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group"))
+    wxPROPERTY_FLAGS( WindowStyle , wxChoiceStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
 wxEND_PROPERTIES_TABLE()
 
 wxBEGIN_HANDLERS_TABLE(wxChoice)
 wxEND_HANDLERS_TABLE()
 
 wxEND_PROPERTIES_TABLE()
 
 wxBEGIN_HANDLERS_TABLE(wxChoice)
 wxEND_HANDLERS_TABLE()
 
-wxCONSTRUCTOR_4( wxChoice , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size ) 
+wxCONSTRUCTOR_4( wxChoice , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size )
 #else
 IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
 #endif
 /*
 #else
 IMPLEMENT_DYNAMIC_CLASS(wxChoice, wxControl)
 #endif
 /*
-       TODO PROPERTIES
-               selection (long)
-               content (list)
-                       item
+    TODO PROPERTIES
+        selection (long)
+        content (list)
+            item
 */
 
 // ============================================================================
 */
 
 // ============================================================================
@@ -115,17 +115,6 @@ bool wxChoice::Create(wxWindow *parent,
                       const wxValidator& validator,
                       const wxString& name)
 {
                       const wxValidator& validator,
                       const wxString& name)
 {
-    if ( !CreateControl(parent, id, pos, size, style, validator, name) )
-        return FALSE;
-
-    long msStyle = WS_CHILD | CBS_DROPDOWNLIST | WS_TABSTOP | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL;
-    if ( style & wxCB_SORT )
-        msStyle |= CBS_SORT;
-
-    if ( style & wxCLIP_SIBLINGS )
-        msStyle |= WS_CLIPSIBLINGS;
-
-
     // Experience shows that wxChoice vs. wxComboBox distinction confuses
     // quite a few people - try to help them
     wxASSERT_MSG( !(style & wxCB_DROPDOWN) &&
     // Experience shows that wxChoice vs. wxComboBox distinction confuses
     // quite a few people - try to help them
     wxASSERT_MSG( !(style & wxCB_DROPDOWN) &&
@@ -134,19 +123,40 @@ bool wxChoice::Create(wxWindow *parent,
                   _T("this style flag is ignored by wxChoice, you ")
                   _T("probably want to use a wxComboBox") );
 
                   _T("this style flag is ignored by wxChoice, you ")
                   _T("probably want to use a wxComboBox") );
 
-    if ( !MSWCreateControl(wxT("COMBOBOX"), msStyle) )
+    return CreateAndInit(parent, id, pos, size, n, choices, style,
+                         validator, name);
+}
+
+bool wxChoice::CreateAndInit(wxWindow *parent,
+                             wxWindowID id,
+                             const wxPoint& pos,
+                             const wxSize& size,
+                             int n, const wxString choices[],
+                             long style,
+                             const wxValidator& validator,
+                             const wxString& name)
+{
+    // initialize wxControl
+    if ( !CreateControl(parent, id, pos, size, style, validator, name) )
+        return FALSE;
+
+    // now create the real HWND
+    if ( !MSWCreateControl(wxT("COMBOBOX"), _T(""), pos, size) )
         return FALSE;
 
         return FALSE;
 
-    // A choice/combobox normally has a white background (or other, depending
-    // on global settings) rather than inheriting the parent's background colour.
+
+    // choice/combobox normally has "white" (depends on colour scheme, of
+    // course) background rather than inheriting the parent's background
     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
 
     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
 
+    // initialize the controls contents
     for ( int i = 0; i < n; i++ )
     {
         Append(choices[i]);
     }
 
     for ( int i = 0; i < n; i++ )
     {
         Append(choices[i]);
     }
 
-    SetSize(pos.x, pos.y, size.x, size.y);
+    // and now we may finally size the control properly (if needed)
+    SetBestSize(size);
 
     return TRUE;
 }
 
     return TRUE;
 }
@@ -165,6 +175,26 @@ bool wxChoice::Create(wxWindow *parent,
                   style, validator, name);
 }
 
                   style, validator, name);
 }
 
+WXDWORD wxChoice::MSWGetStyle(long style, WXDWORD *exstyle) const
+{
+    // we never have an external border
+    WXDWORD msStyle = wxControl::MSWGetStyle
+                      (
+                        (style & ~wxBORDER_MASK) | wxBORDER_NONE, exstyle
+                      );
+
+    // WS_CLIPSIBLINGS is useful with wxChoice and doesn't seem to result in
+    // any problems
+    msStyle |= WS_CLIPSIBLINGS;
+
+    // wxChoice-specific styles
+    msStyle |= CBS_DROPDOWNLIST | WS_HSCROLL | WS_VSCROLL;
+    if ( style & wxCB_SORT )
+        msStyle |= CBS_SORT;
+
+    return msStyle;
+}
+
 wxChoice::~wxChoice()
 {
     Free();
 wxChoice::~wxChoice()
 {
     Free();
@@ -176,11 +206,17 @@ wxChoice::~wxChoice()
 
 int wxChoice::DoAppend(const wxString& item)
 {
 
 int wxChoice::DoAppend(const wxString& item)
 {
-    int n = (int)SendMessage(GetHwnd(), CB_ADDSTRING, 0, (LONG)item.c_str());
+    int n = (int)SendMessage(GetHwnd(), CB_ADDSTRING, 0, (LPARAM)item.c_str());
     if ( n == CB_ERR )
     {
         wxLogLastError(wxT("SendMessage(CB_ADDSTRING)"));
     }
     if ( n == CB_ERR )
     {
         wxLogLastError(wxT("SendMessage(CB_ADDSTRING)"));
     }
+    else // ok
+    {
+        // we need to refresh our size in order to have enough space for the
+        // newly added items
+        UpdateVisibleHeight();
+    }
 
     return n;
 }
 
     return n;
 }
@@ -190,11 +226,15 @@ int wxChoice::DoInsert(const wxString& item, int pos)
     wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
     wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index"));
 
     wxCHECK_MSG(!(GetWindowStyle() & wxCB_SORT), -1, wxT("can't insert into sorted list"));
     wxCHECK_MSG((pos>=0) && (pos<=GetCount()), -1, wxT("invalid index"));
 
-    int n = (int)SendMessage(GetHwnd(), CB_INSERTSTRING, pos, (LONG)item.c_str());
+    int n = (int)SendMessage(GetHwnd(), CB_INSERTSTRING, pos, (LPARAM)item.c_str());
     if ( n == CB_ERR )
     {
         wxLogLastError(wxT("SendMessage(CB_INSERTSTRING)"));
     }
     if ( n == CB_ERR )
     {
         wxLogLastError(wxT("SendMessage(CB_INSERTSTRING)"));
     }
+    else // ok
+    {
+        UpdateVisibleHeight();
+    }
 
     return n;
 }
 
     return n;
 }
@@ -209,6 +249,8 @@ void wxChoice::Delete(int n)
     }
 
     SendMessage(GetHwnd(), CB_DELETESTRING, n, 0);
     }
 
     SendMessage(GetHwnd(), CB_DELETESTRING, n, 0);
+
+    UpdateVisibleHeight();
 }
 
 void wxChoice::Clear()
 }
 
 void wxChoice::Clear()
@@ -216,6 +258,8 @@ void wxChoice::Clear()
     Free();
 
     SendMessage(GetHwnd(), CB_RESETCONTENT, 0, 0);
     Free();
 
     SendMessage(GetHwnd(), CB_RESETCONTENT, 0, 0);
+
+    UpdateVisibleHeight();
 }
 
 void wxChoice::Free()
 }
 
 void wxChoice::Free()
@@ -367,9 +411,10 @@ wxClientData* wxChoice::DoGetItemClientObject( int n ) const
 // wxMSW specific helpers
 // ----------------------------------------------------------------------------
 
 // wxMSW specific helpers
 // ----------------------------------------------------------------------------
 
-int wxChoice::GetVisibleHeight() const
+void wxChoice::UpdateVisibleHeight()
 {
 {
-    return ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, (WPARAM)-1, 0);
+    // be careful to not change the width here
+    DoSetSize(-1, -1, -1, GetSize().y, wxSIZE_USE_EXISTING);
 }
 
 void wxChoice::DoMoveWindow(int x, int y, int width, int height)
 }
 
 void wxChoice::DoMoveWindow(int x, int y, int width, int height)
@@ -392,13 +437,11 @@ void wxChoice::DoMoveWindow(int x, int y, int width, int height)
 
 void wxChoice::DoGetSize(int *w, int *h) const
 {
 
 void wxChoice::DoGetSize(int *w, int *h) const
 {
+    // this is weird: sometimes, the height returned by Windows is clearly the
+    // total height of the control including the drop down list -- but only
+    // sometimes, and normally it isn't... I have no idea about what to do with
+    // this
     wxControl::DoGetSize(w, h);
     wxControl::DoGetSize(w, h);
-
-    // we need to return only the height of the visible part, not the entire
-    // height in the Windows sense which includes the height of the drop down
-    // list as well
-    if ( h )
-        *h = GetVisibleHeight();
 }
 
 void wxChoice::DoSetSize(int x, int y,
 }
 
 void wxChoice::DoSetSize(int x, int y,
@@ -432,10 +475,11 @@ void wxChoice::DoSetSize(int x, int y,
     // as it is not affected by normal WM_SETSIZE
     if ( height != -1 )
     {
     // as it is not affected by normal WM_SETSIZE
     if ( height != -1 )
     {
-        const int hVisibleCurrent = GetVisibleHeight();
-        if ( hVisibleCurrent != heightOrig )
+        const int delta = heightOrig - GetSize().y;
+        if ( delta )
         {
         {
-            SendMessage(GetHwnd(), CB_SETITEMHEIGHT, (WPARAM)-1, heightOrig);
+            int h = ::SendMessage(GetHwnd(), CB_GETITEMHEIGHT, (WPARAM)-1, 0);
+            SendMessage(GetHwnd(), CB_SETITEMHEIGHT, (WPARAM)-1, h + delta);
         }
     }
 }
         }
     }
 }
@@ -461,10 +505,10 @@ wxSize wxChoice::DoGetBestSize() const
     // the combobox should be slightly larger than the widest string
     wChoice += 5*GetCharWidth();
 
     // the combobox should be slightly larger than the widest string
     wChoice += 5*GetCharWidth();
 
-    return wxSize(wChoice, GetVisibleHeight());
+    return wxSize(wChoice, EDIT_HEIGHT_FROM_CHAR_HEIGHT(GetCharHeight()));
 }
 
 }
 
-long wxChoice::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
+WXLRESULT wxChoice::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
     if ( nMsg == WM_LBUTTONUP )
     {
 {
     if ( nMsg == WM_LBUTTONUP )
     {