]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/listctrl.cpp
extracted LPITEMIDLIST wrappers in a separate header (also [will be] used by wxStdnar...
[wxWidgets.git] / src / msw / listctrl.cpp
index 4d906a5c85a5a59eeb07c4ef99b60688e9fed84a..8336fc4af7d0c6c728dcfc313414be964475960b 100644 (file)
@@ -17,7 +17,7 @@
 // headers
 // ----------------------------------------------------------------------------
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
     #pragma implementation "listctrl.h"
     #pragma implementation "listctrlbase.h"
 #endif
 
 #include "wx/msw/private.h"
 
-#if defined(__GNUWIN32_OLD__) && !defined(__CYGWIN10__)
-    #include "wx/msw/gnuwin32/extra.h"
-#else
-    #include <commctrl.h>
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__)
+  #include <ole2.h>
+  #include <shellapi.h>
+  #if _WIN32_WCE < 400
+    #include <aygshell.h>
+  #endif
 #endif
 
-#include "wx/msw/missing.h"
+// include <commctrl.h> "properly"
+#include "wx/msw/wrapcctl.h"
 
 // ----------------------------------------------------------------------------
 // private functions
@@ -78,60 +81,77 @@ static void wxConvertToMSWListCol(int col, const wxListItem& item,
 // ----------------------------------------------------------------------------
 
 // We have to handle both fooW and fooA notifications in several cases
-// because of broken commctl.dll and/or unicows.dll. This class is used to
+// because of broken comctl32.dll and/or unicows.dll. This class is used to
 // convert LV_ITEMA and LV_ITEMW to LV_ITEM (which is either LV_ITEMA or
 // LV_ITEMW depending on wxUSE_UNICODE setting), so that it can be processed
 // by wxConvertToMSWListItem().
+#if wxUSE_UNICODE
+    #define LV_ITEM_NATIVE  LV_ITEMW
+    #define LV_ITEM_OTHER   LV_ITEMA
+
+    #define LV_CONV_TO_WX   cMB2WX
+    #define LV_CONV_BUF     wxMB2WXbuf
+#else // ANSI
+    #define LV_ITEM_NATIVE  LV_ITEMA
+    #define LV_ITEM_OTHER   LV_ITEMW
+
+    #define LV_CONV_TO_WX   cWC2WX
+    #define LV_CONV_BUF     wxWC2WXbuf
+#endif // Unicode/ANSI
+
 class wxLV_ITEM
 {
 public:
-    ~wxLV_ITEM() { delete m_buf; }
-    operator LV_ITEM&() const { return *m_item; }
+    // default ctor, use Init() later
+    wxLV_ITEM() { m_buf = NULL; m_pItem = NULL; }
 
-#if wxUSE_UNICODE
-    wxLV_ITEM(LV_ITEMW &item) : m_buf(NULL), m_item(&item) {}
-    wxLV_ITEM(LV_ITEMA &item)
+    // init without conversion
+    void Init(LV_ITEM_NATIVE& item)
     {
-        m_item = new LV_ITEM((LV_ITEM&)item);
-        if ( (item.mask & LVIF_TEXT) && item.pszText )
-        {
-            m_buf = new wxMB2WXbuf(wxConvLocal.cMB2WX(item.pszText));
-            m_item->pszText = (wxChar*)m_buf->data();
-        }
-        else
-            m_buf = NULL;
+        wxASSERT_MSG( !m_pItem, _T("Init() called twice?") );
+
+        m_pItem = &item;
     }
-private:
-    wxMB2WXbuf *m_buf;
 
-#else // !wxUSE_UNICODE
-    wxLV_ITEM(LV_ITEMW &item)
+    // init with conversion
+    void Init(LV_ITEM_OTHER& item)
     {
-        m_item = new LV_ITEM((LV_ITEM&)item);
+        // avoid unnecessary dynamic memory allocation, jjust make m_pItem
+        // point to our own m_item
+
+        // memcpy() can't work if the struct sizes are different
+        wxCOMPILE_TIME_ASSERT( sizeof(LV_ITEM_OTHER) == sizeof(LV_ITEM_NATIVE),
+                                CodeCantWorkIfDiffSizes);
 
-        // the code below doesn't compile without wxUSE_WCHAR_T and as I don't
-        // know if it's useful to have it at all (do we ever get Unicode
-        // notifications in ANSI mode? I don't think so...) I'm not going to
-        // write alternative implementation right now
-        //
-        // but if it is indeed used, we should simply directly use
-        // ::WideCharToMultiByte() here
-#if wxUSE_WCHAR_T
+        memcpy(&m_item, &item, sizeof(LV_ITEM_NATIVE));
+
+        // convert text from ANSI to Unicod if necessary
         if ( (item.mask & LVIF_TEXT) && item.pszText )
         {
-            m_buf = new wxWC2WXbuf(wxConvLocal.cWC2WX(item.pszText));
-            m_item->pszText = (wxChar*)m_buf->data();
+            m_buf = new LV_CONV_BUF(wxConvLocal.LV_CONV_TO_WX(item.pszText));
+            m_item.pszText = (wxChar *)m_buf->data();
         }
-        else
-#endif // wxUSE_WCHAR_T
-            m_buf = NULL;
     }
-    wxLV_ITEM(LV_ITEMA &item) : m_buf(NULL), m_item(&item) {}
+
+    // ctor without conversion
+    wxLV_ITEM(LV_ITEM_NATIVE& item) : m_buf(NULL), m_pItem(&item) { }
+
+    // ctor with conversion
+    wxLV_ITEM(LV_ITEM_OTHER& item) : m_buf(NULL)
+    {
+        Init(item);
+    }
+
+    ~wxLV_ITEM() { delete m_buf; }
+
+    // conversion to the real LV_ITEM
+    operator LV_ITEM_NATIVE&() const { return *m_pItem; }
+
 private:
-    wxWC2WXbuf *m_buf;
-#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+    LV_CONV_BUF *m_buf;
 
-    LV_ITEM *m_item;
+    LV_ITEM_NATIVE *m_pItem;
+    LV_ITEM_NATIVE m_item;
 
     DECLARE_NO_COPY_CLASS(wxLV_ITEM)
 };
@@ -186,7 +206,7 @@ public:
 
 // Get the internal data structure
 static wxListItemInternalData *wxGetInternalData(HWND hwnd, long itemId);
-static wxListItemInternalData *wxGetInternalData(wxListCtrl *ctl, long itemId);
+static wxListItemInternalData *wxGetInternalData(const wxListCtrl *ctl, long itemId);
 static wxListItemAttr *wxGetInternalDataAttr(wxListCtrl *ctl, long itemId);
 static void wxDeleteInternalData(wxListCtrl* ctl, long itemId);
 
@@ -201,8 +221,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
+#if WXWIN_COMPATIBILITY_2_4
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
+#endif
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
@@ -218,7 +240,74 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
 
+#if wxUSE_EXTENDED_RTTI
+WX_DEFINE_FLAGS( wxListCtrlStyle )
+
+wxBEGIN_FLAGS( wxListCtrlStyle )
+    // new style border flags, we put them first to
+    // use them for streaming out
+    wxFLAGS_MEMBER(wxBORDER_SIMPLE)
+    wxFLAGS_MEMBER(wxBORDER_SUNKEN)
+    wxFLAGS_MEMBER(wxBORDER_DOUBLE)
+    wxFLAGS_MEMBER(wxBORDER_RAISED)
+    wxFLAGS_MEMBER(wxBORDER_STATIC)
+    wxFLAGS_MEMBER(wxBORDER_NONE)
+
+    // old style border flags
+    wxFLAGS_MEMBER(wxSIMPLE_BORDER)
+    wxFLAGS_MEMBER(wxSUNKEN_BORDER)
+    wxFLAGS_MEMBER(wxDOUBLE_BORDER)
+    wxFLAGS_MEMBER(wxRAISED_BORDER)
+    wxFLAGS_MEMBER(wxSTATIC_BORDER)
+    wxFLAGS_MEMBER(wxBORDER)
+
+    // standard window styles
+    wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
+    wxFLAGS_MEMBER(wxCLIP_CHILDREN)
+    wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
+    wxFLAGS_MEMBER(wxWANTS_CHARS)
+    wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
+    wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
+    wxFLAGS_MEMBER(wxVSCROLL)
+    wxFLAGS_MEMBER(wxHSCROLL)
+
+    wxFLAGS_MEMBER(wxLC_LIST)
+    wxFLAGS_MEMBER(wxLC_REPORT)
+    wxFLAGS_MEMBER(wxLC_ICON)
+    wxFLAGS_MEMBER(wxLC_SMALL_ICON)
+    wxFLAGS_MEMBER(wxLC_ALIGN_TOP)
+    wxFLAGS_MEMBER(wxLC_ALIGN_LEFT)
+    wxFLAGS_MEMBER(wxLC_AUTOARRANGE)
+    wxFLAGS_MEMBER(wxLC_USER_TEXT)
+    wxFLAGS_MEMBER(wxLC_EDIT_LABELS)
+    wxFLAGS_MEMBER(wxLC_NO_HEADER)
+    wxFLAGS_MEMBER(wxLC_SINGLE_SEL)
+    wxFLAGS_MEMBER(wxLC_SORT_ASCENDING)
+    wxFLAGS_MEMBER(wxLC_SORT_DESCENDING)
+    wxFLAGS_MEMBER(wxLC_VIRTUAL)
+
+wxEND_FLAGS( wxListCtrlStyle )
+
+IMPLEMENT_DYNAMIC_CLASS_XTI(wxListCtrl, wxControl,"wx/listctrl.h")
+
+wxBEGIN_PROPERTIES_TABLE(wxListCtrl)
+    wxEVENT_PROPERTY( TextUpdated , wxEVT_COMMAND_TEXT_UPDATED , wxCommandEvent )
+
+    wxPROPERTY_FLAGS( WindowStyle , wxListCtrlStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
+wxEND_PROPERTIES_TABLE()
+
+wxBEGIN_HANDLERS_TABLE(wxListCtrl)
+wxEND_HANDLERS_TABLE()
+
+wxCONSTRUCTOR_5( wxListCtrl , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
+
+/*
+ TODO : Expose more information of a list's layout etc. via appropriate objects (à la NotebookPageInfo)
+*/
+#else
 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
+#endif
+
 IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
 IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
 
@@ -241,14 +330,13 @@ void wxListCtrl::Init()
     m_imageListNormal = NULL;
     m_imageListSmall = NULL;
     m_imageListState = NULL;
-    m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE;
-    m_baseStyle = 0;
+    m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = false;
     m_colCount = 0;
     m_count = 0;
-    m_ignoreChangeMessages = FALSE;
+    m_ignoreChangeMessages = false;
     m_textCtrl = NULL;
-    m_AnyInternalData = FALSE;
-    m_hasAnyAttr = FALSE;
+    m_AnyInternalData = false;
+    m_hasAnyAttr = false;
 }
 
 bool wxListCtrl::Create(wxWindow *parent,
@@ -259,103 +347,119 @@ bool wxListCtrl::Create(wxWindow *parent,
                         const wxValidator& validator,
                         const wxString& name)
 {
-#if wxUSE_VALIDATORS
-    SetValidator(validator);
-#endif // wxUSE_VALIDATORS
+    if ( !CreateControl(parent, id, pos, size, style, validator, name) )
+        return false;
 
-    SetName(name);
+    if ( !MSWCreateControl(WC_LISTVIEW, _T(""), pos, size) )
+        return false;
 
-    int x = pos.x;
-    int y = pos.y;
-    int width = size.x;
-    int height = size.y;
+    // explicitly say that we want to use Unicode because otherwise we get ANSI
+    // versions of _some_ messages (notably LVN_GETDISPINFOA) in MSLU build
+    wxSetCCUnicodeFormat(GetHwnd());
 
-    m_windowStyle = style;
+    // for comctl32.dll v 4.70+ we want to have this attribute because it's
+    // prettier (and also because wxGTK does it like this)
+    if ( InReportView() && wxTheApp->GetComCtl32Version() >= 470 )
+    {
+        ::SendMessage(GetHwnd(), LVM_SETEXTENDEDLISTVIEWSTYLE,
+                      0, LVS_EX_FULLROWSELECT);
+    }
 
-    SetParent(parent);
+    return true;
+}
 
-    if (width <= 0)
-        width = 100;
-    if (height <= 0)
-        height = 30;
-    if (x < 0)
-        x = 0;
-    if (y < 0)
-        y = 0;
+WXDWORD wxListCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
+{
+    WXDWORD wstyle = wxControl::MSWGetStyle(style, exstyle);
 
-    m_windowId = (id == -1) ? NewControlId() : id;
+    wstyle |= LVS_SHAREIMAGELISTS | LVS_SHOWSELALWAYS;
 
-    DWORD wstyle = WS_VISIBLE | WS_CHILD | WS_TABSTOP |
-                   LVS_SHAREIMAGELISTS | LVS_SHOWSELALWAYS;
+#ifdef __WXDEBUG__
+    size_t nModes = 0;
 
-    m_baseStyle = wstyle;
+    #define MAP_MODE_STYLE(wx, ms)                                            \
+        if ( style & (wx) ) { wstyle |= (ms); nModes++; }
+#else // !__WXDEBUG__
+    #define MAP_MODE_STYLE(wx, ms)                                            \
+        if ( style & (wx) ) wstyle |= (ms);
+#endif // __WXDEBUG__
 
-    if ( !DoCreateControl(x, y, width, height) )
-        return FALSE;
+    MAP_MODE_STYLE(wxLC_ICON, LVS_ICON)
+    MAP_MODE_STYLE(wxLC_SMALL_ICON, LVS_SMALLICON)
+    MAP_MODE_STYLE(wxLC_LIST, LVS_LIST)
+    MAP_MODE_STYLE(wxLC_REPORT, LVS_REPORT)
 
-    if (parent)
-        parent->AddChild(this);
+    wxASSERT_MSG( nModes == 1,
+                  _T("wxListCtrl style should have exactly one mode bit set") );
 
-    return TRUE;
-}
+#undef MAP_MODE_STYLE
 
-bool wxListCtrl::DoCreateControl(int x, int y, int w, int h)
-{
-    DWORD wstyle = m_baseStyle;
+    if ( style & wxLC_ALIGN_LEFT )
+        wstyle |= LVS_ALIGNLEFT;
 
-    WXDWORD exStyle = 0;
-    WXDWORD standardStyle = MSWGetStyle(GetWindowStyle(), & exStyle) ;
+    if ( style & wxLC_ALIGN_TOP )
+        wstyle |= LVS_ALIGNTOP;
 
-    long oldStyle = 0; // Dummy
-    wstyle |= ConvertToMSWStyle(oldStyle, m_windowStyle);
-    wstyle |= standardStyle;
+    if ( style & wxLC_AUTOARRANGE )
+        wstyle |= LVS_AUTOARRANGE;
 
-    // Create the ListView control.
-    m_hWnd = (WXHWND)CreateWindowEx(exStyle,
-                                    WC_LISTVIEW,
-                                    wxT(""),
-                                    wstyle,
-                                    x, y, w, h,
-                                    GetWinHwnd(GetParent()),
-                                    (HMENU)m_windowId,
-                                    wxGetInstance(),
-                                    NULL);
+    if ( style & wxLC_NO_SORT_HEADER )
+        wstyle |= LVS_NOSORTHEADER;
 
-    if ( !m_hWnd )
-    {
-        wxLogError(_("Can't create list control window, check that comctl32.dll is installed."));
+    if ( style & wxLC_NO_HEADER )
+        wstyle |= LVS_NOCOLUMNHEADER;
 
-        return FALSE;
-    }
+    if ( style & wxLC_EDIT_LABELS )
+        wstyle |= LVS_EDITLABELS;
 
-    // for comctl32.dll v 4.70+ we want to have this attribute because it's
-    // prettier (and also because wxGTK does it like this)
-    if ( (wstyle & LVS_REPORT) && wxTheApp->GetComCtl32Version() >= 470 )
+    if ( style & wxLC_SINGLE_SEL )
+        wstyle |= LVS_SINGLESEL;
+
+    if ( style & wxLC_SORT_ASCENDING )
     {
-        ::SendMessage(GetHwnd(), LVM_SETEXTENDEDLISTVIEWSTYLE,
-                      0, LVS_EX_FULLROWSELECT);
+        wstyle |= LVS_SORTASCENDING;
+
+        wxASSERT_MSG( !(style & wxLC_SORT_DESCENDING),
+                      _T("can't sort in ascending and descending orders at once") );
     }
+    else if ( style & wxLC_SORT_DESCENDING )
+        wstyle |= LVS_SORTDESCENDING;
 
-    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
-    SetForegroundColour(GetParent()->GetForegroundColour());
+#if !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
+    if ( style & wxLC_VIRTUAL )
+    {
+        int ver = wxTheApp->GetComCtl32Version();
+        if ( ver < 470 )
+        {
+            wxLogWarning(_("Please install a newer version of comctl32.dll\n(at least version 4.70 is required but you have %d.%02d)\nor this program won't operate correctly."),
+                        ver / 100, ver % 100);
+        }
 
-    SubclassWin(m_hWnd);
+        wstyle |= LVS_OWNERDATA;
+    }
+#endif // ancient cygwin
 
-    return TRUE;
+    return wstyle;
 }
 
 void wxListCtrl::UpdateStyle()
 {
-    if ( GetHWND() )
+    if ( GetHwnd() )
     {
         // The new window view style
-        long dummy;
-        DWORD dwStyleNew = ConvertToMSWStyle(dummy, m_windowStyle);
-        dwStyleNew |= m_baseStyle;
+        DWORD dwStyleNew = MSWGetStyle(m_windowStyle, NULL);
+
+        // some styles are not returned by MSWGetStyle()
+        if ( IsShown() )
+            dwStyleNew |= WS_VISIBLE;
 
         // Get the current window style.
         DWORD dwStyleOld = ::GetWindowLong(GetHwnd(), GWL_STYLE);
 
+        // we don't have wxVSCROLL style, but the list control may have it,
+        // don't change it then
+        dwStyleNew |= dwStyleOld & (WS_HSCROLL | WS_VSCROLL);
+
         // Only set the window style if the view bits have changed.
         if ( dwStyleOld != dwStyleNew )
         {
@@ -369,14 +473,13 @@ void wxListCtrl::FreeAllInternalData()
     if (m_AnyInternalData)
     {
         int n = GetItemCount();
-        int i = 0;
 
-        m_ignoreChangeMessages = TRUE;
-        for (i = 0; i < n; i++)
+        m_ignoreChangeMessages = true;
+        for (int i = 0; i < n; i++)
             wxDeleteInternalData(this, i);
-        m_ignoreChangeMessages = FALSE;
+        m_ignoreChangeMessages = false;
 
-        m_AnyInternalData = FALSE;
+        m_AnyInternalData = false;
     }
 }
 
@@ -417,161 +520,58 @@ void wxListCtrl::SetSingleStyle(long style, bool add)
             flag = flag & ~wxLC_MASK_SORT;
     }
 
-    if ( flag & style )
-    {
-        if ( !add )
-            flag -= style;
-    }
+    if ( add )
+        flag |= style;
     else
-    {
-        if ( add )
-        {
-            flag |= style;
-        }
-    }
+        flag &= ~style;
 
-    m_windowStyle = flag;
-
-    UpdateStyle();
+    SetWindowStyleFlag(flag);
 }
 
 // Set the whole window style
 void wxListCtrl::SetWindowStyleFlag(long flag)
 {
-    m_windowStyle = flag;
-
-    UpdateStyle();
-}
-
-// Can be just a single style, or a bitlist
-long wxListCtrl::ConvertToMSWStyle(long& oldStyle, long style) const
-{
-    long wstyle = 0;
-    if ( style & wxLC_ICON )
-    {
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
-            oldStyle -= LVS_SMALLICON;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
-            oldStyle -= LVS_REPORT;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
-            oldStyle -= LVS_LIST;
-        wstyle |= LVS_ICON;
-    }
-
-    if ( style & wxLC_SMALL_ICON )
-    {
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
-            oldStyle -= LVS_ICON;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
-            oldStyle -= LVS_REPORT;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
-            oldStyle -= LVS_LIST;
-        wstyle |= LVS_SMALLICON;
-    }
-
-    if ( style & wxLC_LIST )
-    {
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
-            oldStyle -= LVS_ICON;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_REPORT )
-            oldStyle -= LVS_REPORT;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
-            oldStyle -= LVS_SMALLICON;
-        wstyle |= LVS_LIST;
-    }
-
-    if ( style & wxLC_REPORT )
-    {
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_ICON )
-            oldStyle -= LVS_ICON;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_LIST )
-            oldStyle -= LVS_LIST;
-        if ( (oldStyle & LVS_TYPEMASK) == LVS_SMALLICON )
-            oldStyle -= LVS_SMALLICON;
-
-        wstyle |= LVS_REPORT;
-    }
-
-    if ( style & wxLC_ALIGN_LEFT )
+    if ( flag != m_windowStyle )
     {
-        if ( oldStyle & LVS_ALIGNTOP )
-            oldStyle -= LVS_ALIGNTOP;
-        wstyle |= LVS_ALIGNLEFT;
-    }
-
-    if ( style & wxLC_ALIGN_TOP )
-    {
-        if ( oldStyle & LVS_ALIGNLEFT )
-            oldStyle -= LVS_ALIGNLEFT;
-        wstyle |= LVS_ALIGNTOP;
-    }
-
-    if ( style & wxLC_AUTOARRANGE )
-        wstyle |= LVS_AUTOARRANGE;
-
-    if ( style & wxLC_NO_SORT_HEADER )
-        wstyle |= LVS_NOSORTHEADER;
-
-    if ( style & wxLC_NO_HEADER )
-        wstyle |= LVS_NOCOLUMNHEADER;
-
-    if ( style & wxLC_EDIT_LABELS )
-        wstyle |= LVS_EDITLABELS;
-
-    if ( style & wxLC_SINGLE_SEL )
-        wstyle |= LVS_SINGLESEL;
+        m_windowStyle = flag;
 
-    if ( style & wxLC_SORT_ASCENDING )
-    {
-        if ( oldStyle & LVS_SORTDESCENDING )
-            oldStyle -= LVS_SORTDESCENDING;
-        wstyle |= LVS_SORTASCENDING;
-    }
-
-    if ( style & wxLC_SORT_DESCENDING )
-    {
-        if ( oldStyle & LVS_SORTASCENDING )
-            oldStyle -= LVS_SORTASCENDING;
-        wstyle |= LVS_SORTDESCENDING;
-    }
-
-#if !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
-    if ( style & wxLC_VIRTUAL )
-    {
-        int ver = wxTheApp->GetComCtl32Version();
-        if ( ver < 470 )
-        {
-            wxLogWarning(_("Please install a newer version of comctl32.dll\n(at least version 4.70 is required but you have %d.%02d)\nor this program won't operate correctly."),
-                        ver / 100, ver % 100);
-        }
+        UpdateStyle();
 
-        wstyle |= LVS_OWNERDATA;
+        Refresh();
     }
-#endif
-
-    return wstyle;
 }
 
 // ----------------------------------------------------------------------------
 // accessors
 // ----------------------------------------------------------------------------
 
+/* static */ wxVisualAttributes
+wxListCtrl::GetClassDefaultAttributes(wxWindowVariant variant)
+{
+    wxVisualAttributes attrs = GetCompositeControlsDefaultAttributes(variant);
+
+    // common controls have their own default font
+    attrs.font = wxGetCCDefaultFont();
+
+    return attrs;
+}
+
 // Sets the foreground, i.e. text, colour
 bool wxListCtrl::SetForegroundColour(const wxColour& col)
 {
     if ( !wxWindow::SetForegroundColour(col) )
-        return FALSE;
+        return false;
 
     ListView_SetTextColor(GetHwnd(), wxColourToRGB(col));
 
-    return TRUE;
+    return true;
 }
 
 // Sets the background colour
 bool wxListCtrl::SetBackgroundColour(const wxColour& col)
 {
     if ( !wxWindow::SetBackgroundColour(col) )
-        return FALSE;
+        return false;
 
     // we set the same colour for both the "empty" background and the items
     // background
@@ -579,7 +579,7 @@ bool wxListCtrl::SetBackgroundColour(const wxColour& col)
     ListView_SetBkColor(GetHwnd(), color);
     ListView_SetTextBkColor(GetHwnd(), color);
 
-    return TRUE;
+    return true;
 }
 
 // Gets information about this column
@@ -636,12 +636,16 @@ bool wxListCtrl::GetColumn(int col, wxListItem& item) const
         }
     }
 
-#if _WIN32_IE >= 0x0300
+    // the column images were not supported in older versions but how to check
+    // for this? we can't use _WIN32_IE because we always define it to a very
+    // high value, so see if another symbol which is only defined starting from
+    // comctl32.dll 4.70 is available
+#ifdef NM_CUSTOMDRAW // _WIN32_IE >= 0x0300
     if ( item.m_mask & wxLIST_MASK_IMAGE )
     {
         item.m_image = lvCol.iImage;
     }
-#endif
+#endif // LVCOLUMN::iImage exists
 
     return success;
 }
@@ -763,7 +767,7 @@ bool wxListCtrl::SetItem(wxListItem& info)
         if (! data)
         {
             // need to set it
-            m_AnyInternalData = TRUE;
+            m_AnyInternalData = true;
             data = new wxListItemInternalData();
             item.lParam = (LPARAM) data;
             item.mask |= LVIF_PARAM;
@@ -794,7 +798,7 @@ bool wxListCtrl::SetItem(wxListItem& info)
         {
             wxLogDebug(_T("ListView_SetItem() failed"));
 
-            return FALSE;
+            return false;
         }
     }
 
@@ -804,10 +808,10 @@ bool wxListCtrl::SetItem(wxListItem& info)
     // check whether it has any custom attributes
     if ( info.HasAttributes() )
     {
-        m_hasAnyAttr = TRUE;
+        m_hasAnyAttr = true;
 
         // if the colour has changed, we must redraw the item
-        updateNow = TRUE;
+        updateNow = true;
     }
 
     if ( updateNow )
@@ -816,7 +820,7 @@ bool wxListCtrl::SetItem(wxListItem& info)
         RefreshItem(item.iItem);
     }
 
-    return TRUE;
+    return true;
 }
 
 long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
@@ -881,7 +885,7 @@ bool wxListCtrl::SetItemState(long item, long state, long stateMask)
     {
         wxLogLastError(_T("ListView_SetItemState"));
 
-        return FALSE;
+        return false;
     }
 
     if ( focusOld != -1 )
@@ -895,7 +899,7 @@ bool wxListCtrl::SetItemState(long item, long state, long stateMask)
         }
     }
 
-    return TRUE;
+    return true;
 }
 
 // Sets the item image
@@ -936,7 +940,7 @@ void wxListCtrl::SetItemText(long item, const wxString& str)
 }
 
 // Gets the item data
-long wxListCtrl::GetItemData(long item) const
+wxUIntPtr wxListCtrl::GetItemData(long item) const
 {
     wxListItem info;
 
@@ -960,6 +964,25 @@ bool wxListCtrl::SetItemData(long item, long data)
     return SetItem(info);
 }
 
+wxRect wxListCtrl::GetViewRect() const
+{
+    wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST),
+                    _T("wxListCtrl::GetViewRect() only works in icon mode") );
+
+    RECT rc;
+    if ( !ListView_GetViewRect(GetHwnd(), &rc) )
+    {
+        wxLogDebug(_T("ListView_GetViewRect() failed."));
+
+        wxZeroMemory(rc);
+    }
+
+    wxRect rect;
+    wxCopyRECTToRect(rc, rect);
+
+    return rect;
+}
+
 // Gets the item rectangle
 bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const
 {
@@ -1012,9 +1035,13 @@ int wxListCtrl::GetItemCount() const
     return m_count;
 }
 
-// Retrieves the spacing between icons in pixels.
-// If small is TRUE, gets the spacing for the small icon
-// view, otherwise the large icon view.
+wxSize wxListCtrl::GetItemSpacing() const
+{
+    const int spacing = ListView_GetItemSpacing(GetHwnd(), (BOOL)HasFlag(wxLC_SMALL_ICON));
+
+    return wxSize(LOWORD(spacing), HIWORD(spacing));
+}
+
 int wxListCtrl::GetItemSpacing(bool isSmall) const
 {
     return ListView_GetItemSpacing(GetHwnd(), (BOOL) isSmall);
@@ -1030,10 +1057,12 @@ void wxListCtrl::SetItemTextColour( long item, const wxColour &col )
 
 wxColour wxListCtrl::GetItemTextColour( long item ) const
 {
-    wxListItem info;
-    info.m_itemId = item;
-    GetItem( info );
-    return info.GetTextColour();
+    wxColour col;
+    wxListItemInternalData *data = wxGetInternalData(this, item);
+    if ( data && data->attr )
+        col = data->attr->GetTextColour();
+
+    return col;
 }
 
 void wxListCtrl::SetItemBackgroundColour( long item, const wxColour &col )
@@ -1046,10 +1075,12 @@ void wxListCtrl::SetItemBackgroundColour( long item, const wxColour &col )
 
 wxColour wxListCtrl::GetItemBackgroundColour( long item ) const
 {
-    wxListItem info;
-    info.m_itemId = item;
-    GetItem( info );
-    return info.GetBackgroundColour();
+    wxColour col;
+    wxListItemInternalData *data = wxGetInternalData(this, item);
+    if ( data && data->attr )
+        col = data->attr->GetBackgroundColour();
+
+    return col;
 }
 
 // Gets the number of selected items in the list control
@@ -1140,21 +1171,21 @@ void wxListCtrl::SetImageList(wxImageList *imageList, int which)
         flags = LVSIL_NORMAL;
         if (m_ownsImageListNormal) delete m_imageListNormal;
         m_imageListNormal = imageList;
-        m_ownsImageListNormal = FALSE;
+        m_ownsImageListNormal = false;
     }
     else if ( which == wxIMAGE_LIST_SMALL )
     {
         flags = LVSIL_SMALL;
         if (m_ownsImageListSmall) delete m_imageListSmall;
         m_imageListSmall = imageList;
-        m_ownsImageListSmall = FALSE;
+        m_ownsImageListSmall = false;
     }
     else if ( which == wxIMAGE_LIST_STATE )
     {
         flags = LVSIL_STATE;
         if (m_ownsImageListState) delete m_imageListState;
         m_imageListState = imageList;
-        m_ownsImageListState = FALSE;
+        m_ownsImageListState = false;
     }
     ListView_SetImageList(GetHwnd(), (HIMAGELIST) imageList ? imageList->GetHIMAGELIST() : 0, flags);
 }
@@ -1163,11 +1194,11 @@ void wxListCtrl::AssignImageList(wxImageList *imageList, int which)
 {
     SetImageList(imageList, which);
     if ( which == wxIMAGE_LIST_NORMAL )
-        m_ownsImageListNormal = TRUE;
+        m_ownsImageListNormal = true;
     else if ( which == wxIMAGE_LIST_SMALL )
-        m_ownsImageListSmall = TRUE;
+        m_ownsImageListSmall = true;
     else if ( which == wxIMAGE_LIST_STATE )
-        m_ownsImageListState = TRUE;
+        m_ownsImageListState = true;
 }
 
 // ----------------------------------------------------------------------------
@@ -1196,7 +1227,7 @@ bool wxListCtrl::DeleteItem(long item)
     if ( !ListView_DeleteItem(GetHwnd(), (int) item) )
     {
         wxLogLastError(_T("ListView_DeleteItem"));
-        return FALSE;
+        return false;
     }
 
     m_count -= 1;
@@ -1225,13 +1256,12 @@ bool wxListCtrl::DeleteItem(long item)
         RefreshRect(rectWin);
     }
 
-    return TRUE;
+    return true;
 }
 
 // Deletes all items
 bool wxListCtrl::DeleteAllItems()
 {
-    FreeAllInternalData();
     return ListView_DeleteAllItems(GetHwnd()) != 0;
 }
 
@@ -1244,7 +1274,7 @@ bool wxListCtrl::DeleteAllColumns()
         {
             wxLogLastError(wxT("ListView_DeleteColumn"));
 
-            return FALSE;
+            return false;
         }
 
         m_colCount--;
@@ -1252,7 +1282,7 @@ bool wxListCtrl::DeleteAllColumns()
 
     wxASSERT_MSG( m_colCount == 0, wxT("no columns should be left") );
 
-    return TRUE;
+    return true;
 }
 
 // Deletes a column
@@ -1314,13 +1344,13 @@ bool wxListCtrl::EndEditLabel(bool WXUNUSED(cancel))
 {
     wxFAIL_MSG( _T("not implemented") );
 
-    return FALSE;
+    return false;
 }
 
 // Ensures this item is visible
 bool wxListCtrl::EnsureVisible(long item)
 {
-    return ListView_EnsureVisible(GetHwnd(), (int) item, FALSE) != 0;
+    return ListView_EnsureVisible(GetHwnd(), (int) item, FALSE) != FALSE;
 }
 
 // Find an item whose label matches this string, starting from the item after 'start'
@@ -1347,7 +1377,7 @@ long wxListCtrl::FindItem(long start, const wxString& str, bool partial)
 // NOTE : Lindsay Mathieson - 14-July-2002
 //        No longer use ListView_FindItem as the data attribute is now stored
 //        in a wxListItemInternalData structure refernced by the actual lParam
-long wxListCtrl::FindItem(long start, long data)
+long wxListCtrl::FindItem(long start, wxUIntPtr data)
 {
     long  idx = start + 1;
     long count = GetItemCount();
@@ -1396,23 +1426,38 @@ long wxListCtrl::HitTest(const wxPoint& point, int& flags)
     ListView_HitTest(GetHwnd(), & hitTestInfo);
 
     flags = 0;
+
     if ( hitTestInfo.flags & LVHT_ABOVE )
         flags |= wxLIST_HITTEST_ABOVE;
     if ( hitTestInfo.flags & LVHT_BELOW )
         flags |= wxLIST_HITTEST_BELOW;
-    if ( hitTestInfo.flags & LVHT_NOWHERE )
-        flags |= wxLIST_HITTEST_NOWHERE;
-    if ( hitTestInfo.flags & LVHT_ONITEMICON )
-        flags |= wxLIST_HITTEST_ONITEMICON;
-    if ( hitTestInfo.flags & LVHT_ONITEMLABEL )
-        flags |= wxLIST_HITTEST_ONITEMLABEL;
-    if ( hitTestInfo.flags & LVHT_ONITEMSTATEICON )
-        flags |= wxLIST_HITTEST_ONITEMSTATEICON;
     if ( hitTestInfo.flags & LVHT_TOLEFT )
         flags |= wxLIST_HITTEST_TOLEFT;
     if ( hitTestInfo.flags & LVHT_TORIGHT )
         flags |= wxLIST_HITTEST_TORIGHT;
 
+    if ( hitTestInfo.flags & LVHT_NOWHERE )
+        flags |= wxLIST_HITTEST_NOWHERE;
+
+    // note a bug or at least a very strange feature of comtl32.dll (tested
+    // with version 4.0 under Win95 and 6.0 under Win 2003): if you click to
+    // the right of the item label, ListView_HitTest() returns a combination of
+    // LVHT_ONITEMICON, LVHT_ONITEMLABEL and LVHT_ONITEMSTATEICON -- filter out
+    // the bits which don't make sense
+    if ( hitTestInfo.flags & LVHT_ONITEMLABEL )
+    {
+        flags |= wxLIST_HITTEST_ONITEMLABEL;
+
+        // do not translate LVHT_ONITEMICON here, as per above
+    }
+    else
+    {
+        if ( hitTestInfo.flags & LVHT_ONITEMICON )
+            flags |= wxLIST_HITTEST_ONITEMICON;
+        if ( hitTestInfo.flags & LVHT_ONITEMSTATEICON )
+            flags |= wxLIST_HITTEST_ONITEMSTATEICON;
+    }
+
     return (long) hitTestInfo.iItem;
 }
 
@@ -1430,7 +1475,7 @@ long wxListCtrl::InsertItem(wxListItem& info)
     bool needInternalData = ((info.m_mask & wxLIST_MASK_DATA) || info.HasAttributes());
     if (needInternalData)
     {
-        m_AnyInternalData = TRUE;
+        m_AnyInternalData = true;
         item.mask |= LVIF_PARAM;
 
         // internal stucture that manages data
@@ -1440,16 +1485,20 @@ long wxListCtrl::InsertItem(wxListItem& info)
         if (info.m_mask & wxLIST_MASK_DATA)
             data->lParam = info.m_data;
 
-    // check whether it has any custom attributes
-    if ( info.HasAttributes() )
-    {
+        // check whether it has any custom attributes
+        if ( info.HasAttributes() )
+        {
             // take copy of attributes
             data->attr = new wxListItemAttr(*info.GetAttributes());
-    }
+
+            // and remember that we have some now...
+            m_hasAnyAttr = true;
+        }
     };
 
     long rv = ListView_InsertItem(GetHwnd(), & item);
-    m_count += 1;
+
+    m_count++;
     wxASSERT_MSG( m_count == ListView_GetItemCount(GetHwnd()),
                   wxT("m_count should match ListView_GetItemCount"));
 
@@ -1500,34 +1549,18 @@ long wxListCtrl::InsertColumn(long col, wxListItem& item)
         lvCol.cx = 80;
     }
 
-    // when we insert a column which can contain an image, we must specify this
-    // flag right now as doing it later in SetColumn() has no effect
-    //
-    // we use LVCFMT_BITMAP_ON_RIGHT by default because without it there is no
-    // way to dynamically set/clear the bitmap as the column without a bitmap
-    // on the left looks ugly (there is a hole)
-    //
-    // unfortunately with my version of comctl32.dll (5.80), the left column
-    // image is always on the left and it seems that it's a "feature" - I
-    // didn't find any way to work around it in any case
-    if ( lvCol.mask & LVCF_IMAGE )
-    {
-        lvCol.mask |= LVCF_FMT;
-        lvCol.fmt |= LVCFMT_BITMAP_ON_RIGHT;
-    }
-
-    bool success = ListView_InsertColumn(GetHwnd(), col, &lvCol) != -1;
-    if ( success )
+    long n = ListView_InsertColumn(GetHwnd(), col, &lvCol);
+    if ( n != -1 )
     {
         m_colCount++;
     }
-    else
+    else // failed to insert?
     {
         wxLogDebug(wxT("Failed to insert the column '%s' into listview!"),
                    lvCol.pszText);
     }
 
-    return success;
+    return n;
 }
 
 long wxListCtrl::InsertColumn(long col,
@@ -1556,10 +1589,10 @@ bool wxListCtrl::ScrollList(int dx, int dy)
     {
         wxLogDebug(_T("ListView_Scroll(%d, %d) failed"), dx, dy);
 
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 // Sort items.
@@ -1611,10 +1644,10 @@ bool wxListCtrl::SortItems(wxListCtrlCompare fn, long data)
     {
         wxLogDebug(_T("ListView_SortItems() failed"));
 
-        return FALSE;
+        return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 
@@ -1630,17 +1663,17 @@ bool wxListCtrl::MSWCommand(WXUINT cmd, WXWORD id)
         wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id);
         event.SetEventObject( this );
         ProcessCommand(event);
-        return TRUE;
+        return true;
     }
     else if (cmd == EN_KILLFOCUS)
     {
         wxCommandEvent event(wxEVT_KILL_FOCUS, id);
         event.SetEventObject( this );
         ProcessCommand(event);
-        return TRUE;
+        return true;
     }
     else
-        return FALSE;
+        return false;
 }
 
 bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
@@ -1705,6 +1738,9 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 event.m_col = nmHDR->iItem;
                 break;
 
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
+            case GN_CONTEXTMENU:
+#endif //__WXWINCE__
             case NM_RCLICK:
                 {
                     eventType = wxEVT_COMMAND_LIST_COL_RIGHT_CLICK;
@@ -1716,12 +1752,17 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 
                     // where did the click occur?
                     POINT ptClick;
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
+                  if(nmhdr->code == GN_CONTEXTMENU) {
+                      ptClick = ((NMRGINFO*)nmhdr)->ptAction;
+                  } else
+#endif //__WXWINCE__
                     if ( !::GetCursorPos(&ptClick) )
                     {
                         wxLogLastError(_T("GetCursorPos"));
                     }
 
-                    if ( !::ScreenToClient(hwndHdr, &ptClick) )
+                    if ( !::ScreenToClient(GetHwnd(), &ptClick) )
                     {
                         wxLogLastError(_T("ScreenToClient(listctrl header)"));
                     }
@@ -1747,20 +1788,15 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 break;
 
             case HDN_GETDISPINFOW:
-                {
-                    LPNMHDDISPINFOW info = (LPNMHDDISPINFOW) lParam;
-                    // This is a fix for a strange bug under XP.
-                    // Normally, info->iItem is a valid index, but
-                    // sometimes this is a silly (large) number
-                    // and when we return FALSE via wxControl::MSWOnNotify
-                    // to indicate that it hasn't yet been processed,
-                    // there's a GPF in Windows.
-                    // By returning TRUE here, we avoid further processing
-                    // of this strange message.
-                    if ( info->iItem >= GetColumnCount() )
-                        return TRUE;
-                }
-                // fall through
+                // letting Windows XP handle this message results in mysterious
+                // crashes in comctl32.dll seemingly because of bad message
+                // parameters
+                //
+                // I have no idea what is the real cause of the bug (which is,
+                // just to make things interesting, is impossible to reproduce
+                // reliably) but ignoring all these messages does fix it and
+                // doesn't seem to have any negative consequences
+                return true;
 
             default:
                 return wxControl::MSWOnNotify(idCtrl, lParam, result);
@@ -1782,7 +1818,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
         if ( m_ignoreChangeMessages &&
              ( (nmLV->hdr.code == LVN_ITEMCHANGED) || (nmLV->hdr.code == LVN_ITEMCHANGING)))
         {
-            return TRUE;
+            return true;
         }
 
 
@@ -1816,55 +1852,43 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 break;
 
             // NB: we have to handle both *A and *W versions here because some
-            //    versions of comctl32.dll send ANSI message to an Unicode app
+            //     versions of comctl32.dll send ANSI messages even to the
+            //     Unicode windows
             case LVN_BEGINLABELEDITA:
-                {
-                    eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
-                    wxLV_ITEM item(((LV_DISPINFOA *)lParam)->item);
-                    wxConvertFromMSWListItem(GetHwnd(), event.m_item, item);
-                    event.m_itemIndex = event.m_item.m_itemId;
-                }
-                break;
             case LVN_BEGINLABELEDITW:
                 {
+                    wxLV_ITEM item;
+                    if ( nmhdr->code == LVN_BEGINLABELEDITA )
+                    {
+                        item.Init(((LV_DISPINFOA *)lParam)->item);
+                    }
+                    else // LVN_BEGINLABELEDITW
+                    {
+                        item.Init(((LV_DISPINFOW *)lParam)->item);
+                    }
+
                     eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
-                    wxLV_ITEM item(((LV_DISPINFOW *)lParam)->item);
                     wxConvertFromMSWListItem(GetHwnd(), event.m_item, item);
                     event.m_itemIndex = event.m_item.m_itemId;
                 }
                 break;
 
             case LVN_ENDLABELEDITA:
+            case LVN_ENDLABELEDITW:
                 {
-                    eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
-                    wxLV_ITEM item(((LV_DISPINFOA *)lParam)->item);
-                    wxConvertFromMSWListItem(NULL, event.m_item, item);
-                    if ( ((LV_ITEM)item).pszText == NULL ||
-                         ((LV_ITEM)item).iItem == -1 )
+                    wxLV_ITEM item;
+                    if ( nmhdr->code == LVN_ENDLABELEDITA )
                     {
-                        // don't keep a stale wxTextCtrl around
-                        if ( m_textCtrl )
-                        {
-                            // EDIT control will be deleted by the list control itself so
-                            // prevent us from deleting it as well
-                            m_textCtrl->UnsubclassWin();
-                            m_textCtrl->SetHWND(0);
-                            delete m_textCtrl;
-                            m_textCtrl = NULL;
-                        }
-                        return FALSE;
+                        item.Init(((LV_DISPINFOA *)lParam)->item);
+                    }
+                    else // LVN_ENDLABELEDITW
+                    {
+                        item.Init(((LV_DISPINFOW *)lParam)->item);
                     }
 
-                    event.m_itemIndex = event.m_item.m_itemId;
-                }
-                break;
-            case LVN_ENDLABELEDITW:
-                {
-                    eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
-                    wxLV_ITEM item(((LV_DISPINFOW *)lParam)->item);
-                    wxConvertFromMSWListItem(NULL, event.m_item, item);
-                    if ( ((LV_ITEM)item).pszText == NULL ||
-                         ((LV_ITEM)item).iItem == -1 )
+                    // was editing cancelled?
+                    const LV_ITEM& lvi = (LV_ITEM)item;
+                    if ( !lvi.pszText || lvi.iItem == -1 )
                     {
                         // don't keep a stale wxTextCtrl around
                         if ( m_textCtrl )
@@ -1876,9 +1900,12 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                             delete m_textCtrl;
                             m_textCtrl = NULL;
                         }
-                        return FALSE;
+
+                        event.SetEditCanceled(true);
                     }
 
+                    eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
+                    wxConvertFromMSWListItem(NULL, event.m_item, item);
                     event.m_itemIndex = event.m_item.m_itemId;
                 }
                 break;
@@ -1899,7 +1926,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 if (m_count == 0)
                     // this should be prevented by the post-processing code below,
                     // but "just in case"
-                    return FALSE;
+                    return false;
 
                 eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
                 event.m_itemIndex = iItem;
@@ -1907,6 +1934,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 wxDeleteInternalData(this, iItem);
                 break;
 
+#if WXWIN_COMPATIBILITY_2_4
             case LVN_SETDISPINFO:
                 {
                     eventType = wxEVT_COMMAND_LIST_SET_INFO;
@@ -1914,6 +1942,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                     wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
                 }
                 break;
+#endif
 
             case LVN_INSERTITEM:
                 eventType = wxEVT_COMMAND_LIST_INSERT_ITEM;
@@ -1922,7 +1951,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 
             case LVN_ITEMCHANGED:
                 // we translate this catch all message into more interesting
-                // (and more easy to process) wxWindows events
+                // (and more easy to process) wxWidgets events
 
                 // first of all, we deal with the state change events only and
                 // only for valid items (item == -1 for the virtual list
@@ -1972,7 +2001,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 if ( eventType == wxEVT_NULL )
                 {
                     // not an interesting event for us
-                    return FALSE;
+                    return false;
                 }
 
                 break;
@@ -2023,7 +2052,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 // anything else
                 if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
                 {
-                    return TRUE;
+                    return true;
                 }
 
                 // else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event
@@ -2031,7 +2060,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 if ( iItem == -1 )
                 {
                     // not on item
-                    return FALSE;
+                    return false;
                 }
 
                 eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
@@ -2040,18 +2069,26 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 event.m_item.m_data = GetItemData(iItem);
                 break;
 
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
+            case GN_CONTEXTMENU:
+#endif //__WXWINCE__
             case NM_RCLICK:
                 // if the user processes it in wxEVT_COMMAND_RIGHT_CLICK(),
                 // don't do anything else
                 if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
                 {
-                    return TRUE;
+                    return true;
                 }
 
                 // else translate it into wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK event
                 LV_HITTESTINFO lvhti;
                 wxZeroMemory(lvhti);
 
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
+              if(nmhdr->code == GN_CONTEXTMENU) {
+                  lvhti.pt = ((NMRGINFO*)nmhdr)->ptAction;
+              } else
+#endif //__WXWINCE__
                 ::GetCursorPos(&(lvhti.pt));
                 ::ScreenToClient(GetHwnd(),&(lvhti.pt));
                 if ( ListView_HitTest(GetHwnd(),&lvhti) != -1 )
@@ -2066,12 +2103,11 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 }
                 break;
 
-#if defined(_WIN32_IE) && _WIN32_IE >= 0x300 \
-        && !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
+#ifdef NM_CUSTOMDRAW
             case NM_CUSTOMDRAW:
                 *result = OnCustomDraw(lParam);
 
-                return TRUE;
+                return true;
 #endif // _WIN32_IE >= 0x300
 
             case LVN_ODCACHEHINT:
@@ -2080,21 +2116,18 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 
                     eventType = wxEVT_COMMAND_LIST_CACHE_HINT;
 
-                    // we get some really stupid cache hints like ones for items in
-                    // range 0..0 for an empty control or, after deleting an item,
-                    // for items in invalid range - filter this garbage out
-                    if ( cacheHint->iFrom < cacheHint->iTo )
-                    {
-                        event.m_oldItemIndex = cacheHint->iFrom;
+                    // we get some really stupid cache hints like ones for
+                    // items in range 0..0 for an empty control or, after
+                    // deleting an item, for items in invalid range -- filter
+                    // this garbage out
+                    if ( cacheHint->iFrom > cacheHint->iTo )
+                        return false;
 
-                        long iMax = GetItemCount();
-                        event.m_itemIndex = cacheHint->iTo < iMax ? cacheHint->iTo
-                                                                  : iMax - 1;
-                    }
-                    else
-                    {
-                        return FALSE;
-                    }
+                    event.m_oldItemIndex = cacheHint->iFrom;
+
+                    const long iMax = GetItemCount();
+                    event.m_itemIndex = cacheHint->iTo < iMax ? cacheHint->iTo
+                                                              : iMax - 1;
                 }
                 break;
 
@@ -2112,20 +2145,20 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                         wxStrncpy(lvi.pszText, text, lvi.cchTextMax);
                     }
 
-#if defined(_WIN32_IE) && _WIN32_IE >= 0x300 \
-        && !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 1 ) )
+                    // see comment at the end of wxListCtrl::GetColumn()
+#ifdef NM_CUSTOMDRAW
                     if ( lvi.mask & LVIF_IMAGE )
                     {
                         lvi.iImage = OnGetItemImage(item);
                     }
-#endif
+#endif // NM_CUSTOMDRAW
 
                     // a little dose of healthy paranoia: as we never use
                     // LVM_SETCALLBACKMASK we're not supposed to get these ones
                     wxASSERT_MSG( !(lvi.mask & LVIF_STATE),
                                   _T("we don't support state callbacks yet!") );
 
-                    return TRUE;
+                    return true;
                 }
                 // fall through
 
@@ -2136,7 +2169,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
     else
     {
         // where did this one come from?
-        return FALSE;
+        return false;
     }
 
     // process the event
@@ -2151,11 +2184,15 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
     switch ( nmhdr->code )
     {
         case LVN_DELETEALLITEMS:
-            // always return TRUE to suppress all additional LVN_DELETEITEM
+            // always return true to suppress all additional LVN_DELETEITEM
             // notifications - this makes deleting all items from a list ctrl
             // much faster
             *result = TRUE;
-            return TRUE;
+
+            // also, we may free all user data now (couldn't do it before as
+            // the user should have access to it in OnDeleteAllItems() handler)
+            FreeAllInternalData();
+            return true;
 
         case LVN_ENDLABELEDITA:
         case LVN_ENDLABELEDITW:
@@ -2173,7 +2210,7 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                 m_textCtrl = NULL;
             }
 
-            return TRUE;
+            return true;
     }
 
     if ( processed )
@@ -2182,7 +2219,8 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
     return processed;
 }
 
-#if defined(_WIN32_IE) && _WIN32_IE >= 0x300
+// see comment at the end of wxListCtrl::GetColumn()
+#ifdef NM_CUSTOMDRAW // _WIN32_IE >= 0x0300
 
 WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam)
 {
@@ -2282,12 +2320,10 @@ void wxListCtrl::OnPaint(wxPaintEvent& event)
     // Reset the device origin since it may have been set
     dc.SetDeviceOrigin(0, 0);
 
-    bool drawHRules = ((GetWindowStyle() & wxLC_HRULES) != 0);
-    bool drawVRules = ((GetWindowStyle() & wxLC_VRULES) != 0);
+    bool drawHRules = HasFlag(wxLC_HRULES);
+    bool drawVRules = HasFlag(wxLC_VRULES);
 
-    if (!drawHRules && !drawVRules)
-        return;
-    if ((GetWindowStyle() & wxLC_REPORT) == 0)
+    if (!InReportView() || !drawHRules && !drawVRules)
         return;
 
     wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID);
@@ -2296,7 +2332,6 @@ void wxListCtrl::OnPaint(wxPaintEvent& event)
 
     wxSize clientSize = GetClientSize();
     wxRect itemRect;
-    int cy=0;
 
     int itemCount = GetItemCount();
     int i;
@@ -2307,7 +2342,7 @@ void wxListCtrl::OnPaint(wxPaintEvent& event)
         {
             if (GetItemRect(i, itemRect))
             {
-                cy = itemRect.GetTop();
+                int cy = itemRect.GetTop();
                 if (i != 0) // Don't draw the first one
                 {
                     dc.DrawLine(0, cy, clientSize.x, cy);
@@ -2356,9 +2391,9 @@ wxString wxListCtrl::OnGetItemText(long WXUNUSED(item), long WXUNUSED(col)) cons
 
 int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
 {
-    // same as above
-    wxFAIL_MSG( _T("wxListCtrl::OnGetItemImage not supposed to be called") );
-
+    wxCHECK_MSG(!GetImageList(wxIMAGE_LIST_SMALL),
+                -1,
+                wxT("List control has an image list, OnGetItemImage should be overridden."));
     return -1;
 }
 
@@ -2375,7 +2410,8 @@ void wxListCtrl::SetItemCount(long count)
 {
     wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") );
 
-    if ( !::SendMessage(GetHwnd(), LVM_SETITEMCOUNT, (WPARAM)count, LVSICF_NOSCROLL) )
+    if ( !::SendMessage(GetHwnd(), LVM_SETITEMCOUNT, (WPARAM)count,
+                        LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL) )
     {
         wxLogLastError(_T("ListView_SetItemCount"));
     }
@@ -2412,31 +2448,33 @@ void wxListCtrl::RefreshItems(long itemFrom, long itemTo)
     RefreshRect(rect);
 }
 
+// ----------------------------------------------------------------------------
+// internal data stuff
+// ----------------------------------------------------------------------------
+
 static wxListItemInternalData *wxGetInternalData(HWND hwnd, long itemId)
 {
     LV_ITEM it;
     it.mask = LVIF_PARAM;
     it.iItem = itemId;
 
-    bool success = ListView_GetItem(hwnd, &it) != 0;
-    if (success)
-        return (wxListItemInternalData *) it.lParam;
-    else
+    if ( !ListView_GetItem(hwnd, &it) )
         return NULL;
+
+    return (wxListItemInternalData *) it.lParam;
 };
 
-static wxListItemInternalData *wxGetInternalData(wxListCtrl *ctl, long itemId)
+static
+wxListItemInternalData *wxGetInternalData(const wxListCtrl *ctl, long itemId)
 {
-    return wxGetInternalData((HWND) ctl->GetHWND(), itemId);
+    return wxGetInternalData(GetHwndOf(ctl), itemId);
 };
 
 static wxListItemAttr *wxGetInternalDataAttr(wxListCtrl *ctl, long itemId)
 {
     wxListItemInternalData *data = wxGetInternalData(ctl, itemId);
-    if (data)
-        return data->attr;
-    else
-        return NULL;
+
+    return data ? data->attr : NULL;
 };
 
 static void wxDeleteInternalData(wxListCtrl* ctl, long itemId)
@@ -2454,6 +2492,10 @@ static void wxDeleteInternalData(wxListCtrl* ctl, long itemId)
     }
 }
 
+// ----------------------------------------------------------------------------
+// wxWin <-> MSW items conversions
+// ----------------------------------------------------------------------------
+
 static void wxConvertFromMSWListItem(HWND hwndListCtrl,
                                      wxListItem& info,
                                      LV_ITEM& lvItem)
@@ -2471,13 +2513,13 @@ static void wxConvertFromMSWListItem(HWND hwndListCtrl,
 
     long oldMask = lvItem.mask;
 
-    bool needText = FALSE;
+    bool needText = false;
     if (hwndListCtrl != 0)
     {
         if ( lvItem.mask & LVIF_TEXT )
-            needText = FALSE;
+            needText = false;
         else
-            needText = TRUE;
+            needText = true;
 
         if ( needText )
         {
@@ -2592,7 +2634,7 @@ static void wxConvertToMSWListItem(const wxListCtrl *ctrl,
     if (info.m_mask & wxLIST_MASK_TEXT)
     {
         lvItem.mask |= LVIF_TEXT;
-        if ( ctrl->GetWindowStyleFlag() & wxLC_USER_TEXT )
+        if ( ctrl->HasFlag(wxLC_USER_TEXT) )
         {
             lvItem.pszText = LPSTR_TEXTCALLBACK;
         }
@@ -2644,18 +2686,29 @@ static void wxConvertToMSWListCol(int WXUNUSED(col), const wxListItem& item,
             lvCol.cx = item.m_width;
     }
 
-#if defined(_WIN32_IE) && _WIN32_IE >= 0x300 \
-        && !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 1 ) )
+    // see comment at the end of wxListCtrl::GetColumn()
+#ifdef NM_CUSTOMDRAW // _WIN32_IE >= 0x0300
     if ( item.m_mask & wxLIST_MASK_IMAGE )
     {
         if ( wxTheApp->GetComCtl32Version() >= 470 )
         {
-            lvCol.mask |= LVCF_IMAGE;
+            lvCol.mask |= LVCF_IMAGE | LVCF_FMT;
+
+            // we use LVCFMT_BITMAP_ON_RIGHT because thei mages on the right
+            // seem to be generally nicer than on the left and the generic
+            // version only draws them on the right (we don't have a flag to
+            // specify the image location anyhow)
+            //
+            // we don't use LVCFMT_COL_HAS_IMAGES because it doesn't seem to
+            // make any difference in my tests -- but maybe we should?
+            lvCol.fmt |= LVCFMT_BITMAP_ON_RIGHT | LVCFMT_IMAGE;
+
             lvCol.iImage = item.m_image;
         }
         //else: it doesn't support item images anyhow
     }
-#endif
+#endif // _WIN32_IE >= 0x0300
 }
 
 #endif // wxUSE_LISTCTRL
+