+// ----------------------------------------------------------------------------
+// declaration and implementation of wxCheckListBoxItem class
+// ----------------------------------------------------------------------------
+
+class wxCheckListBoxItem : public wxOwnerDrawn
+{
+friend class wxCheckListBox;
+public:
+  // ctor
+  wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex);
+
+  // drawing functions
+  virtual bool OnDrawItem(wxDC& dc, const wxRect& rc, wxODAction act, wxODStatus stat);
+
+  // simple accessors
+  bool IsChecked() const  { return m_bChecked;        }
+  void Check(bool bCheck);
+  void Toggle() { Check(!IsChecked()); }
+
+private:
+  bool            m_bChecked;
+  wxCheckListBox *m_pParent;
+  size_t            m_nIndex;
+};
+
+wxCheckListBoxItem::wxCheckListBoxItem(wxCheckListBox *pParent, size_t nIndex)
+                  : wxOwnerDrawn("", TRUE)   // checkable
+{
+  m_bChecked = FALSE;
+  m_pParent  = pParent;
+  m_nIndex   = nIndex;
+
+  // we don't initialize m_nCheckHeight/Width vars because it's
+  // done in OnMeasure while they are used only in OnDraw and we
+  // know that there will always be OnMeasure before OnDraw
+
+  // fix appearance
+  SetMarginWidth(GetDefaultMarginWidth());
+}
+
+/*
+ * JACS - I've got the owner-draw stuff partially working with WIN16,
+ * with a really horrible-looking cross for wxCheckListBox instead of a
+ * check - could use a bitmap check-mark instead, defined in wx.rc.
+ * Also there's a refresh problem whereby it doesn't always draw the
+ * check until you click to the right of it, which is OK for WIN32.
+ */
+
+bool wxCheckListBoxItem::OnDrawItem(wxDC& dc, const wxRect& rc,
+                                    wxODAction act, wxODStatus stat)
+{
+  if ( IsChecked() )
+    stat = (wxOwnerDrawn::wxODStatus)(stat | wxOwnerDrawn::wxODChecked);
+
+// TODO:
+/*
+
+  if ( wxOwnerDrawn::OnDrawItem(dc, rc, act, stat) ) {
+    // ## using native API for performance and precision
+    size_t nCheckWidth  = GetDefaultMarginWidth(),
+         nCheckHeight = m_pParent->GetItemHeight();
+
+    int x = rc.GetX(),
+        y = rc.GetY();
+
+    HDC hdc = (HDC)dc.GetHDC();
+
+    // create pens
+    HPEN hpenBack = CreatePen(PS_SOLID, 0, GetSysColor(COLOR_WINDOW)),
+         hpenGray = CreatePen(PS_SOLID, 0, RGB(128, 128, 128)),
+         hpenPrev = (HPEN)SelectObject(hdc, hpenBack);
+
+    // we erase the 1-pixel border
+    Rectangle(hdc, x, y, x + nCheckWidth, y + nCheckHeight);
+
+    // shift check mark 1 pixel to the right (it looks better like this)
+    x++;
+
+    if ( IsChecked() ) {
+      // first create a monochrome bitmap in a memory DC
+      HDC hdcMem = CreateCompatibleDC(hdc);
+      HBITMAP hbmpCheck = CreateBitmap(nCheckWidth, nCheckHeight, 1, 1, 0);
+      HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmpCheck);
+
+      // then draw a check mark into it
+      RECT rect ;
+      rect.left   = 0 ;
+      rect.top    = 0 ;
+      rect.right  = nCheckWidth ;
+      rect.bottom = nCheckHeight ;
+
+#ifdef __WIN32__
+#ifndef __SC__
+      DrawFrameControl(hdcMem, &rect, DFC_MENU, DFCS_MENUCHECK);
+#endif
+#else
+      // In WIN16, draw a cross
+      HPEN blackPen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
+      HPEN whiteBrush = (HPEN)GetStockObject(WHITE_BRUSH);
+      HPEN hPenOld = (HPEN)::SelectObject(hdcMem, blackPen);
+      HPEN hBrushOld = (HPEN)::SelectObject(hdcMem, whiteBrush);
+      ::SetROP2(hdcMem, R2_COPYPEN);
+      Rectangle(hdcMem, 0, 0, nCheckWidth, nCheckHeight);
+      MoveTo(hdcMem, 0, 0);
+      LineTo(hdcMem, nCheckWidth, nCheckHeight);
+      MoveTo(hdcMem, nCheckWidth, 0);
+      LineTo(hdcMem, 0, nCheckHeight);
+      ::SelectObject(hdcMem, hPenOld);
+      ::SelectObject(hdcMem, hBrushOld);
+      ::DeleteObject(blackPen);
+#endif
+
+      // finally copy it to screen DC and clean up
+      BitBlt(hdc, x, y, nCheckWidth - 1, nCheckHeight,
+             hdcMem, 0, 0, SRCCOPY);
+
+      SelectObject(hdcMem, hbmpOld);
+      DeleteObject(hbmpCheck);
+      DeleteDC(hdcMem);
+    }
+
+    // now we draw the smaller rectangle
+    y++;
+    nCheckWidth  -= 2;
+    nCheckHeight -= 2;
+
+    // draw hollow gray rectangle
+    (void)SelectObject(hdc, hpenGray);
+    HBRUSH hbrPrev  = (HBRUSH)SelectObject(hdc, GetStockObject(NULL_BRUSH));
+    Rectangle(hdc, x, y, x + nCheckWidth, y + nCheckHeight);
+
+    // clean up
+    (void)SelectObject(hdc, hpenPrev);
+    (void)SelectObject(hdc, hbrPrev);
+
+    DeleteObject(hpenBack);
+    DeleteObject(hpenGray);
+
+//
+//    dc.DrawRectangle(x, y, nCheckWidth, nCheckHeight);
+//
+//    if ( IsChecked() ) {
+//      dc.DrawLine(x, y, x + nCheckWidth, y + nCheckHeight);
+//      dc.DrawLine(x, y + nCheckHeight, x + nCheckWidth, y);
+//    }
+//
+
+    return TRUE;
+  }
+*/
+  return FALSE;
+}
+
+// change the state of the item and redraw it
+void wxCheckListBoxItem::Check(bool check)
+{
+    m_bChecked = check;
+
+    // index may be chanegd because new items were added/deleted
+    if ( m_pParent->GetItemIndex(this) != (int)m_nIndex )
+    {
+        // update it
+        int index = m_pParent->GetItemIndex(this);
+
+        wxASSERT_MSG( index != wxNOT_FOUND, wxT("what does this item do here?") );
+
+        m_nIndex = (size_t)index;
+    }
+
+    HWND hwndListbox = (HWND)m_pParent->GetHWND();
+
+// TODO:
+/*
+    RECT rcUpdate;
+    if ( ::SendMessage(hwndListbox, LB_GETITEMRECT,
+                       m_nIndex, (LPARAM)&rcUpdate) == LB_ERR )
+    {
+        wxLogDebug(wxT("LB_GETITEMRECT failed"));
+    }
+
+    InvalidateRect(hwndListbox, &rcUpdate, FALSE);
+*/
+    wxCommandEvent event(wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, m_pParent->GetId());
+    event.SetInt(m_nIndex);
+    event.SetEventObject(m_pParent);
+    m_pParent->ProcessCommand(event);
+}
+