/////////////////////////////////////////////////////////////////////////////
-// Name: listctrl.cpp
+// Name: src/msw/listctrl.cpp
// Purpose: wxListCtrl
// Author: Julian Smart
// Modified by:
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)
+DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT)
IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl)
// Deletes an item
bool wxListCtrl::DeleteItem(long item)
{
- return (ListView_DeleteItem(GetHwnd(), (int) item) != 0);
+ if ( !ListView_DeleteItem(GetHwnd(), (int) item) )
+ {
+ wxLogLastError(_T("ListView_DeleteItem"));
+ return FALSE;
+ }
+
+ // the virtual list control doesn't refresh itself correctly, help it
+ if ( IsVirtual() )
+ {
+ // we need to refresh all the lines below the one which was deleted
+ wxRect rectItem;
+ if ( item > 0 && GetItemCount() )
+ {
+ GetItemRect(item - 1, rectItem);
+ }
+ else
+ {
+ rectItem.y =
+ rectItem.height = 0;
+ }
+
+ wxRect rectWin = GetRect();
+ rectWin.height = rectWin.GetBottom() - rectItem.GetBottom();
+ rectWin.y = rectItem.GetBottom();
+
+ RefreshRect(rectWin);
+ }
+
+ return TRUE;
}
// Deletes all items
bool wxListCtrl::DeleteAllItems()
{
- return (ListView_DeleteAllItems(GetHwnd()) != 0);
+ return ListView_DeleteAllItems(GetHwnd()) != 0;
}
// Deletes all items
// -----------------
wxListEvent event(wxEVT_NULL, m_windowId);
+ event.SetEventObject(this);
+
wxEventType eventType = wxEVT_NULL;
NMHDR *nmhdr = (NMHDR *)lParam;
+ // if your compiler is as broken as this, you should really change it: this
+ // code is needed for normal operation! #ifdef below is only useful for
+ // automatic rebuilds which are done with a very old compiler version
+#ifdef LVM_FIRST
+
// check for messages from the header (in report view)
HWND hwndHdr = ListView_GetHeader(GetHwnd());
return wxControl::MSWOnNotify(idCtrl, lParam, result);
}
}
- else if ( nmhdr->hwndFrom == GetHwnd() )
+ else
+#endif // defined(LVM_FIRST)
+ if ( nmhdr->hwndFrom == GetHwnd() )
{
// almost all messages use NM_LISTVIEW
NM_LISTVIEW *nmLV = (NM_LISTVIEW *)nmhdr;
{
eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT;
LV_DISPINFO *info = (LV_DISPINFO *)lParam;
- wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
+ wxConvertFromMSWListItem(NULL, event.m_item, info->item);
if ( info->item.pszText == NULL || info->item.iItem == -1 )
return FALSE;
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;
- event.m_itemIndex = nmLV->iItem;
- }
- else if ( !(nmLV->uNewState & LVIS_SELECTED) && (nmLV->uOldState & LVIS_SELECTED) )
+ // we translate this catch all message into more interesting
+ // (and more easy to process) wxWindows events
+
+ // first of all, we deal with the state change events only
+ if ( nmLV->uChanged & LVIF_STATE )
{
- eventType = wxEVT_COMMAND_LIST_ITEM_DESELECTED;
- event.m_itemIndex = nmLV->iItem;
+ // temp vars for readability
+ const UINT stOld = nmLV->uOldState;
+ const UINT stNew = nmLV->uNewState;
+
+ // has the focus changed?
+ if ( !(stOld & LVIS_FOCUSED) && (stNew & LVIS_FOCUSED) )
+ {
+ eventType = wxEVT_COMMAND_LIST_ITEM_FOCUSED;
+ event.m_itemIndex = nmLV->iItem;
+ }
+
+ if ( (stNew & LVIS_SELECTED) != (stOld & LVIS_SELECTED) )
+ {
+ if ( eventType != wxEVT_NULL )
+ {
+ // focus and selection have both changed: send the
+ // focus event from here and the selection one
+ // below
+ event.SetEventType(eventType);
+ (void)GetEventHandler()->ProcessEvent(event);
+ }
+ else // no focus event to send
+ {
+ // then need to set m_itemIndex as it wasn't done
+ // above
+ event.m_itemIndex = nmLV->iItem;
+ }
+
+ eventType = stNew & LVIS_SELECTED
+ ? wxEVT_COMMAND_LIST_ITEM_SELECTED
+ : wxEVT_COMMAND_LIST_ITEM_DESELECTED;
+ }
}
- else
+
+ if ( eventType == wxEVT_NULL )
{
+ // not an interesting event for us
return FALSE;
}
+
break;
case LVN_KEYDOWN:
else
{
eventType = wxEVT_COMMAND_LIST_KEY_DOWN;
- event.m_code = wxCharCodeMSWToWX(wVKey);
+
+ // wxCharCodeMSWToWX() returns 0 if the key is an ASCII
+ // value which should be used as is
+ int code = wxCharCodeMSWToWX(wVKey);
+ event.m_code = code ? code : wVKey;
}
event.m_itemIndex =
// process the event
// -----------------
- event.SetEventObject( this );
event.SetEventType(eventType);
if ( !GetEventHandler()->ProcessEvent(event) )