]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/listbox.cpp
wxWindow::FindFocus() doesn't exist in wxGTK - #ifdef'd out
[wxWidgets.git] / src / msw / listbox.cpp
index 3971e400ee46b56530f14e3e65a5146bdc2aea27..0ffc6ec3c85bafb28013c3b1be100a2a11e63d72 100644 (file)
@@ -42,6 +42,9 @@
   #include  "wx/ownerdrw.h"
 #endif
 
+#include "wx/dynarray.h"
+#include "wx/log.h"
+
 #if !USE_SHARED_LIBRARY
   IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
 #endif
@@ -78,7 +81,7 @@ wxOwnerDrawn *wxListBox::CreateItem(uint n)
 // this macro is dangerous but still better than tons of (HWND)GetHWND()
 #define   hwnd    (HWND)GetHWND()
 
-bool wxListBox::MSWCommand(const WXUINT param, const WXWORD WXUNUSED(id))
+bool wxListBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
 {
 /*
   if (param == LBN_SELCANCEL)
@@ -89,11 +92,11 @@ bool wxListBox::MSWCommand(const WXUINT param, const WXWORD WXUNUSED(id))
   if (param == LBN_SELCHANGE)
   {
     wxCommandEvent event(wxEVT_COMMAND_LISTBOX_SELECTED, m_windowId);
-    int *liste = NULL;
-    int count = GetSelections(&liste) ;
-    if (count && liste)
+    wxArrayInt aSelections;
+    int count = GetSelections(aSelections);
+    if ( count > 0 )
     {
-      event.m_commandInt = liste[0] ;
+      event.m_commandInt = aSelections[0] ;
       event.m_clientData = GetClientData(event.m_commandInt);
       wxString str(GetString(event.m_commandInt));
       if (str != "")
@@ -115,7 +118,9 @@ bool wxListBox::MSWCommand(const WXUINT param, const WXWORD WXUNUSED(id))
   {
     wxCommandEvent event(wxEVT_COMMAND_LISTBOX_DOUBLECLICKED, m_windowId);
     event.SetEventObject( this );
-    if ( !GetEventHandler()->ProcessEvent(event) )
+    GetEventHandler()->ProcessEvent(event) ;
+    return TRUE;
+/*
     {
 #if WXWIN_COMPATIBILITY
       wxWindow *parent = (wxWindow *)GetParent();
@@ -124,6 +129,7 @@ bool wxListBox::MSWCommand(const WXUINT param, const WXWORD WXUNUSED(id))
 #endif
       return TRUE;
     }
+ */
   }
   return FALSE;
 }
@@ -133,21 +139,19 @@ wxListBox::wxListBox(void)
 {
   m_noItems = 0;
   m_selected = 0;
-  m_selections = NULL;
 }
 
-bool wxListBox::Create(wxWindow *parent, const wxWindowID id,
+bool wxListBox::Create(wxWindow *parent, wxWindowID id,
                        const wxPoint& pos,
                        const wxSize& size,
-                       const int n, const wxString choices[],
-                       const long style,
+                       int n, const wxString choices[],
+                       long style,
                        const wxValidator& validator,
                        const wxString& name)
 {
   m_noItems = n;
   m_hWnd = 0;
   m_selected = 0;
-  m_selections = NULL;
 
   SetName(name);
   SetValidator(validator);
@@ -184,13 +188,10 @@ bool wxListBox::Create(wxWindow *parent, const wxWindowID id,
       // we don't support LBS_OWNERDRAWVARIABLE yet
       wstyle |= LBS_OWNERDRAWFIXED;
     }
-#else
-  // Change from previous versions of wxWin: JACS Nov. 1995
-  // Not sure whether to have integral, or no integral
-  // style. With the latter we may get partial items showing.
-  // VZ: also it makes life more difficult for owner-drawn controls
-    wstyle |= LBS_NOINTEGRALHEIGHT;
 #endif
+  // Without this style, you get unexpected heights, so e.g. constraint layout
+  // doesn't work properly
+  wstyle |= LBS_NOINTEGRALHEIGHT;
 
   bool want3D;
   WXDWORD exStyle = Determine3DEffects(WS_EX_CLIENTEDGE, &want3D) ;
@@ -209,6 +210,9 @@ bool wxListBox::Create(wxWindow *parent, const wxWindowID id,
                                 0, 0, 0, 0, 
                                 (HWND)parent->GetHWND(), (HMENU)m_windowId,
                                 wxGetInstance(), NULL);
+
+  m_hWnd = (WXHWND)wx_list;
+
 #if CTL3D
   if (want3D)
   {
@@ -217,12 +221,15 @@ bool wxListBox::Create(wxWindow *parent, const wxWindowID id,
   }
 #endif
 
+  // Subclass again to catch messages
+  SubclassWin((WXHWND)wx_list);
+
   uint ui;
   for (ui = 0; ui < (uint)n; ui++) {
     SendMessage(wx_list, LB_ADDSTRING, 0, (LPARAM)(const char *)choices[ui]);
   }
 
-  #if USE_OWNER_DRAWN
+#if USE_OWNER_DRAWN
     if ( m_windowStyle & wxLB_OWNERDRAW ) {
       for (ui = 0; ui < (uint)n; ui++) {
         // create new item which will process WM_{DRAW|MEASURE}ITEM messages
@@ -232,35 +239,28 @@ bool wxListBox::Create(wxWindow *parent, const wxWindowID id,
         ListBox_SetItemData(wx_list, ui, pNewItem);
       }
     }
-  #endif
+#endif
 
   if ((m_windowStyle & wxLB_MULTIPLE) == 0)
     SendMessage(wx_list, LB_SETCURSEL, 0, 0);
 
-  ShowWindow(wx_list, SW_SHOW);
-
-  m_hWnd = (WXHWND)wx_list;
-
-  // Subclass again for purposes of dialog editing mode
-  SubclassWin((WXHWND)wx_list);
-
   SetFont(* parent->GetFont());
 
   SetSize(x, y, width, height);
 
+  ShowWindow(wx_list, SW_SHOW);
+
   return TRUE;
 }
 
 wxListBox::~wxListBox(void)
 {
-  #if USE_OWNER_DRAWN
+#if USE_OWNER_DRAWN
     uint uiCount = m_aItems.Count();
     while ( uiCount-- != 0 ) {
       delete m_aItems[uiCount];
     }
-  #endif
-
-  DELETEA(m_selections);
+#endif
 }
 
 void wxListBox::SetupColours(void)
@@ -269,7 +269,7 @@ void wxListBox::SetupColours(void)
   SetForegroundColour(GetParent()->GetDefaultForegroundColour());
 }
 
-void wxListBox::SetFirstItem(const int N)
+void wxListBox::SetFirstItem(int N)
 {
   SendMessage(hwnd,LB_SETTOPINDEX,(WPARAM)N,(LPARAM)0) ;
 }
@@ -282,7 +282,7 @@ void wxListBox::SetFirstItem(const wxString& s)
     SetFirstItem(N) ;
 }
 
-void wxListBox::Delete(const int N)
+void wxListBox::Delete(int N)
 {
   SendMessage(hwnd, LB_DELETESTRING, N, 0);
   m_noItems --;
@@ -294,14 +294,14 @@ void wxListBox::Append(const wxString& item)
   int index = ListBox_AddString(hwnd, item);
   m_noItems ++;
 
-  #if USE_OWNER_DRAWN
+#if USE_OWNER_DRAWN
     if ( m_windowStyle & wxLB_OWNERDRAW ) {
       wxOwnerDrawn *pNewItem = CreateItem(-1); // dummy argument
       pNewItem->SetName(item);
       m_aItems.Add(pNewItem);
       ListBox_SetItemData(hwnd, index, pNewItem);
     }
-  #endif
+#endif
 
   SetHorizontalExtent(item);
 }
@@ -311,20 +311,20 @@ void wxListBox::Append(const wxString& item, char *Client_data)
   int index = ListBox_AddString(hwnd, item);
   m_noItems ++;
 
-  #if USE_OWNER_DRAWN
+#if USE_OWNER_DRAWN
     if ( m_windowStyle & wxLB_OWNERDRAW ) {
       // client data must be pointer to wxOwnerDrawn, otherwise we would crash
       // in OnMeasure/OnDraw.
       wxFAIL_MSG("Can't use client data with owner-drawn listboxes");
     }
     else
-  #endif
+#endif
       ListBox_SetItemData(hwnd, index, Client_data);
 
   SetHorizontalExtent(item);
 }
 
-void wxListBox::Set(const int n, const wxString *choices, char** clientData)
+void wxListBox::Set(int n, const wxString *choices, char** clientData)
 {
   ShowWindow(hwnd, SW_HIDE);
   ListBox_ResetContent(hwnd);
@@ -337,7 +337,7 @@ void wxListBox::Set(const int n, const wxString *choices, char** clientData)
   }
   m_noItems = n;
 
-  #if USE_OWNER_DRAWN
+#if USE_OWNER_DRAWN
     if ( m_windowStyle & wxLB_OWNERDRAW ) {
       // first delete old items
       uint ui = m_aItems.Count();
@@ -357,7 +357,7 @@ void wxListBox::Set(const int n, const wxString *choices, char** clientData)
                      "Can't use client data with owner-drawn listboxes");
       }
     }
-  #endif
+#endif
 
   SetHorizontalExtent("");
   ShowWindow(hwnd, SW_SHOW);
@@ -380,7 +380,7 @@ void wxListBox::Clear(void)
   ListBox_GetHorizontalExtent(hwnd);
 }
 
-void wxListBox::SetSelection(const int N, const bool select)
+void wxListBox::SetSelection(int N, bool select)
 {
   if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
     SendMessage(hwnd, LB_SETSEL, select, N);
@@ -393,85 +393,73 @@ void wxListBox::SetSelection(const int N, const bool select)
   }
 }
 
-bool wxListBox::Selected(const int N) const
+bool wxListBox::Selected(int N) const
 {
   return SendMessage(hwnd, LB_GETSEL, N, 0) == 0 ? FALSE : TRUE;
 }
 
-void wxListBox::Deselect(const int N)
+void wxListBox::Deselect(int N)
 {
   if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
     SendMessage(hwnd, LB_SETSEL, FALSE, N);
 }
 
-char *wxListBox::GetClientData(const int N) const
+char *wxListBox::GetClientData(int N) const
 {
   return (char *)SendMessage(hwnd, LB_GETITEMDATA, N, 0);
 }
 
-void wxListBox::SetClientData(const int N, char *Client_data)
+void wxListBox::SetClientData(int N, char *Client_data)
 {
-  (void)SendMessage(hwnd, LB_SETITEMDATA, N, (LONG)Client_data);
-/*
-  if (result == LB_ERR)
-      return -1;
-  else
-      return 0;
- */
+  if ( ListBox_SetItemData(hwnd, N, Client_data) == LB_ERR )
+    wxLogDebug("LB_SETITEMDATA failed");
 }
 
 // Return number of selections and an array of selected integers
-// Use selections field to store data, which will be cleaned up
-// by destructor if necessary.
-int wxListBox::GetSelections(int **list_selections) const
+int wxListBox::GetSelections(wxArrayInt& aSelections) const
 {
-  wxListBox *nonConst = (wxListBox *)this; // const is a white lie!
-  if (nonConst->m_selections)
-    { delete[] nonConst->m_selections; nonConst->m_selections = NULL; };
+  aSelections.Empty();
+
   if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
   {
-    int no_sel = (int)SendMessage(hwnd, LB_GETSELCOUNT, 0, 0);
-    if (no_sel == 0)
-      return 0;
-    nonConst->m_selections = new int[no_sel];
-    SendMessage(hwnd, LB_GETSELITEMS, no_sel, (LONG)m_selections);
-    *list_selections = m_selections;
+    int no_sel = ListBox_GetSelCount(hwnd);
+    if (no_sel != 0) {
+      int *selections = new int[no_sel];
+      if ( ListBox_GetSelItems(hwnd, no_sel, selections) == LB_ERR ) {
+        wxFAIL_MSG("This listbox can't have single-selection style!");
+      }
+
+      aSelections.Alloc(no_sel);
+      for ( int n = 0; n < no_sel; n++ )
+        aSelections.Add(selections[n]);
+
+      delete [] selections;
+    }
+
     return no_sel;
   }
-  else
+  else  // single-selection listbox
   {
-    int sel = (int)SendMessage(hwnd, LB_GETCURSEL, 0, 0);
-    if (sel == LB_ERR)
-      return 0;
-    nonConst->m_selections = new int[1];
-    nonConst->m_selections[0] = sel;
-    *list_selections = m_selections;
+    aSelections.Add(ListBox_GetCurSel(hwnd));
+
     return 1;
   }
 }
 
 // Get single selection, for single choice list items
-int wxListBox::GetSelection(void) const
+int wxListBox::GetSelection() const
 {
-  wxListBox *nonConst = (wxListBox *)this; // const is a white lie!
-  if (nonConst->m_selections)
-    { delete[] nonConst->m_selections; nonConst->m_selections = NULL; };
-  if ((m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED))
-    return -1;
-  else
-  {
-    int sel = (int)SendMessage(hwnd, LB_GETCURSEL, 0, 0);
-    if (sel == LB_ERR)
-      return -1;
-    else
-    {
-      return sel;
-    }
-  }
+  wxCHECK_MSG( !(m_windowStyle & wxLB_MULTIPLE) && 
+               !(m_windowStyle & wxLB_EXTENDED), 
+               -1,
+               "GetSelection() can't be used with multiple-selection "
+               "listboxes, use GetSelections() instead." );
+
+  return ListBox_GetCurSel(hwnd);
 }
 
 // Find string for position
-wxString wxListBox::GetString(const int N) const
+wxString wxListBox::GetString(int N) const
 {
   if (N < 0 || N > m_noItems)
     return wxString("");
@@ -481,7 +469,7 @@ wxString wxListBox::GetString(const int N) const
   return wxString(wxBuffer);
 }
 
-void wxListBox::SetSize(const int x, const int y, const int width, const int height, const int sizeFlags)
+void wxListBox::SetSize(int x, int y, int width, int height, int sizeFlags)
 {
   int currentX, currentY;
   GetPosition(&currentX, &currentY);
@@ -532,16 +520,6 @@ void wxListBox::SetSize(const int x, const int y, const int width, const int hei
   MoveWindow(hwnd, (int)control_x, (int)control_y,
                    (int)control_width, (int)control_height, TRUE);
 
-/*
-#if WXWIN_COMPATIBILITY
-  GetEventHandler()->OldOnSize(width, height);
-#else
-  wxSizeEvent event(wxSize(width, height), m_windowId);
-  event.eventObject = this;
-  GetEventHandler()->ProcessEvent(event);
-#endif
-*/
-
 }
 
 // Windows-specific code to set the horizontal extent of
@@ -605,7 +583,7 @@ void wxListBox::SetHorizontalExtent(const wxString& s)
 }
 
 void
-wxListBox::InsertItems(const int nItems, const wxString items[], const int pos)
+wxListBox::InsertItems(int nItems, const wxString items[], int pos)
 {
   int i;
   for (i = 0; i < nItems; i++)
@@ -626,7 +604,7 @@ wxListBox::InsertItems(const int nItems, const wxString items[], const int pos)
   SetHorizontalExtent("");
 }
 
-void wxListBox::SetString(const int N, const wxString& s)
+void wxListBox::SetString(int N, const wxString& s)
 {
   int sel = GetSelection();
   
@@ -646,10 +624,11 @@ void wxListBox::SetString(const int N, const wxString& s)
   if (sel >= 0)
     SetSelection(sel);
 
-  #if       USE_OWNER_DRAWN
-    // update item's text
-    m_aItems[N]->SetName(s);
-  #endif  //USE_OWNER_DRAWN
+#if       USE_OWNER_DRAWN
+  if ( m_windowStyle & wxLB_OWNERDRAW )
+         // update item's text
+         m_aItems[N]->SetName(s);
+#endif  //USE_OWNER_DRAWN
 }
 
 int wxListBox::Number (void) const
@@ -667,7 +646,7 @@ wxString wxListBox::GetStringSelection (void) const
     return wxString("");
 }
 
-bool wxListBox::SetStringSelection (const wxString& s, const bool flag)
+bool wxListBox::SetStringSelection (const wxString& s, bool flag)
 {
   int sel = FindString (s);
   if (sel > -1)
@@ -697,7 +676,7 @@ void wxListBox::Command (wxCommandEvent & event)
   ProcessCommand (event);
 }
 
-WXHBRUSH wxListBox::OnCtlColor(const WXHDC pDC, const WXHWND pWnd, const WXUINT nCtlColor,
+WXHBRUSH wxListBox::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor,
                        WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
 {
 #if CTL3D
@@ -726,7 +705,7 @@ WXHBRUSH wxListBox::OnCtlColor(const WXHDC pDC, const WXHWND pWnd, const WXUINT
 
 long wxListBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 {
-/*
+#if 0
   switch (nMsg)
   {
         case WM_INITDIALOG:
@@ -745,11 +724,11 @@ long wxListBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
         case WM_MBUTTONDBLCLK:
         case WM_LBUTTONDOWN:
         case WM_LBUTTONUP:
-//        case WM_LBUTTONDBLCLK:
+        case WM_LBUTTONDBLCLK:
         case WM_MOUSEMOVE:
-        case WM_DESTROY:
         case WM_COMMAND:
         case WM_NOTIFY:
+        case WM_DESTROY:
         case WM_MENUSELECT:
         case WM_INITMENUPOPUP:
         case WM_DRAWITEM:
@@ -776,7 +755,8 @@ long wxListBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
                case WM_NCHITTEST:
             return MSWDefWindowProc(nMsg, wParam, lParam );
     }
-*/
+#endif
+
   return wxControl::MSWWindowProc(nMsg, wParam, lParam);
 }
 
@@ -796,7 +776,7 @@ long wxListBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
 bool wxListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
 {
   // only owner-drawn control should receive this message
-  wxCHECK_RET( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
+  wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
 
   MEASUREITEMSTRUCT *pStruct = (MEASUREITEMSTRUCT *)item;
 
@@ -814,13 +794,13 @@ bool wxListBox::MSWOnMeasure(WXMEASUREITEMSTRUCT *item)
 bool wxListBox::MSWOnDraw(WXDRAWITEMSTRUCT *item)
 {
   // only owner-drawn control should receive this message
-  wxCHECK_RET( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
+  wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
 
   DRAWITEMSTRUCT *pStruct = (DRAWITEMSTRUCT *)item;
   wxListBoxItem *pItem = (wxListBoxItem *)SendMessage(hwnd, LB_GETITEMDATA, 
                                                       pStruct->itemID, 0);
 
-  wxCHECK_RET( (int)pItem != LB_ERR, FALSE );
+  wxCHECK( (int)pItem != LB_ERR, FALSE );
 
   wxDC dc;
   dc.SetHDC((WXHDC)pStruct->hDC, FALSE);