X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2bda0e173844e8e0f8acf4e8ad8b5c26e5c6fe5d..6e4739a0e1e6b22dc33e5974cea0d5a4df89e815:/src/msw/listbox.cpp diff --git a/src/msw/listbox.cpp b/src/msw/listbox.cpp index 3971e400ee..0ffc6ec3c8 100644 --- a/src/msw/listbox.cpp +++ b/src/msw/listbox.cpp @@ -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(¤tX, ¤tY); @@ -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);