X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2bda0e173844e8e0f8acf4e8ad8b5c26e5c6fe5d..44c4a3348693414bace13852e50d926c1aa9f08b:/src/msw/listbox.cpp diff --git a/src/msw/listbox.cpp b/src/msw/listbox.cpp index 3971e400ee..40f02d0f05 100644 --- a/src/msw/listbox.cpp +++ b/src/msw/listbox.cpp @@ -38,10 +38,13 @@ #undef GetCharWidth #endif -#if USE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN #include "wx/ownerdrw.h" #endif +#include "wx/dynarray.h" +#include "wx/log.h" + #if !USE_SHARED_LIBRARY IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl) #endif @@ -50,7 +53,7 @@ // list box item declaration and implementation // ============================================================================ -#if USE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN class wxListBoxItem : public wxOwnerDrawn { @@ -64,7 +67,7 @@ wxListBoxItem::wxListBoxItem(const wxString& str) : wxOwnerDrawn(str, FALSE) SetMarginWidth(0); } -wxOwnerDrawn *wxListBox::CreateItem(uint n) +wxOwnerDrawn *wxListBox::CreateItem(size_t n) { return new wxListBoxItem(); } @@ -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_noItems = 0; m_hWnd = 0; m_selected = 0; - m_selections = NULL; SetName(name); SetValidator(validator); @@ -156,7 +160,7 @@ bool wxListBox::Create(wxWindow *parent, const wxWindowID id, wxSystemSettings settings; SetBackgroundColour(settings.GetSystemColour(wxSYS_COLOUR_WINDOW)); - SetForegroundColour(parent->GetDefaultForegroundColour()); + SetForegroundColour(parent->GetForegroundColour()); m_windowId = ( id == -1 ) ? (int)NewControlId() : id; @@ -179,97 +183,93 @@ bool wxListBox::Create(wxWindow *parent, const wxWindowID id, if (m_windowStyle & wxLB_SORT) wstyle |= LBS_SORT; -#if USE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN if ( m_windowStyle & wxLB_OWNERDRAW ) { // 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) ; // Even with extended styles, need to combine with WS_BORDER // for them to look right. - if ( want3D || (m_windowStyle & wxSIMPLE_BORDER) - || (m_windowStyle & wxRAISED_BORDER) - || (m_windowStyle & wxSUNKEN_BORDER) - || (m_windowStyle & wxDOUBLE_BORDER) ) { + if ( want3D || wxStyleHasBorder(m_windowStyle) ) + { wstyle |= WS_BORDER; } - HWND wx_list = CreateWindowEx(exStyle, "LISTBOX", NULL, + m_hWnd = (WXHWND)::CreateWindowEx(exStyle, "LISTBOX", NULL, wstyle | WS_CHILD, 0, 0, 0, 0, (HWND)parent->GetHWND(), (HMENU)m_windowId, wxGetInstance(), NULL); + + wxCHECK_MSG( m_hWnd, FALSE, "Failed to create listbox" ); + #if CTL3D if (want3D) { - Ctl3dSubclassCtl(wx_list); + Ctl3dSubclassCtl(hwnd); m_useCtl3D = TRUE; } #endif - uint ui; - for (ui = 0; ui < (uint)n; ui++) { - SendMessage(wx_list, LB_ADDSTRING, 0, (LPARAM)(const char *)choices[ui]); + // Subclass again to catch messages + SubclassWin(m_hWnd); + + size_t ui; + for (ui = 0; ui < (size_t)n; ui++) { + Append(choices[ui]); } - #if USE_OWNER_DRAWN + /* Not needed -- done in Append +#if wxUSE_OWNER_DRAWN if ( m_windowStyle & wxLB_OWNERDRAW ) { - for (ui = 0; ui < (uint)n; ui++) { + for (ui = 0; ui < (size_t)n; ui++) { // create new item which will process WM_{DRAW|MEASURE}ITEM messages wxOwnerDrawn *pNewItem = CreateItem(ui); pNewItem->SetName(choices[ui]); m_aItems.Add(pNewItem); - ListBox_SetItemData(wx_list, ui, pNewItem); + ListBox_SetItemData(hwnd, ui, pNewItem); } } - #endif - - if ((m_windowStyle & wxLB_MULTIPLE) == 0) - SendMessage(wx_list, LB_SETCURSEL, 0, 0); - - ShowWindow(wx_list, SW_SHOW); - - m_hWnd = (WXHWND)wx_list; +#endif +*/ - // Subclass again for purposes of dialog editing mode - SubclassWin((WXHWND)wx_list); + if ( (m_windowStyle & wxLB_MULTIPLE) == 0 ) + SendMessage(hwnd, LB_SETCURSEL, 0, 0); - SetFont(* parent->GetFont()); + SetFont(parent->GetFont()); SetSize(x, y, width, height); + Show(TRUE); + return TRUE; } wxListBox::~wxListBox(void) { - #if USE_OWNER_DRAWN - uint uiCount = m_aItems.Count(); +#if wxUSE_OWNER_DRAWN + size_t uiCount = m_aItems.Count(); while ( uiCount-- != 0 ) { delete m_aItems[uiCount]; } - #endif - - DELETEA(m_selections); +#endif } void wxListBox::SetupColours(void) { SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_WINDOW)); - SetForegroundColour(GetParent()->GetDefaultForegroundColour()); + SetForegroundColour(GetParent()->GetForegroundColour()); } -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 wxUSE_OWNER_DRAWN if ( m_windowStyle & wxLB_OWNERDRAW ) { - wxOwnerDrawn *pNewItem = CreateItem(-1); // dummy argument + wxOwnerDrawn *pNewItem = CreateItem(index); // 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 wxUSE_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,17 +337,17 @@ void wxListBox::Set(const int n, const wxString *choices, char** clientData) } m_noItems = n; - #if USE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN if ( m_windowStyle & wxLB_OWNERDRAW ) { // first delete old items - uint ui = m_aItems.Count(); + size_t ui = m_aItems.Count(); while ( ui-- != 0 ) { delete m_aItems[ui]; } m_aItems.Empty(); // then create new ones - for (ui = 0; ui < (uint)n; ui++) { + for (ui = 0; ui < (size_t)n; ui++) { wxOwnerDrawn *pNewItem = CreateItem(ui); pNewItem->SetName(choices[ui]); m_aItems.Add(pNewItem); @@ -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); @@ -496,6 +484,8 @@ void wxListBox::SetSize(const int x, const int y, const int width, const int hei if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) y1 = currentY; + AdjustForParentClientOrigin(x1, y1, sizeFlags); + // If we're prepared to use the existing size, then... if (width == -1 && height == -1 && ((sizeFlags & wxSIZE_AUTO) != wxSIZE_AUTO)) { @@ -505,7 +495,7 @@ void wxListBox::SetSize(const int x, const int y, const int width, const int hei int cx; // button font dimensions int cy; - wxGetCharSize(GetHWND(), &cx, &cy,GetFont()); + wxGetCharSize(GetHWND(), &cx, &cy, & GetFont()); float control_width, control_height, control_x, control_y; @@ -532,16 +522,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 @@ -560,8 +540,8 @@ void wxListBox::SetHorizontalExtent(const wxString& s) int existingExtent = (int)SendMessage(hwnd, LB_GETHORIZONTALEXTENT, 0, 0L); HDC dc = GetWindowDC(hwnd); HFONT oldFont = 0; - if (GetFont() && GetFont()->GetResourceHandle()) - oldFont = ::SelectObject(dc, (HFONT) GetFont()->GetResourceHandle()); + if (GetFont().Ok() && GetFont().GetResourceHandle()) + oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle()); GetTextMetrics(dc, &lpTextMetric); SIZE extentXY; @@ -581,8 +561,8 @@ void wxListBox::SetHorizontalExtent(const wxString& s) int largestExtent = 0; HDC dc = GetWindowDC(hwnd); HFONT oldFont = 0; - if (GetFont() && GetFont()->GetResourceHandle()) - oldFont = ::SelectObject(dc, (HFONT) GetFont()->GetResourceHandle()); + if (GetFont().Ok() && GetFont().GetResourceHandle()) + oldFont = (HFONT) ::SelectObject(dc, (HFONT) GetFont().GetResourceHandle()); GetTextMetrics(dc, &lpTextMetric); int i; @@ -605,19 +585,19 @@ 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++) ListBox_InsertString(hwnd, i + pos, items[i]); m_noItems += nItems; - #if USE_OWNER_DRAWN + #if wxUSE_OWNER_DRAWN if ( m_windowStyle & wxLB_OWNERDRAW ) { for ( i = 0; i < nItems; i++ ) { - wxOwnerDrawn *pNewItem = CreateItem((uint)(pos + i)); + wxOwnerDrawn *pNewItem = CreateItem((size_t)(pos + i)); pNewItem->SetName(items[i]); - m_aItems.Insert(pNewItem, (uint)(pos + i)); + m_aItems.Insert(pNewItem, (size_t)(pos + i)); ListBox_SetItemData(hwnd, i, pNewItem); } } @@ -626,9 +606,11 @@ 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(); + int sel = -1; + if (!(m_windowStyle & wxLB_MULTIPLE) && !(m_windowStyle & wxLB_EXTENDED)) + sel = GetSelection(); char *oldData = (char *)wxListBox::GetClientData(N); @@ -646,10 +628,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 wxUSE_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 +650,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 +680,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 +709,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 +728,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,11 +759,12 @@ long wxListBox::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) case WM_NCHITTEST: return MSWDefWindowProc(nMsg, wParam, lParam ); } -*/ +#endif + return wxControl::MSWWindowProc(nMsg, wParam, lParam); } -#if USE_OWNER_DRAWN +#if wxUSE_OWNER_DRAWN // drawing // ------- @@ -796,7 +780,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 +798,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); @@ -834,4 +818,4 @@ bool wxListBox::MSWOnDraw(WXDRAWITEMSTRUCT *item) } #endif - // USE_OWNER_DRAWN + // wxUSE_OWNER_DRAWN