]> git.saurik.com Git - wxWidgets.git/commitdiff
added a bunch of new wxListCtrl messages: column right click and
authorVadim Zeitlin <vadim@wxwidgets.org>
Sat, 1 Sep 2001 01:01:51 +0000 (01:01 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sat, 1 Sep 2001 01:01:51 +0000 (01:01 +0000)
start/continue/end dragging column divider

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11530 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/latex/wx/listctrl.tex
docs/latex/wx/listevt.tex
include/wx/listctrl.h
samples/listctrl/listtest.cpp
samples/listctrl/listtest.h
src/generic/listctrl.cpp
src/msw/listctrl.cpp

index 783a2ffaf7a977bf7940bf17b597b1788fc4fcb0..f3c0c9b79b9c7a29b3dcd5e36bc91d98ed3531c6 100644 (file)
@@ -72,15 +72,19 @@ functions that take a \helpref{wxListEvent}{wxlistevent} argument.
 \twocolitem{{\bf EVT\_LIST\_END\_LABEL\_EDIT(id, func)}}{Finish editing a label. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.}
 \twocolitem{{\bf EVT\_LIST\_DELETE\_ITEM(id, func)}}{Delete an item.}
 \twocolitem{{\bf EVT\_LIST\_DELETE\_ALL\_ITEMS(id, func)}}{Delete all items.}
-\twocolitem{{\bf EVT\_LIST\_GET\_INFO(id, func)}}{Request information from the application, usually the item text.}
-\twocolitem{{\bf EVT\_LIST\_SET\_INFO(id, func)}}{Information is being supplied (not implemented).}
+%\twocolitem{{\bf EVT\_LIST\_GET\_INFO(id, func)}}{Request information from the application, usually the item text.}
+%\twocolitem{{\bf EVT\_LIST\_SET\_INFO(id, func)}}{Information is being supplied (not implemented).}
 \twocolitem{{\bf EVT\_LIST\_ITEM\_SELECTED(id, func)}}{The item has been selected.}
 \twocolitem{{\bf EVT\_LIST\_ITEM\_DESELECTED(id, func)}}{The item has been deselected.}
 \twocolitem{{\bf EVT\_LIST\_ITEM\_ACTIVATED(id, func)}}{The item has been activated (ENTER or double click).}
+\twocolitem{{\bf EVT\_LIST\_ITEM\_RIGHT\_CLICK(id, func)}}{An item has been right-clicked.}
 \twocolitem{{\bf EVT\_LIST\_KEY\_DOWN(id, func)}}{A key has been pressed.}
 \twocolitem{{\bf EVT\_LIST\_INSERT\_ITEM(id, func)}}{An item has been inserted.}
 \twocolitem{{\bf EVT\_LIST\_COL\_CLICK(id, func)}}{A column ({\bf m\_col}) has been left-clicked.}
-\twocolitem{{\bf EVT\_LIST\_ITEM\_RIGHT\_CLICK(id, func)}}{An item has been right-clicked.}
+\twocolitem{{\bf EVT\_LIST\_COL\_RIGHT\_CLICK(id, func)}}{A column ({\bf m\_col}) has been right-clicked.}
+\twocolitem{{\bf EVT\_LIST\_COL\_BEGIN\_DRAG(id, func)}}{The user started resizing a column - can be vetoed.}
+\twocolitem{{\bf EVT\_LIST\_COL\_DRAGGING(id, func)}}{The divider between columns is being dragged.}
+\twocolitem{{\bf EVT\_LIST\_COL\_END\_DRAG(id, func)}}{A column has been resized by the user.}
 \twocolitem{{\bf EVT\_LIST\_CACHE\_HINT(id, func)}}{Prepare cache for a virtual list control}
 \end{twocollist}%
 
index 867ecda597b24254dea522f41d6f3ffefbccd3c7..36f200c43de1aaa8814eace32cb12b245386bcac 100644 (file)
@@ -26,14 +26,19 @@ functions that take a wxListEvent argument.
 \twocolitem{{\bf EVT\_LIST\_END\_LABEL\_EDIT(id, func)}}{Finish editing a label. This can be prevented by calling \helpref{Veto()}{wxnotifyeventveto}.}
 \twocolitem{{\bf EVT\_LIST\_DELETE\_ITEM(id, func)}}{Delete an item.}
 \twocolitem{{\bf EVT\_LIST\_DELETE\_ALL\_ITEMS(id, func)}}{Delete all items.}
-\twocolitem{{\bf EVT\_LIST\_GET\_INFO(id, func)}}{Request information from the application, usually the item text.}
-\twocolitem{{\bf EVT\_LIST\_SET\_INFO(id, func)}}{Information is being supplied (not implemented).}
+%\twocolitem{{\bf EVT\_LIST\_GET\_INFO(id, func)}}{Request information from the application, usually the item text.}
+%\twocolitem{{\bf EVT\_LIST\_SET\_INFO(id, func)}}{Information is being supplied (not implemented).}
 \twocolitem{{\bf EVT\_LIST\_ITEM\_SELECTED(id, func)}}{The item has been selected.}
 \twocolitem{{\bf EVT\_LIST\_ITEM\_DESELECTED(id, func)}}{The item has been deselected.}
 \twocolitem{{\bf EVT\_LIST\_ITEM\_ACTIVATED(id, func)}}{The item has been activated (ENTER or double click).}
+\twocolitem{{\bf EVT\_LIST\_ITEM\_RIGHT\_CLICK(id, func)}}{An item has been right-clicked.}
 \twocolitem{{\bf EVT\_LIST\_KEY\_DOWN(id, func)}}{A key has been pressed.}
 \twocolitem{{\bf EVT\_LIST\_INSERT\_ITEM(id, func)}}{An item has been inserted.}
 \twocolitem{{\bf EVT\_LIST\_COL\_CLICK(id, func)}}{A column ({\bf m\_col}) has been left-clicked.}
+\twocolitem{{\bf EVT\_LIST\_COL\_RIGHT\_CLICK(id, func)}}{A column ({\bf m\_col}) has been right-clicked.}
+\twocolitem{{\bf EVT\_LIST\_COL\_BEGIN\_DRAG(id, func)}}{The user started resizing a column - can be vetoed.}
+\twocolitem{{\bf EVT\_LIST\_COL\_DRAGGING(id, func)}}{The divider between columns is being dragged.}
+\twocolitem{{\bf EVT\_LIST\_COL\_END\_DRAG(id, func)}}{A column has been resized by the user.}
 \twocolitem{{\bf EVT\_LIST\_CACHE\_HINT(id, func)}}{Prepare cache for a virtual list control}
 \end{twocollist}%
 
@@ -85,7 +90,10 @@ The old item index.
 
 \constfunc{int}{GetColumn}{\void}
 
-The column position.
+The column position: it is only used with {\tt COL} events. For the column
+dragging events, it is the column to the left of the divider being dragged, for
+the column click events it may be $-1$ if the user clicked in the list control
+header outside any column.
 
 \membersection{wxListEvent::Cancelled}\label{wxlisteventcancelled}
 
index 8526b2ef274468a4852a5d83103d44197acfebd1..5de7d0c77cab9e39420feefe7098b517e17c16e8 100644 (file)
@@ -399,6 +399,10 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, 714)
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED, 715)
     DECLARE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT, 716)
+    DECLARE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, 717)
+    DECLARE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, 718)
+    DECLARE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING, 719)
+    DECLARE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG, 720)
 END_DECLARE_EVENT_TYPES()
 
 typedef void (wxEvtHandler::*wxListEventFunction)(wxListEvent&);
@@ -411,14 +415,21 @@ typedef void (wxEvtHandler::*wxListEventFunction)(wxListEvent&);
 #define EVT_LIST_DELETE_ALL_ITEMS(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
 #define EVT_LIST_GET_INFO(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_GET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
 #define EVT_LIST_SET_INFO(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_SET_INFO, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
-#define EVT_LIST_ITEM_SELECTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_ITEM_SELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
-#define EVT_LIST_ITEM_DESELECTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_ITEM_DESELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
 #define EVT_LIST_KEY_DOWN(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_KEY_DOWN, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
 #define EVT_LIST_INSERT_ITEM(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_INSERT_ITEM, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
+
 #define EVT_LIST_COL_CLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_COL_CLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
+#define EVT_LIST_COL_RIGHT_CLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
+#define EVT_LIST_COL_BEGIN_DRAG(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
+#define EVT_LIST_COL_DRAGGING(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_COL_DRAGGING, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
+#define EVT_LIST_COL_END_DRAG(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_COL_END_DRAG, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
+
+#define EVT_LIST_ITEM_SELECTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_ITEM_SELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
+#define EVT_LIST_ITEM_DESELECTED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_ITEM_DESELECTED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, NULL ),
 #define EVT_LIST_ITEM_RIGHT_CLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, (wxObject *) NULL ),
 #define EVT_LIST_ITEM_MIDDLE_CLICK(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, (wxObject *) NULL ),
 #define EVT_LIST_ITEM_ACTIVATED(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, (wxObject *) NULL ),
+
 #define EVT_LIST_CACHE_HINT(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_COMMAND_LIST_CACHE_HINT, id, -1, (wxObjectEventFunction) (wxEventFunction) (wxListEventFunction) & fn, (wxObject *) NULL ),
 
 #endif // wxUSE_LISTCTRL
index b355ed1a7f3f8e573f11168dad24de8dd623dcf2..862ac6d52d13a62ed64ac1afa7aefe83852ed416 100644 (file)
@@ -90,7 +90,13 @@ BEGIN_EVENT_TABLE(MyListCtrl, wxListCtrl)
     EVT_LIST_ITEM_DESELECTED(LIST_CTRL, MyListCtrl::OnDeselected)
     EVT_LIST_KEY_DOWN(LIST_CTRL, MyListCtrl::OnListKeyDown)
     EVT_LIST_ITEM_ACTIVATED(LIST_CTRL, MyListCtrl::OnActivated)
+
     EVT_LIST_COL_CLICK(LIST_CTRL, MyListCtrl::OnColClick)
+    EVT_LIST_COL_RIGHT_CLICK(LIST_CTRL, MyListCtrl::OnColRightClick)
+    EVT_LIST_COL_BEGIN_DRAG(LIST_CTRL, MyListCtrl::OnColBeginDrag)
+    EVT_LIST_COL_DRAGGING(LIST_CTRL, MyListCtrl::OnColDragging)
+    EVT_LIST_COL_END_DRAG(LIST_CTRL, MyListCtrl::OnColEndDrag)
+
     EVT_LIST_CACHE_HINT(LIST_CTRL, MyListCtrl::OnCacheHint)
 
     EVT_CHAR(MyListCtrl::OnChar)
@@ -577,6 +583,26 @@ void MyListCtrl::OnColClick(wxListEvent& event)
     wxLogMessage( wxT("OnColumnClick at %d."), event.GetColumn() );
 }
 
+void MyListCtrl::OnColRightClick(wxListEvent& event)
+{
+    wxLogMessage( wxT("OnColumnRightClick at %d."), event.GetColumn() );
+}
+
+void MyListCtrl::OnColBeginDrag(wxListEvent& event)
+{
+    wxLogMessage( wxT("OnColBeginDrag: column %d."), event.GetColumn() );
+}
+
+void MyListCtrl::OnColDragging(wxListEvent& event)
+{
+    wxLogMessage( wxT("OnColDragging: column %d."), event.GetColumn() );
+}
+
+void MyListCtrl::OnColEndDrag(wxListEvent& event)
+{
+    wxLogMessage( wxT("OnColEndDrag: column %d."), event.GetColumn() );
+}
+
 void MyListCtrl::OnBeginDrag(wxListEvent& event)
 {
     const wxPoint& pt = event.m_pointDrag;
index f649e03a7960c75a0eb134b613180940c2e8c72d..d91ce1b9f4c9a72a9000e03b6ba4c4364e75b773 100644 (file)
@@ -33,6 +33,10 @@ public:
     void InsertItemInReportView(int i);
 
     void OnColClick(wxListEvent& event);
+    void OnColRightClick(wxListEvent& event);
+    void OnColBeginDrag(wxListEvent& event);
+    void OnColDragging(wxListEvent& event);
+    void OnColEndDrag(wxListEvent& event);
     void OnBeginDrag(wxListEvent& event);
     void OnBeginRDrag(wxListEvent& event);
     void OnBeginLabelEdit(wxListEvent& event);
index b6e7e543c214b0c5ecb8c6a723896c2c1b745a3b..6289db800ce1e0b9dd67541747b3522635c20254 100644 (file)
@@ -65,6 +65,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
@@ -1973,19 +1977,22 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event )
             m_minX = xpos;
         }
 
-        if (event.LeftDown())
+        if (event.LeftDown() || event.RightUp())
         {
-            if (hit_border)
+            if (hit_border && event.LeftDown())
             {
                 m_isDragging = TRUE;
                 m_currentX = x;
                 DrawCurrent();
                 CaptureMouse();
             }
-            else
+            else // click on a column
             {
                 wxWindow *parent = GetParent();
-                wxListEvent le( wxEVT_COMMAND_LIST_COL_CLICK, parent->GetId() );
+                wxListEvent le( event.LeftDown()
+                                    ? wxEVT_COMMAND_LIST_COL_CLICK
+                                    : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK,
+                                parent->GetId() );
                 le.SetEventObject( parent );
                 le.m_col = m_column;
                 parent->GetEventHandler()->ProcessEvent( le );
index 1196685fe8506f99ad660b9d43176a5734a05e96..406282e30553dfee8eb3df7acffbea6a27a954c8 100644 (file)
@@ -117,6 +117,10 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK)
 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED)
@@ -1478,172 +1482,249 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 
     NMHDR *nmhdr = (NMHDR *)lParam;
 
-    // almost all messages use NM_LISTVIEW
-    NM_LISTVIEW *nmLV = (NM_LISTVIEW *)nmhdr;
+    // check for messages from the header (in report view)
+    HWND hwndHdr = ListView_GetHeader(GetHwnd());
 
-    // this is true for almost all events
-    event.m_item.m_data = nmLV->lParam;
-
-    switch ( nmhdr->code )
+    // is it a message from the header?
+    if ( nmhdr->hwndFrom == hwndHdr )
     {
-        case LVN_BEGINRDRAG:
-            eventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
-            // fall through
+        NMHEADER *nmHDR = (NMHEADER *)nmhdr;
+        event.m_itemIndex = -1;
 
-        case LVN_BEGINDRAG:
-            if ( eventType == wxEVT_NULL )
-            {
-                eventType = wxEVT_COMMAND_LIST_BEGIN_DRAG;
-            }
+        switch ( nmhdr->code )
+        {
+            // yet another comctl32.dll bug: under NT/W2K it sends Unicode
+            // TRACK messages even to ANSI programs: on my system I get
+            // HDN_BEGINTRACKW and HDN_ENDTRACKA and no HDN_TRACK at all!
+            //
+            // work around is to simply catch both versions and hope that it
+            // works (why should this message exist in ANSI and Unicode is
+            // beyond me as it doesn't deal with strings at all...)
+            case HDN_BEGINTRACKA:
+            case HDN_BEGINTRACKW:
+                eventType = wxEVT_COMMAND_LIST_COL_BEGIN_DRAG;
+                // fall through
+
+            case HDN_TRACKA:
+            case HDN_TRACKW:
+                if ( eventType == wxEVT_NULL )
+                    eventType = wxEVT_COMMAND_LIST_COL_DRAGGING;
+                // fall through
+
+            case HDN_ENDTRACKA:
+            case HDN_ENDTRACKW:
+                if ( eventType == wxEVT_NULL )
+                    eventType = wxEVT_COMMAND_LIST_COL_END_DRAG;
+                event.m_col = nmHDR->iItem;
+                break;
+
+            case NM_RCLICK:
+                {
+                    eventType = wxEVT_COMMAND_LIST_COL_RIGHT_CLICK;
+                    event.m_col = -1;
 
-            event.m_itemIndex = nmLV->iItem;
-            event.m_pointDrag.x = nmLV->ptAction.x;
-            event.m_pointDrag.y = nmLV->ptAction.y;
-            break;
+                    // find the column clicked: we have to search for it
+                    // ourselves as the notification message doesn't provide
+                    // this info
 
-        case LVN_BEGINLABELEDIT:
-            {
-                eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
-                LV_DISPINFO *info = (LV_DISPINFO *)lParam;
-                wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
-                event.m_itemIndex = event.m_item.m_itemId;
-            }
-            break;
+                    // where did the click occur?
+                    POINT ptClick;
+                    if ( !::GetCursorPos(&ptClick) )
+                    {
+                        wxLogLastError(_T("GetCursorPos"));
+                    }
 
-        case LVN_COLUMNCLICK:
-            eventType = wxEVT_COMMAND_LIST_COL_CLICK;
-            event.m_itemIndex = -1;
-            event.m_col = nmLV->iSubItem;
-            break;
+                    if ( !::ScreenToClient(hwndHdr, &ptClick) )
+                    {
+                        wxLogLastError(_T("ScreenToClient(listctrl header)"));
+                    }
 
-        case LVN_DELETEALLITEMS:
-            eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS;
-            event.m_itemIndex = -1;
+                    event.m_pointDrag.x = ptClick.x;
+                    event.m_pointDrag.y = ptClick.y;
 
-            FreeAllAttrs();
+                    int colCount = Header_GetItemCount(hwndHdr);
 
-            break;
+                    RECT rect;
+                    for ( int col = 0; col < colCount; col++ )
+                    {
+                        if ( Header_GetItemRect(hwndHdr, col, &rect) )
+                        {
+                            if ( ::PtInRect(&rect, ptClick) )
+                            {
+                                event.m_col = col;
+                                break;
+                            }
+                        }
+                    }
+                }
+                break;
 
-        case LVN_DELETEITEM:
-            eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
-            event.m_itemIndex = nmLV->iItem;
+            default:
+                return wxControl::MSWOnNotify(idCtrl, lParam, result);
+        }
+    }
+    else if ( nmhdr->hwndFrom == GetHwnd() )
+    {
+        // almost all messages use NM_LISTVIEW
+        NM_LISTVIEW *nmLV = (NM_LISTVIEW *)nmhdr;
 
-            if ( m_hasAnyAttr )
-            {
-                delete (wxListItemAttr *)m_attrs.Delete(nmLV->iItem);
-            }
-            break;
+        // this is true for almost all events
+        event.m_item.m_data = nmLV->lParam;
 
-        case LVN_ENDLABELEDIT:
-            {
-                eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
-                LV_DISPINFO *info = (LV_DISPINFO *)lParam;
-                wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
-                if ( info->item.pszText == NULL || info->item.iItem == -1 )
-                    return FALSE;
+        switch ( nmhdr->code )
+        {
+            case LVN_BEGINRDRAG:
+                eventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
+                // fall through
 
-                event.m_itemIndex = event.m_item.m_itemId;
-            }
-            break;
+            case LVN_BEGINDRAG:
+                if ( eventType == wxEVT_NULL )
+                {
+                    eventType = wxEVT_COMMAND_LIST_BEGIN_DRAG;
+                }
 
-        case LVN_SETDISPINFO:
-            {
-                eventType = wxEVT_COMMAND_LIST_SET_INFO;
-                LV_DISPINFO *info = (LV_DISPINFO *)lParam;
-                wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
-            }
-            break;
+                event.m_itemIndex = nmLV->iItem;
+                event.m_pointDrag.x = nmLV->ptAction.x;
+                event.m_pointDrag.y = nmLV->ptAction.y;
+                break;
 
-        case LVN_INSERTITEM:
-            eventType = wxEVT_COMMAND_LIST_INSERT_ITEM;
-            event.m_itemIndex = nmLV->iItem;
-            break;
+            case LVN_BEGINLABELEDIT:
+                {
+                    eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
+                    LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+                    wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
+                    event.m_itemIndex = event.m_item.m_itemId;
+                }
+                break;
 
-        case LVN_ITEMCHANGED:
-            // This needs to be sent to wxListCtrl as a rather more concrete
-            // event. For now, just detect a selection or deselection.
-            if ( (nmLV->uNewState & LVIS_SELECTED) && !(nmLV->uOldState & LVIS_SELECTED) )
-            {
-                eventType = wxEVT_COMMAND_LIST_ITEM_SELECTED;
+            case LVN_COLUMNCLICK:
+                eventType = wxEVT_COMMAND_LIST_COL_CLICK;
+                event.m_itemIndex = -1;
+                event.m_col = nmLV->iSubItem;
+                break;
+
+            case LVN_DELETEALLITEMS:
+                eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS;
+                event.m_itemIndex = -1;
+
+                FreeAllAttrs();
+
+                break;
+
+            case LVN_DELETEITEM:
+                eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
                 event.m_itemIndex = nmLV->iItem;
-            }
-            else if ( !(nmLV->uNewState & LVIS_SELECTED) && (nmLV->uOldState & LVIS_SELECTED) )
-            {
-                eventType = wxEVT_COMMAND_LIST_ITEM_DESELECTED;
+
+                if ( m_hasAnyAttr )
+                {
+                    delete (wxListItemAttr *)m_attrs.Delete(nmLV->iItem);
+                }
+                break;
+
+            case LVN_ENDLABELEDIT:
+                {
+                    eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
+                    LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+                    wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
+                    if ( info->item.pszText == NULL || info->item.iItem == -1 )
+                        return FALSE;
+
+                    event.m_itemIndex = event.m_item.m_itemId;
+                }
+                break;
+
+            case LVN_SETDISPINFO:
+                {
+                    eventType = wxEVT_COMMAND_LIST_SET_INFO;
+                    LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+                    wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
+                }
+                break;
+
+            case LVN_INSERTITEM:
+                eventType = wxEVT_COMMAND_LIST_INSERT_ITEM;
                 event.m_itemIndex = nmLV->iItem;
-            }
-            else
-            {
-                return FALSE;
-            }
-            break;
+                break;
 
-        case LVN_KEYDOWN:
-            {
-                LV_KEYDOWN *info = (LV_KEYDOWN *)lParam;
-                WORD wVKey = info->wVKey;
-
-                // get the current selection
-                long lItem = GetNextItem(-1,
-                                         wxLIST_NEXT_ALL,
-                                         wxLIST_STATE_SELECTED);
-
-                // <Enter> or <Space> activate the selected item if any (but
-                // not with Shift and/or Ctrl as then they have a predefined
-                // meaning for the list view)
-                if ( lItem != -1 &&
-                     (wVKey == VK_RETURN || wVKey == VK_SPACE) &&
-                     !(wxIsShiftDown() || wxIsCtrlDown()) )
+            case LVN_ITEMCHANGED:
+                // This needs to be sent to wxListCtrl as a rather more concrete
+                // event. For now, just detect a selection or deselection.
+                if ( (nmLV->uNewState & LVIS_SELECTED) && !(nmLV->uOldState & LVIS_SELECTED) )
+                {
+                    eventType = wxEVT_COMMAND_LIST_ITEM_SELECTED;
+                    event.m_itemIndex = nmLV->iItem;
+                }
+                else if ( !(nmLV->uNewState & LVIS_SELECTED) && (nmLV->uOldState & LVIS_SELECTED) )
                 {
-                    eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
+                    eventType = wxEVT_COMMAND_LIST_ITEM_DESELECTED;
+                    event.m_itemIndex = nmLV->iItem;
                 }
                 else
                 {
-                    eventType = wxEVT_COMMAND_LIST_KEY_DOWN;
-                    event.m_code = wxCharCodeMSWToWX(wVKey);
+                    return FALSE;
                 }
+                break;
+
+            case LVN_KEYDOWN:
+                {
+                    LV_KEYDOWN *info = (LV_KEYDOWN *)lParam;
+                    WORD wVKey = info->wVKey;
+
+                    // get the current selection
+                    long lItem = GetNextItem(-1,
+                                             wxLIST_NEXT_ALL,
+                                             wxLIST_STATE_SELECTED);
+
+                    // <Enter> or <Space> activate the selected item if any (but
+                    // not with Shift and/or Ctrl as then they have a predefined
+                    // meaning for the list view)
+                    if ( lItem != -1 &&
+                         (wVKey == VK_RETURN || wVKey == VK_SPACE) &&
+                         !(wxIsShiftDown() || wxIsCtrlDown()) )
+                    {
+                        eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
+                    }
+                    else
+                    {
+                        eventType = wxEVT_COMMAND_LIST_KEY_DOWN;
+                        event.m_code = wxCharCodeMSWToWX(wVKey);
+                    }
 
-                event.m_itemIndex =
-                event.m_item.m_itemId = lItem;
+                    event.m_itemIndex =
+                    event.m_item.m_itemId = lItem;
+
+                    if ( lItem != -1 )
+                    {
+                        // fill the other fields too
+                        event.m_item.m_text = GetItemText(lItem);
+                        event.m_item.m_data = GetItemData(lItem);
+                    }
+                }
+                break;
 
-                if ( lItem != -1 )
+            case NM_DBLCLK:
+                // if the user processes it in wxEVT_COMMAND_LEFT_CLICK(), don't do
+                // anything else
+                if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
                 {
-                    // fill the other fields too
-                    event.m_item.m_text = GetItemText(lItem);
-                    event.m_item.m_data = GetItemData(lItem);
+                    return TRUE;
                 }
-            }
-            break;
 
-        case NM_DBLCLK:
-            // if the user processes it in wxEVT_COMMAND_LEFT_CLICK(), don't do
-            // anything else
-            if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
-            {
-                return TRUE;
-            }
+                // else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event
+                // if it happened on an item (and not on empty place)
+                if ( nmLV->iItem == -1 )
+                {
+                    // not on item
+                    return FALSE;
+                }
 
-            // else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event
-            // if it happened on an item (and not on empty place)
-            if ( nmLV->iItem == -1 )
-            {
-                // not on item
-                return FALSE;
-            }
+                eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
+                event.m_itemIndex = nmLV->iItem;
+                event.m_item.m_text = GetItemText(nmLV->iItem);
+                event.m_item.m_data = GetItemData(nmLV->iItem);
+                break;
 
-            eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
-            event.m_itemIndex = nmLV->iItem;
-            event.m_item.m_text = GetItemText(nmLV->iItem);
-            event.m_item.m_data = GetItemData(nmLV->iItem);
-            break;
-
-        case NM_RCLICK:
-            /* TECH NOTE: NM_RCLICK isn't really good enough here. We want to
-               subclass and check for the actual WM_RBUTTONDOWN message,
-               because NM_RCLICK waits for the WM_RBUTTONUP message as well
-               before firing off. We want to have notify events for both down
-               -and- up. */
-            {
+            case NM_RCLICK:
                 // if the user processes it in wxEVT_COMMAND_RIGHT_CLICK(),
                 // don't do anything else
                 if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
@@ -1667,89 +1748,76 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                         event.m_pointDrag.y = lvhti.pt.y;
                     }
                 }
-            }
-            break;
-
-#if 0
-        case NM_MCLICK: // ***** THERE IS NO NM_MCLICK. Subclass anyone? ******
-            {
-                // if the user processes it in wxEVT_COMMAND_MIDDLE_CLICK(), don't do
-                // anything else
-                if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
-                {
-                    return TRUE;
-                }
-
-                // else translate it into wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK event
-                eventType = wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK;
-                NMITEMACTIVATE* hdr = (NMITEMACTIVATE*)lParam;
-                event.m_itemIndex = hdr->iItem;
-            }
-            break;
-#endif // 0
+                break;
 
 #if defined(_WIN32_IE) && _WIN32_IE >= 0x300 \
-    && !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
-        case NM_CUSTOMDRAW:
-            *result = OnCustomDraw(lParam);
+        && !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) )
+            case NM_CUSTOMDRAW:
+                *result = OnCustomDraw(lParam);
 
-            return TRUE;
+                return TRUE;
 #endif // _WIN32_IE >= 0x300
 
-        case LVN_ODCACHEHINT:
-            {
-                const NM_CACHEHINT *cacheHint = (NM_CACHEHINT *)lParam;
+            case LVN_ODCACHEHINT:
+                {
+                    const NM_CACHEHINT *cacheHint = (NM_CACHEHINT *)lParam;
 
-                eventType = wxEVT_COMMAND_LIST_CACHE_HINT;
+                    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 )
+                    {
+                        event.m_oldItemIndex = cacheHint->iFrom;
 
-                    long iMax = GetItemCount();
-                    event.m_itemIndex = cacheHint->iTo < iMax ? cacheHint->iTo
-                                                              : iMax - 1;
-                }
-                else
-                {
-                    return FALSE;
+                        long iMax = GetItemCount();
+                        event.m_itemIndex = cacheHint->iTo < iMax ? cacheHint->iTo
+                                                                  : iMax - 1;
+                    }
+                    else
+                    {
+                        return FALSE;
+                    }
                 }
-            }
-            break;
+                break;
 
-        case LVN_GETDISPINFO:
-            if ( IsVirtual() )
-            {
-                LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+            case LVN_GETDISPINFO:
+                if ( IsVirtual() )
+                {
+                    LV_DISPINFO *info = (LV_DISPINFO *)lParam;
 
-                LV_ITEM& lvi = info->item;
-                long item = lvi.iItem;
+                    LV_ITEM& lvi = info->item;
+                    long item = lvi.iItem;
 
-                if ( lvi.mask & LVIF_TEXT )
-                {
-                    wxString text = OnGetItemText(item, lvi.iSubItem);
-                    wxStrncpy(lvi.pszText, text, lvi.cchTextMax);
-                }
+                    if ( lvi.mask & LVIF_TEXT )
+                    {
+                        wxString text = OnGetItemText(item, lvi.iSubItem);
+                        wxStrncpy(lvi.pszText, text, lvi.cchTextMax);
+                    }
 
-                if ( lvi.mask & LVIF_IMAGE )
-                {
-                    lvi.iImage = OnGetItemImage(item);
-                }
+                    if ( lvi.mask & LVIF_IMAGE )
+                    {
+                        lvi.iImage = OnGetItemImage(item);
+                    }
 
-                // 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!") );
+                    // 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;
-            }
-            // fall through
+                    return TRUE;
+                }
+                // fall through
 
-        default:
-            return wxControl::MSWOnNotify(idCtrl, lParam, result);
+            default:
+                return wxControl::MSWOnNotify(idCtrl, lParam, result);
+        }
+    }
+    else
+    {
+        // where did this one come from?
+        return FALSE;
     }
 
     // process the event