+ wxListEvent event(wxEVT_NULL, m_windowId);
+ wxEventType eventType = wxEVT_NULL;
+ NMHDR *nmhdr = (NMHDR *)lParam;
+ switch ( nmhdr->code )
+ {
+ case LVN_BEGINRDRAG:
+ eventType = wxEVT_COMMAND_LIST_BEGIN_RDRAG;
+ // fall through
+
+ case LVN_BEGINDRAG:
+ if ( eventType == wxEVT_NULL )
+ {
+ eventType = wxEVT_COMMAND_LIST_BEGIN_DRAG;
+ }
+
+ {
+ NM_LISTVIEW *hdr = (NM_LISTVIEW *)lParam;
+ event.m_itemIndex = hdr->iItem;
+ event.m_pointDrag.x = hdr->ptAction.x;
+ event.m_pointDrag.y = hdr->ptAction.y;
+ }
+ break;
+
+ case LVN_BEGINLABELEDIT:
+ {
+ eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT;
+ LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+ wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd());
+ break;
+ }
+
+ case LVN_COLUMNCLICK:
+ {
+ eventType = wxEVT_COMMAND_LIST_COL_CLICK;
+ NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
+ event.m_itemIndex = -1;
+ event.m_col = hdr->iSubItem;
+ break;
+ }
+
+ case LVN_DELETEALLITEMS:
+ // what's the sense of generating a wxWin event for this when
+ // it's absolutely not portable?
+#if 0
+ eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS;
+ event.m_itemIndex = -1;
+#endif // 0
+
+ // return TRUE to suppress all additional LVN_DELETEITEM
+ // notifications - this makes deleting all items from a list ctrl
+ // much faster
+ *result = TRUE;
+
+ return TRUE;
+
+ case LVN_DELETEITEM:
+ {
+ eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
+ NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
+ event.m_itemIndex = hdr->iItem;
+
+ if ( m_hasAnyAttr )
+ {
+ delete (wxListItemAttr *)m_attrs.Delete(hdr->iItem);
+ }
+ }
+ break;
+
+ case LVN_ENDLABELEDIT:
+ {
+ eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
+ LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+ wxConvertFromMSWListItem(this, event.m_item, info->item);
+ if ( info->item.pszText == NULL || info->item.iItem == -1 )
+ return FALSE;
+ }
+ break;
+
+ case LVN_SETDISPINFO:
+ {
+ eventType = wxEVT_COMMAND_LIST_SET_INFO;
+ LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+ wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd());
+ }
+ break;
+
+ case LVN_GETDISPINFO:
+ // this provokes stack overflow: indeed, wxConvertFromMSWListItem()
+ // sends us WM_NOTIFY! As it doesn't do anything for now, just leave
+ // it out.
+#if 0
+ {
+ // TODO: some text buffering here, I think
+ // TODO: API for getting Windows to retrieve values
+ // on demand.
+ eventType = wxEVT_COMMAND_LIST_GET_INFO;
+ LV_DISPINFO *info = (LV_DISPINFO *)lParam;
+ wxConvertFromMSWListItem(this, event.m_item, info->item, GetHwnd());
+ break;
+ }
+#endif // 0
+ return FALSE;
+
+
+ case LVN_INSERTITEM:
+ {
+ eventType = wxEVT_COMMAND_LIST_INSERT_ITEM;
+ NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
+ event.m_itemIndex = hdr->iItem;
+ 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.
+ NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
+ if ( (hdr->uNewState & LVIS_SELECTED) && !(hdr->uOldState & LVIS_SELECTED) )
+ {
+ eventType = wxEVT_COMMAND_LIST_ITEM_SELECTED;
+ event.m_itemIndex = hdr->iItem;
+ }
+ else if ( !(hdr->uNewState & LVIS_SELECTED) && (hdr->uOldState & LVIS_SELECTED) )
+ {
+ eventType = wxEVT_COMMAND_LIST_ITEM_DESELECTED;
+ event.m_itemIndex = hdr->iItem;
+ }
+ else
+ 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
+ if ( lItem != -1 && (wVKey == VK_RETURN || wVKey == VK_SPACE) )
+ {
+ // TODO this behaviour probably should be optional
+ eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
+ event.m_itemIndex = lItem;
+ }
+ else
+ {
+ eventType = wxEVT_COMMAND_LIST_KEY_DOWN;
+ event.m_code = wxCharCodeMSWToWX(wVKey);
+ }
+ 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)
+ {
+ NM_LISTVIEW* hdr = (NM_LISTVIEW*)lParam;
+ if ( hdr->iItem == -1 )
+ {
+ // not on item
+ return FALSE;
+ }
+
+ eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
+ event.m_itemIndex = hdr->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. */