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