home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / os2 / listbox.cpp < prev    next >
C/C++ Source or Header  |  2002-12-27  |  30KB  |  964 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Name:        listbox.cpp
  3. // Purpose:     wxListBox
  4. // Author:      David Webster
  5. // Modified by:
  6. // Created:     10/09/99
  7. // RCS-ID:      $Id: LISTBOX.CPP,v 1.23.2.1 2002/12/27 14:49:35 JS Exp $
  8. // Copyright:   (c) David Webster
  9. // Licence:     wxWindows licence
  10. ///////////////////////////////////////////////////////////////////////////////
  11.  
  12. // For compilers that support precompilation, includes "wx.h".
  13. #include "wx/wxprec.h"
  14.  
  15. #include "wx/window.h"
  16. #include "wx/os2/private.h"
  17.  
  18. #ifndef WX_PRECOMP
  19. #include "wx/listbox.h"
  20. #include "wx/settings.h"
  21. #include "wx/brush.h"
  22. #include "wx/font.h"
  23. #include "wx/dc.h"
  24. #include "wx/dcscreen.h"
  25. #include "wx/utils.h"
  26. #include "wx/scrolwin.h"
  27. #endif
  28.  
  29. #define INCL_M
  30. #include <os2.h>
  31.  
  32. #include "wx/dynarray.h"
  33. #include "wx/log.h"
  34.  
  35. #if wxUSE_LISTBOX
  36.  
  37. #if wxUSE_OWNER_DRAWN
  38.     #include  "wx/ownerdrw.h"
  39. #endif
  40.  
  41.   IMPLEMENT_DYNAMIC_CLASS(wxListBox, wxControl)
  42.  
  43. // ============================================================================
  44. // list box item declaration and implementation
  45. // ============================================================================
  46.  
  47. #if wxUSE_OWNER_DRAWN
  48.  
  49. class wxListBoxItem : public wxOwnerDrawn
  50. {
  51. public:
  52.     wxListBoxItem(const wxString& rsStr = "");
  53. };
  54.  
  55. wxListBoxItem::wxListBoxItem(
  56.   const wxString& rsStr
  57. )
  58. : wxOwnerDrawn( rsStr
  59.                ,FALSE
  60.               )
  61. {
  62.     //
  63.     // No bitmaps/checkmarks
  64.     //
  65.     SetMarginWidth(0);
  66. } // end of wxListBoxItem::wxListBoxItem
  67.  
  68. wxOwnerDrawn* wxListBox::CreateItem(
  69.   size_t                            n
  70. )
  71. {
  72.     return new wxListBoxItem();
  73. } // end of wxListBox::CreateItem
  74.  
  75. #endif  //USE_OWNER_DRAWN
  76.  
  77. // ============================================================================
  78. // list box control implementation
  79. // ============================================================================
  80.  
  81. // Listbox item
  82. wxListBox::wxListBox()
  83. {
  84.     m_nNumItems = 0;
  85.     m_nSelected = 0;
  86. } // end of wxListBox::wxListBox
  87.  
  88. bool wxListBox::Create(
  89.   wxWindow*                         pParent
  90. , wxWindowID                        vId
  91. , const wxPoint&                    rPos
  92. , const wxSize&                     rSize
  93. , int                               n
  94. , const wxString                    asChoices[]
  95. , long                              lStyle
  96. , const wxValidator&                rValidator
  97. , const wxString&                   rsName
  98. )
  99. {
  100.     m_nNumItems = 0;
  101.     m_hWnd      = 0;
  102.     m_nSelected = 0;
  103.  
  104.     SetName(rsName);
  105. #if wxUSE_VALIDATORS
  106.     SetValidator(rValidator);
  107. #endif
  108.  
  109.     if (pParent)
  110.         pParent->AddChild(this);
  111.  
  112.     wxSystemSettings                vSettings;
  113.  
  114.     SetBackgroundColour(vSettings.GetSystemColour(wxSYS_COLOUR_WINDOW));
  115.     SetForegroundColour(pParent->GetForegroundColour());
  116.  
  117.     m_windowId = (vId == -1) ? (int)NewControlId() : vId;
  118.  
  119.     int                             nX      = rPos.x;
  120.     int                             nY      = rPos.y;
  121.     int                             nWidth  = rSize.x;
  122.     int                             nHeight = rSize.y;
  123.  
  124.     m_windowStyle = lStyle;
  125.  
  126.     lStyle = WS_VISIBLE;
  127.  
  128.     if (m_windowStyle & wxCLIP_SIBLINGS )
  129.         lStyle |= WS_CLIPSIBLINGS;
  130.     if (m_windowStyle & wxLB_MULTIPLE)
  131.         lStyle |= LS_MULTIPLESEL;
  132.     else if (m_windowStyle & wxLB_EXTENDED)
  133.         lStyle |= LS_EXTENDEDSEL;
  134.     if (m_windowStyle & wxLB_HSCROLL)
  135.         lStyle |= LS_HORZSCROLL;
  136.     if (m_windowStyle & wxLB_OWNERDRAW)
  137.         lStyle |= LS_OWNERDRAW;
  138.  
  139.     //
  140.     // Without this style, you get unexpected heights, so e.g. constraint layout
  141.     // doesn't work properly
  142.     //
  143.     lStyle |= LS_NOADJUSTPOS;
  144.  
  145.     m_hWnd = (WXHWND)::WinCreateWindow( GetWinHwnd(pParent) // Parent
  146.                                        ,WC_LISTBOX          // Default Listbox class
  147.                                        ,"LISTBOX"           // Control's name
  148.                                        ,lStyle              // Initial Style
  149.                                        ,0, 0, 0, 0          // Position and size
  150.                                        ,GetWinHwnd(pParent) // Owner
  151.                                        ,HWND_TOP            // Z-Order
  152.                                        ,(HMENU)m_windowId   // Id
  153.                                        ,NULL                // Control Data
  154.                                        ,NULL                // Presentation Parameters
  155.                                       );
  156.     if (m_hWnd == 0)
  157.     {
  158.         return FALSE;
  159.     }
  160.  
  161.     //
  162.     // Subclass again for purposes of dialog editing mode
  163.     //
  164.     SubclassWin(m_hWnd);
  165.  
  166.     LONG                            lUi;
  167.  
  168.     for (lUi = 0; lUi < (LONG)n; lUi++)
  169.     {
  170.         Append(asChoices[lUi]);
  171.     }
  172.     wxFont*                          pTextFont = new wxFont( 10
  173.                                                             ,wxMODERN
  174.                                                             ,wxNORMAL
  175.                                                             ,wxNORMAL
  176.                                                            );
  177.     SetFont(*pTextFont);
  178.  
  179.     //
  180.     // Set standard wxWindows colors for Listbox items and highlighting
  181.     //
  182.     wxColour                        vColour;
  183.  
  184.     vColour.Set(wxString("WHITE"));
  185.  
  186.     LONG                            lColor = (LONG)vColour.GetPixel();
  187.  
  188.     ::WinSetPresParam( m_hWnd
  189.                       ,PP_HILITEFOREGROUNDCOLOR
  190.                       ,sizeof(LONG)
  191.                       ,(PVOID)&lColor
  192.                      );
  193.     vColour.Set(wxString("NAVY"));
  194.     lColor = (LONG)vColour.GetPixel();
  195.     ::WinSetPresParam( m_hWnd
  196.                       ,PP_HILITEBACKGROUNDCOLOR
  197.                       ,sizeof(LONG)
  198.                       ,(PVOID)&lColor
  199.                      );
  200.  
  201.     SetSize( nX
  202.             ,nY
  203.             ,nWidth
  204.             ,nHeight
  205.            );
  206.     delete pTextFont;
  207.     return TRUE;
  208. } // end of wxListBox::Create
  209.  
  210. wxListBox::~wxListBox()
  211. {
  212. #if wxUSE_OWNER_DRAWN
  213.     size_t                          lUiCount = m_aItems.Count();
  214.  
  215.     while (lUiCount-- != 0)
  216.     {
  217.         delete m_aItems[lUiCount];
  218.     }
  219. #endif // wxUSE_OWNER_DRAWN
  220. } // end of wxListBox::~wxListBox
  221.  
  222. void wxListBox::SetupColours()
  223. {
  224.     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
  225.     SetForegroundColour(GetParent()->GetForegroundColour());
  226. } // end of wxListBox::SetupColours
  227.  
  228. // ----------------------------------------------------------------------------
  229. // implementation of wxListBoxBase methods
  230. // ----------------------------------------------------------------------------
  231.  
  232. void wxListBox::DoSetFirstItem(
  233.   int                               N
  234. )
  235. {
  236.     wxCHECK_RET( N >= 0 && N < m_nNumItems,
  237.                  wxT("invalid index in wxListBox::SetFirstItem") );
  238.  
  239.     ::WinSendMsg(GetHwnd(), LM_SETTOPINDEX, MPFROMLONG(N), (MPARAM)0);
  240. } // end of wxListBox::DoSetFirstItem
  241.  
  242. void wxListBox::Delete(
  243.   int                               N
  244. )
  245. {
  246.     wxCHECK_RET( N >= 0 && N < m_nNumItems,
  247.                  wxT("invalid index in wxListBox::Delete") );
  248.  
  249. #if wxUSE_OWNER_DRAWN
  250.     delete m_aItems[N];
  251.     m_aItems.RemoveAt(N);
  252. #else // !wxUSE_OWNER_DRAWN
  253.     if (HasClientObjectData())
  254.     {
  255.         delete GetClientObject(N);
  256.     }
  257. #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
  258.  
  259.     ::WinSendMsg(GetHwnd(), LM_DELETEITEM, (MPARAM)N, (MPARAM)0);
  260.     m_nNumItems--;
  261. } // end of wxListBox::DoSetFirstItem
  262.  
  263. int wxListBox::DoAppend(
  264.   const wxString&                   rsItem
  265. )
  266. {
  267.     int                             nIndex = 0;
  268.     SHORT                           nIndexType = 0;
  269.  
  270.     if (m_windowStyle & wxLB_SORT)
  271.         nIndexType = LIT_SORTASCENDING;
  272.     else
  273.         nIndexType = LIT_END;
  274.     nIndex = (int)::WinSendMsg(GetHwnd(), LM_INSERTITEM, (MPARAM)nIndexType, (MPARAM)rsItem.c_str());
  275.     m_nNumItems++;
  276.  
  277. #if wxUSE_OWNER_DRAWN
  278.     if (m_windowStyle & wxLB_OWNERDRAW)
  279.     {
  280.         wxOwnerDrawn*               pNewItem = CreateItem(nIndex); // dummy argument
  281.         wxScreenDC                  vDc;
  282.         wxCoord                     vHeight;
  283.  
  284.  
  285.         pNewItem->SetName(rsItem);
  286.         m_aItems.Insert(pNewItem, nIndex);
  287.         ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, (MPARAM)((SHORT)nIndex), MPFROMP(pNewItem));
  288.         pNewItem->SetFont(GetFont());
  289.     }
  290. #endif
  291.     return nIndex;
  292. } // end of wxListBox::DoAppend
  293.  
  294. void wxListBox::DoSetItems(
  295.   const wxArrayString&              raChoices
  296. , void**                            ppClientData
  297. )
  298. {
  299.     BOOL                            bHideAndShow = IsShown();
  300.     int                             nCount = 0;
  301.     int                             i;
  302.     SHORT                           nIndexType = 0;
  303.  
  304.     if (bHideAndShow)
  305.     {
  306.         ::WinShowWindow(GetHwnd(), FALSE);
  307.     }
  308.     ::WinSendMsg(GetHwnd(), LM_DELETEALL, (MPARAM)0, (MPARAM)0);
  309.     m_nNumItems = raChoices.GetCount();
  310.     for (i = 0; i < m_nNumItems; i++)
  311.     {
  312.  
  313.         if (m_windowStyle & wxLB_SORT)
  314.             nIndexType = LIT_SORTASCENDING;
  315.         else
  316.             nIndexType = LIT_END;
  317.         ::WinSendMsg(GetHwnd(), LM_INSERTITEM, (MPARAM)nIndexType, (MPARAM)raChoices[i].c_str());
  318.  
  319.         if (ppClientData)
  320.         {
  321. #if wxUSE_OWNER_DRAWN
  322.             wxASSERT_MSG(ppClientData[i] == NULL,
  323.                          wxT("Can't use client data with owner-drawn listboxes"));
  324. #else // !wxUSE_OWNER_DRAWN
  325.             ::WinSendMsg(WinUtil_GetHwnd(), LM_SETITEMHANDLE, MPFROMLONG(lCount), MPFROMP(ppClientData[i]));
  326. #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
  327.         }
  328.     }
  329.  
  330. #if wxUSE_OWNER_DRAWN
  331.     if ( m_windowStyle & wxLB_OWNERDRAW )
  332.     {
  333.         //
  334.         // First delete old items
  335.         //
  336.         WX_CLEAR_ARRAY(m_aItems);
  337.  
  338.         //
  339.         // Then create new ones
  340.         //
  341.         for (size_t ui = 0; ui < (size_t)m_nNumItems; ui++)
  342.         {
  343.             wxOwnerDrawn*           pNewItem = CreateItem(ui);
  344.  
  345.             pNewItem->SetName(raChoices[ui]);
  346.             m_aItems.Add(pNewItem);
  347.             ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, MPFROMLONG(ui), MPFROMP(pNewItem));
  348.         }
  349.     }
  350. #endif // wxUSE_OWNER_DRAWN
  351.     ::WinShowWindow(GetHwnd(), TRUE);
  352. } // end of wxListBox::DoSetItems
  353.  
  354. int wxListBox::FindString(
  355.   const wxString&                   rsString
  356. ) const
  357. {
  358.     int                             nPos;
  359.     LONG                            lTextLength;
  360.     PSZ                             zStr;
  361.  
  362.  
  363.     for (nPos = 0; nPos < m_nNumItems; nPos++)
  364.     {
  365.         lTextLength = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH, (MPARAM)nPos, (MPARAM)0));
  366.         zStr = new char[lTextLength + 1];
  367.         ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT, MPFROM2SHORT(nPos, (SHORT)lTextLength), (MPARAM)zStr);
  368.         if (rsString == (char*)zStr)
  369.         {
  370.             delete [] zStr;
  371.             break;
  372.         }
  373.         delete [] zStr;
  374.     }
  375.     return nPos;
  376. } // end of wxListBox::FindString
  377.  
  378. void wxListBox::Clear()
  379. {
  380. #if wxUSE_OWNER_DRAWN
  381.     size_t                          lUiCount = m_aItems.Count();
  382.  
  383.     while (lUiCount-- != 0)
  384.     {
  385.         delete m_aItems[lUiCount];
  386.     }
  387.  
  388.     m_aItems.Clear();
  389. #else // !wxUSE_OWNER_DRAWN
  390.     if (HasClientObjectData())
  391.     {
  392.         for (size_t n = 0; n < (size_t)m_lNumItems; n++)
  393.         {
  394.             delete GetClientObject(n);
  395.         }
  396.     }
  397. #endif // wxUSE_OWNER_DRAWN/!wxUSE_OWNER_DRAWN
  398.     ::WinSendMsg(GetHwnd(), LM_DELETEALL, (MPARAM)0, (MPARAM)0);
  399.  
  400.     m_nNumItems = 0;
  401. } // end of wxListBox::Clear
  402.  
  403. void wxListBox::SetSelection(
  404.   int                               N
  405. , bool                              bSelect
  406. )
  407. {
  408.     wxCHECK_RET( N >= 0 && N < m_nNumItems,
  409.                  wxT("invalid index in wxListBox::SetSelection") );
  410.     ::WinSendMsg( GetHwnd()
  411.                  ,LM_SELECTITEM
  412.                  ,MPFROMLONG(N)
  413.                  ,(MPARAM)bSelect
  414.                 );
  415.     if(m_windowStyle & wxLB_OWNERDRAW)
  416.         Refresh();
  417. } // end of wxListBox::SetSelection
  418.  
  419. bool wxListBox::IsSelected(
  420.   int                               N
  421. ) const
  422. {
  423.     wxCHECK_MSG( N >= 0 && N < m_nNumItems, FALSE,
  424.                  wxT("invalid index in wxListBox::Selected") );
  425.  
  426.     LONG                            lItem;
  427.  
  428.     if (GetWindowStyleFlag() & wxLB_EXTENDED)
  429.     {
  430.         if (N == 0)
  431.             lItem = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)LIT_FIRST, (MPARAM)0));
  432.         else
  433.             lItem = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)(N - 1), (MPARAM)0));
  434.     }
  435.     else
  436.     {
  437.         lItem = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYSELECTION, (MPARAM)LIT_FIRST, (MPARAM)0));
  438.     }
  439.     return (lItem == (LONG)N && lItem != LIT_NONE);
  440. } // end of wxListBox::IsSelected
  441.  
  442. wxClientData* wxListBox::DoGetItemClientObject(
  443.   int                               n
  444. ) const
  445. {
  446.     return (wxClientData *)DoGetItemClientData(n);
  447. }
  448.  
  449. void* wxListBox::DoGetItemClientData(
  450.   int                               n
  451. ) const
  452. {
  453.     wxCHECK_MSG( n >= 0 && n < m_nNumItems, NULL,
  454.                  wxT("invalid index in wxListBox::GetClientData") );
  455.  
  456.     return((void *)::WinSendMsg(GetHwnd(), LM_QUERYITEMHANDLE, MPFROMLONG(n), (MPARAM)0));
  457. } // end of wxListBox::DoGetItemClientData
  458.  
  459. void wxListBox::DoSetItemClientObject(
  460.   int                               n
  461. , wxClientData*                     pClientData
  462. )
  463. {
  464.     DoSetItemClientData( n
  465.                         ,pClientData
  466.                        );
  467. } // end of wxListBox::DoSetItemClientObject
  468.  
  469. void wxListBox::DoSetItemClientData(
  470.   int                               n
  471. , void*                             pClientData
  472. )
  473. {
  474.     wxCHECK_RET( n >= 0 && n < m_nNumItems,
  475.                  wxT("invalid index in wxListBox::SetClientData") );
  476.  
  477. #if wxUSE_OWNER_DRAWN
  478.     if ( m_windowStyle & wxLB_OWNERDRAW )
  479.     {
  480.         //
  481.         // Client data must be pointer to wxOwnerDrawn, otherwise we would crash
  482.         // in OnMeasure/OnDraw.
  483.         //
  484.         wxFAIL_MSG(wxT("Can't use client data with owner-drawn listboxes"));
  485.     }
  486. #endif // wxUSE_OWNER_DRAWN
  487.  
  488.     ::WinSendMsg(GetHwnd(), LM_SETITEMHANDLE, MPFROMLONG(n), MPFROMP(pClientData));
  489. } // end of wxListBox::DoSetItemClientData
  490.  
  491. bool wxListBox::HasMultipleSelection() const
  492. {
  493.     return (m_windowStyle & wxLB_MULTIPLE) || (m_windowStyle & wxLB_EXTENDED);
  494. } // end of wxListBox::HasMultipleSelection
  495.  
  496. int wxListBox::GetSelections(
  497.   wxArrayInt&                       raSelections
  498. ) const
  499. {
  500.     int                             nCount = 0;
  501.     LONG                            lItem;
  502.  
  503.  
  504.     raSelections.Empty();
  505.     if (HasMultipleSelection())
  506.     {
  507.         lItem = LONGFROMMR(::WinSendMsg( GetHwnd()
  508.                                         ,LM_QUERYSELECTION
  509.                                         ,(MPARAM)LIT_FIRST
  510.                                         ,(MPARAM)0
  511.                                        )
  512.                           );
  513.         if (lItem != LIT_NONE)
  514.         {
  515.             nCount++;
  516.             while ((lItem = LONGFROMMR(::WinSendMsg( GetHwnd()
  517.                                                     ,LM_QUERYSELECTION
  518.                                                     ,(MPARAM)lItem
  519.                                                     ,(MPARAM)0
  520.                                                    )
  521.                                       )) != LIT_NONE)
  522.             {
  523.                 nCount++;
  524.             }
  525.             raSelections.Alloc(nCount);
  526.             lItem = LONGFROMMR(::WinSendMsg( GetHwnd()
  527.                                             ,LM_QUERYSELECTION
  528.                                             ,(MPARAM)LIT_FIRST
  529.                                             ,(MPARAM)0
  530.                                            )
  531.                               );
  532.  
  533.             raSelections.Add((int)lItem);
  534.             while ((lItem = LONGFROMMR(::WinSendMsg( GetHwnd()
  535.                                                     ,LM_QUERYSELECTION
  536.                                                     ,(MPARAM)lItem
  537.                                                     ,(MPARAM)0
  538.                                                    )
  539.                                       )) != LIT_NONE)
  540.             {
  541.                 raSelections.Add((int)lItem);
  542.             }
  543.             return nCount;
  544.         }
  545.         return 0;
  546.     }
  547.     else  // single-selection listbox
  548.     {
  549.         lItem = LONGFROMMR(::WinSendMsg( GetHwnd()
  550.                                         ,LM_QUERYSELECTION
  551.                                         ,(MPARAM)LIT_FIRST
  552.                                         ,(MPARAM)0
  553.                                        )
  554.                           );
  555.         raSelections.Add((int)lItem);
  556.         return 1;
  557.     }
  558.     return 0;
  559. } // end of wxListBox::GetSelections
  560.  
  561. int wxListBox::GetSelection() const
  562. {
  563.     wxCHECK_MSG( !HasMultipleSelection(),
  564.                  -1,
  565.                  wxT("GetSelection() can't be used with multiple-selection "
  566.                     "listboxes, use GetSelections() instead.") );
  567.  
  568.     return(LONGFROMMR(::WinSendMsg( GetHwnd()
  569.                                    ,LM_QUERYSELECTION
  570.                                    ,(MPARAM)LIT_FIRST
  571.                                    ,(MPARAM)0
  572.                                   )
  573.                      ));
  574. } // end of wxListBox::GetSelection
  575.  
  576. wxString wxListBox::GetString(
  577.   int                               N
  578. ) const
  579. {
  580.     LONG                            lLen = 0;
  581.     char*                           zBuf;
  582.     wxString                        sResult;
  583.  
  584.     wxCHECK_MSG( N >= 0 && N < m_nNumItems, "",
  585.                  wxT("invalid index in wxListBox::GetClientData") );
  586.  
  587.     lLen = LONGFROMMR(::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXTLENGTH, (MPARAM)N, (MPARAM)0));
  588.     zBuf = new char[lLen + 1];
  589.     ::WinSendMsg(GetHwnd(), LM_QUERYITEMTEXT, MPFROM2SHORT((SHORT)N, (SHORT)lLen), (MPARAM)zBuf);
  590.     zBuf[lLen] = '\0';
  591.     sResult = zBuf;
  592.     delete [] zBuf;
  593.     return sResult;
  594. } // end of wxListBox::GetString
  595.  
  596. void wxListBox::DoInsertItems(
  597.   const wxArrayString&              asItems
  598. , int                               nPos
  599. )
  600. {
  601.     wxCHECK_RET( nPos >= 0 && nPos <= m_nNumItems,
  602.                  wxT("invalid index in wxListBox::InsertItems") );
  603.  
  604.     int                             nItems = asItems.GetCount();
  605.  
  606.     for (int i = 0; i < nItems; i++)
  607.     {
  608.         int                         nIndex = (int)::WinSendMsg( GetHwnd()
  609.                                                                ,LM_INSERTITEM
  610.                                                                ,MPFROMLONG((LONG)(i + nPos))
  611.                                                                ,(MPARAM)asItems[i].c_str()
  612.                                                               );
  613.  
  614.         wxOwnerDrawn*               pNewItem = CreateItem(nIndex);
  615.  
  616.         pNewItem->SetName(asItems[i]);
  617.         pNewItem->SetFont(GetFont());
  618.         m_aItems.Insert(pNewItem, nIndex);
  619.         ::WinSendMsg( GetHwnd()
  620.                      ,LM_SETITEMHANDLE
  621.                      ,(MPARAM)((SHORT)nIndex)
  622.                      ,MPFROMP(pNewItem)
  623.                     );
  624.         m_nNumItems += nItems;
  625.     }
  626. } // end of wxListBox::DoInsertItems
  627.  
  628. void wxListBox::SetString(
  629.   int                               N
  630. , const wxString&                   rsString
  631. )
  632. {
  633.     wxCHECK_RET( N >= 0 && N < m_nNumItems,
  634.                  wxT("invalid index in wxListBox::SetString") );
  635.  
  636.     //
  637.     // Remember the state of the item
  638.     //
  639.     bool                            bWasSelected = IsSelected(N);
  640.     void*                           pOldData = NULL;
  641.     wxClientData*                   pOldObjData = NULL;
  642.  
  643.     if (m_clientDataItemsType == wxClientData_Void)
  644.         pOldData = GetClientData(N);
  645.     else if (m_clientDataItemsType == wxClientData_Object)
  646.         pOldObjData = GetClientObject(N);
  647.  
  648.     //
  649.     // Delete and recreate it
  650.     //
  651.     ::WinSendMsg( GetHwnd()
  652.                  ,LM_DELETEITEM
  653.                  ,(MPARAM)N
  654.                  ,(MPARAM)0
  655.                 );
  656.  
  657.     int                             nNewN = N;
  658.  
  659.     if (N == m_nNumItems - 1)
  660.         nNewN = -1;
  661.  
  662.     ::WinSendMsg( GetHwnd()
  663.                  ,LM_INSERTITEM
  664.                  ,(MPARAM)nNewN
  665.                  ,(MPARAM)rsString.c_str()
  666.                 );
  667.  
  668.     //
  669.     // Restore the client data
  670.     //
  671.     if (pOldData)
  672.         SetClientData( N
  673.                       ,pOldData
  674.                      );
  675.     else if (pOldObjData)
  676.         SetClientObject( N
  677.                         ,pOldObjData
  678.                        );
  679.  
  680.     //
  681.     // We may have lost the selection
  682.     //
  683.     if (bWasSelected)
  684.         Select(N);
  685.  
  686. #if wxUSE_OWNER_DRAWN
  687.     if (m_windowStyle & wxLB_OWNERDRAW)
  688.         //
  689.         // Update item's text
  690.         //
  691.         m_aItems[N]->SetName(rsString);
  692. #endif  //USE_OWNER_DRAWN
  693. } // end of wxListBox::SetString
  694.  
  695. int wxListBox::GetCount() const
  696. {
  697.     return m_nNumItems;
  698. }
  699.  
  700. // ----------------------------------------------------------------------------
  701. // helpers
  702. // ----------------------------------------------------------------------------
  703.  
  704. wxSize wxListBox::DoGetBestSize() const
  705. {
  706.     //
  707.     // Find the widest string
  708.     //
  709.     int                             nLine;
  710.     int                             nListbox = 0;
  711.     int                             nCx;
  712.     int                             nCy;
  713.  
  714.     for (int i = 0; i < m_nNumItems; i++)
  715.     {
  716.         wxString                    vStr(GetString(i));
  717.  
  718.         GetTextExtent( vStr
  719.                       ,&nLine
  720.                       ,NULL
  721.                      );
  722.         if (nLine > nListbox)
  723.             nListbox = nLine;
  724.     }
  725.  
  726.     //
  727.     // Give it some reasonable default value if there are no strings in the
  728.     // list.
  729.     //
  730.     if (nListbox == 0)
  731.         nListbox = 100;
  732.  
  733.     //
  734.     // The listbox should be slightly larger than the widest string
  735.     //
  736.     wxGetCharSize( GetHWND()
  737.                   ,&nCx
  738.                   ,&nCy
  739.                   ,(wxFont*)&GetFont()
  740.                  );
  741.     nListbox += 3 * nCx;
  742.  
  743.     int                             hListbox = EDIT_HEIGHT_FROM_CHAR_HEIGHT(nCy) * (wxMax(m_nNumItems, 7));
  744.  
  745.     return wxSize( nListbox
  746.                   ,hListbox
  747.                  );
  748. } // end of wxListBox::DoGetBestSize
  749.  
  750. // ----------------------------------------------------------------------------
  751. // callbacks
  752. // ----------------------------------------------------------------------------
  753.  
  754. bool wxListBox::OS2Command(
  755.   WXUINT                            uParam
  756. , WXWORD                            WXUNUSED(wId))
  757. {
  758.     wxEventType                     eEvtType;
  759.  
  760.     if (uParam == LN_SELECT)
  761.     {
  762.         eEvtType = wxEVT_COMMAND_LISTBOX_SELECTED;
  763.     }
  764.     if (uParam == LN_ENTER)
  765.     {
  766.         eEvtType = wxEVT_COMMAND_LISTBOX_DOUBLECLICKED;
  767.     }
  768.     else
  769.     {
  770.         //
  771.         // Some event we're not interested in
  772.         //
  773.         return FALSE;
  774.     }
  775.     wxCommandEvent                  vEvent( eEvtType
  776.                                            ,m_windowId
  777.                                           );
  778.  
  779.     vEvent.SetEventObject(this);
  780.  
  781.     wxArrayInt                      aSelections;
  782.     int                             n;
  783.     int                             nCount = GetSelections(aSelections);
  784.  
  785.     if (nCount > 0)
  786.     {
  787.         n = aSelections[0];
  788.         if (HasClientObjectData())
  789.             vEvent.SetClientObject(GetClientObject(n));
  790.         else if ( HasClientUntypedData() )
  791.             vEvent.SetClientData(GetClientData(n));
  792.         vEvent.SetString(GetString(n));
  793.     }
  794.     else
  795.     {
  796.         n = -1;
  797.     }
  798.     vEvent.m_commandInt = n;
  799.     return GetEventHandler()->ProcessEvent(vEvent);
  800. } // end of wxListBox::OS2Command
  801.  
  802. // ----------------------------------------------------------------------------
  803. // wxCheckListBox support
  804. // ----------------------------------------------------------------------------
  805.  
  806. #if wxUSE_OWNER_DRAWN
  807.  
  808. //
  809. // Drawing
  810. // -------
  811. //
  812. #define OWNER_DRAWN_LISTBOX_EXTRA_SPACE    (1)
  813.  
  814. long wxListBox::OS2OnMeasure(
  815.   WXMEASUREITEMSTRUCT*              pItem
  816. )
  817. {
  818.     if (!pItem)
  819.         pItem = (WXMEASUREITEMSTRUCT*)new OWNERITEM;
  820.  
  821.     POWNERITEM                      pMeasureStruct = (POWNERITEM)pItem;
  822.     wxScreenDC                      vDc;
  823.  
  824.     //
  825.     // Only owner-drawn control should receive this message
  826.     //
  827.     wxCHECK( ((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE );
  828.  
  829.     vDc.SetFont(GetFont());
  830.  
  831.     wxCoord                         vHeight;
  832.     wxCoord                         vWidth;
  833.  
  834.     GetSize( &vWidth
  835.             ,NULL
  836.            );
  837.  
  838.     pMeasureStruct->rclItem.xRight = (USHORT)vWidth;
  839.     pMeasureStruct->rclItem.xLeft  = 0;
  840.     pMeasureStruct->rclItem.yTop   = 0;
  841.     pMeasureStruct->rclItem.yBottom = 0;
  842.  
  843.     vHeight = vDc.GetCharHeight() * 2.5;
  844.     pMeasureStruct->rclItem.yTop  = (USHORT)vHeight;
  845.  
  846.     return long(MRFROM2SHORT((USHORT)vHeight, (USHORT)vWidth));
  847. } // end of wxListBox::OS2OnMeasure
  848.  
  849. bool wxListBox::OS2OnDraw (
  850.   WXDRAWITEMSTRUCT*                 pItem
  851. )
  852. {
  853.     POWNERITEM                      pDrawStruct = (POWNERITEM)pItem;
  854.     LONG                            lItemID = pDrawStruct->idItem;
  855.     int                             eAction = 0;
  856.     int                             eStatus = 0;
  857.  
  858.     //
  859.     // Only owner-drawn control should receive this message
  860.     //
  861.     wxCHECK(((m_windowStyle & wxLB_OWNERDRAW) == wxLB_OWNERDRAW), FALSE);
  862.  
  863.  
  864.     //
  865.     // The item may be -1 for an empty listbox
  866.     //
  867.     if (lItemID == -1L)
  868.         return FALSE;
  869.  
  870.     wxListBoxItem*                   pData = (wxListBoxItem*)PVOIDFROMMR( ::WinSendMsg( GetHwnd()
  871.                                                                                        ,LM_QUERYITEMHANDLE
  872.                                                                                        ,MPFROMLONG(pDrawStruct->idItem)
  873.                                                                                        ,(MPARAM)0
  874.                                                                                       )
  875.                                                                         );
  876.  
  877.     wxCHECK(pData, FALSE );
  878.  
  879.     wxDC                              vDc;
  880.     wxRect                            vRect( wxPoint( pDrawStruct->rclItem.xLeft
  881.                                                      ,pDrawStruct->rclItem.yTop
  882.                                                     )
  883.                                             ,wxPoint( pDrawStruct->rclItem.xRight
  884.                                                      ,pDrawStruct->rclItem.yBottom
  885.                                                     )
  886.                                            );
  887.  
  888.     vDc.SetHPS(pDrawStruct->hps);
  889.  
  890.     if (pDrawStruct->fsAttribute == pDrawStruct->fsAttributeOld)
  891.     {
  892.         //
  893.         // Entire Item needs to be redrawn (either it has reappeared from
  894.         // behind another window or is being displayed for the first time
  895.         //
  896.         eAction = wxOwnerDrawn::wxODDrawAll;
  897.  
  898.         if (pDrawStruct->fsAttribute & MIA_HILITED)
  899.         {
  900.             //
  901.             // If it is currently selected we let the system handle it
  902.             //
  903.             eStatus |= wxOwnerDrawn::wxODSelected;
  904.         }
  905.         if (pDrawStruct->fsAttribute & MIA_CHECKED)
  906.         {
  907.             //
  908.             // If it is currently checked we draw our own
  909.             //
  910.             eStatus |= wxOwnerDrawn::wxODChecked;
  911.             pDrawStruct->fsAttributeOld = pDrawStruct->fsAttribute &= ~MIA_CHECKED;
  912.         }
  913.         if (pDrawStruct->fsAttribute & MIA_DISABLED)
  914.         {
  915.             //
  916.             // If it is currently disabled we let the system handle it
  917.             //
  918.             eStatus |= wxOwnerDrawn::wxODDisabled;
  919.         }
  920.         //
  921.         // Don't really care about framed (indicationg focus) or NoDismiss
  922.         //
  923.     }
  924.     else
  925.     {
  926.         if (pDrawStruct->fsAttribute & MIA_HILITED)
  927.         {
  928.             eAction = wxOwnerDrawn::wxODDrawAll;
  929.             eStatus |= wxOwnerDrawn::wxODSelected;
  930.             //
  931.             // Keep the system from trying to highlight with its bogus colors
  932.             //
  933.             pDrawStruct->fsAttributeOld = pDrawStruct->fsAttribute &= ~MIA_HILITED;
  934.         }
  935.         else if (!(pDrawStruct->fsAttribute & MIA_HILITED))
  936.         {
  937.             eAction = wxOwnerDrawn::wxODDrawAll;
  938.             eStatus = 0;
  939.             //
  940.             // Keep the system from trying to highlight with its bogus colors
  941.             //
  942.             pDrawStruct->fsAttribute = pDrawStruct->fsAttributeOld &= ~MIA_HILITED;
  943.         }
  944.         else
  945.         {
  946.             //
  947.             // For now we don't care about anything else
  948.             // just ignore the entire message!
  949.             //
  950.             return TRUE;
  951.         }
  952.     }
  953.     return pData->OnDrawItem( vDc
  954.                              ,vRect
  955.                              ,(wxOwnerDrawn::wxODAction)eAction
  956.                              ,(wxOwnerDrawn::wxODStatus)eStatus
  957.                             );
  958. } // end of wxListBox::OS2OnDraw
  959.  
  960. #endif // ndef for wxUSE_OWNER_DRAWN
  961.  
  962. #endif // ndef for wxUSE_LISTBOX
  963.  
  964.