#include "wx/vector.h"
#include "wx/msw/private.h"
+#include "wx/msw/private/keyboard.h"
#if defined(__WXWINCE__) && !defined(__HANDHELDPC__)
#include <ole2.h>
{
m_textCtrl->UnsubclassWin();
m_textCtrl->SetHWND(0);
- delete m_textCtrl;
- m_textCtrl = NULL;
+ wxDELETE(m_textCtrl);
}
}
}
// Gets the item text
-wxString wxListCtrl::GetItemText(long item) const
+wxString wxListCtrl::GetItemText(long item, int col) const
{
wxListItem info;
info.m_mask = wxLIST_MASK_TEXT;
info.m_itemId = item;
+ info.m_col = col;
if (!GetItem(info))
return wxEmptyString;
// Deletes all items
bool wxListCtrl::DeleteAllItems()
{
- return ListView_DeleteAllItems(GetHwnd()) != 0;
+ // Calling ListView_DeleteAllItems() will always generate an event but we
+ // shouldn't do it if the control is empty
+ return !GetItemCount() || ListView_DeleteAllItems(GetHwnd()) != 0;
}
// Deletes all items
if ( !hWnd )
{
// failed to start editing
- delete m_textCtrl;
- m_textCtrl = NULL;
+ wxDELETE(m_textCtrl);
return NULL;
}
if ( !hwnd )
return false;
- if ( cancel )
- ::SetWindowText(hwnd, wxEmptyString); // dubious but better than nothing
-
- // we shouldn't destroy the control ourselves according to MSDN, which
- // proposes WM_CANCELMODE to do this, but it doesn't seem to work
- //
- // posting WM_CLOSE to it does seem to work without any side effects
- ::PostMessage(hwnd, WM_CLOSE, 0, 0);
+ // Newer versions of Windows have a special message for cancelling editing,
+ // use it if available.
+#ifdef ListView_CancelEditLabel
+ if ( cancel && (wxApp::GetComCtl32Version() >= 600) )
+ {
+ ListView_CancelEditLabel(GetHwnd());
+ }
+ else
+#endif // ListView_CancelEditLabel
+ {
+ // We shouldn't destroy the control ourselves according to MSDN, which
+ // proposes WM_CANCELMODE to do this, but it doesn't seem to work so
+ // emulate the corresponding user action instead.
+ ::SendMessage(hwnd, WM_KEYDOWN, cancel ? VK_ESCAPE : VK_RETURN, 0);
+ }
return true;
}
event.m_itemIndex = -1;
+ bool ignore = false;
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!
+ // HDN_BEGINTRACKW and HDN_ENDTRACKA!
//
// 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...)
//
- // note that fr HDN_TRACK another possibility could be to use
- // HDN_ITEMCHANGING but it is sent even after HDN_ENDTRACK and when
- // something other than the item width changes so we'd have to
- // filter out the unwanted events then
+ // another problem is that HDN_TRACK is not sent at all by header
+ // with HDS_FULLDRAG style which is used by default by wxListCtrl
+ // under recent Windows versions (starting from at least XP) so we
+ // need to use HDN_ITEMCHANGING instead of it
case HDN_BEGINTRACKA:
case HDN_BEGINTRACKW:
eventType = wxEVT_COMMAND_LIST_COL_BEGIN_DRAG;
// fall through
- case HDN_TRACKA:
- case HDN_TRACKW:
+ case HDN_ITEMCHANGING:
if ( eventType == wxEVT_NULL )
+ {
+ if ( !nmHDR->pitem || !(nmHDR->pitem->mask & HDI_WIDTH) )
+ {
+ // something other than the width is being changed,
+ // ignore it
+ ignore = true;
+ break;
+ }
+
+ // also ignore the events sent when the width didn't really
+ // change: this is not just an optimization but also gets
+ // rid of a useless and unexpected DRAGGING event which
+ // would otherwise be sent after the END_DRAG one as we get
+ // an HDN_ITEMCHANGING after HDN_ENDTRACK for some reason
+ if ( nmHDR->pitem->cxy == GetColumnWidth(nmHDR->iItem) )
+ {
+ ignore = true;
+ break;
+ }
+
eventType = wxEVT_COMMAND_LIST_COL_DRAGGING;
+ }
// fall through
case HDN_ENDTRACKA:
return true;
default:
- return wxControl::MSWOnNotify(idCtrl, lParam, result);
+ ignore = true;
}
+
+ if ( ignore )
+ return wxControl::MSWOnNotify(idCtrl, lParam, result);
}
else
#endif // defined(HDN_BEGINTRACKA)
eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
event.m_itemIndex = iItem;
- // delete the associated internal data
- if ( wxMSWListItemData *data = MSWGetItemData(iItem) )
- {
- const unsigned count = m_internalData.size();
- for ( unsigned n = 0; n < count; n++ )
- {
- if ( m_internalData[n] == data )
- {
- m_internalData.erase(m_internalData.begin() + n);
- delete data;
- data = NULL;
- break;
- }
- }
-
- wxASSERT_MSG( !data, "invalid internal data pointer?" );
- }
break;
case LVN_INSERTITEM:
{
eventType = wxEVT_COMMAND_LIST_KEY_DOWN;
- // 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_code = wxMSWKeyboard::VKToWX(wVKey);
+
+ if ( event.m_code == WXK_NONE )
+ {
+ // We can't translate this to a standard key code,
+ // until support for Unicode key codes is added to
+ // wxListEvent we just ignore them.
+ return false;
+ }
}
event.m_itemIndex =
// wrap to the beginning if necessary
if ( currentPos == maxPos )
{
- // somewhat surprizingly, LVFI_WRAP isn't set in
+ // somewhat surprisingly, LVFI_WRAP isn't set in
// flags but we still should wrap
currentPos = 0;
}
m_count = 0;
return true;
+ case LVN_DELETEITEM:
+ // Delete the associated internal data. Notice that this can be
+ // done only after the event has been handled as the data could be
+ // accessed during the handling of the event.
+ if ( wxMSWListItemData *data = MSWGetItemData(event.m_itemIndex) )
+ {
+ const unsigned count = m_internalData.size();
+ for ( unsigned n = 0; n < count; n++ )
+ {
+ if ( m_internalData[n] == data )
+ {
+ m_internalData.erase(m_internalData.begin() + n);
+ wxDELETE(data);
+ break;
+ }
+ }
+
+ wxASSERT_MSG( !data, "invalid internal data pointer?" );
+ }
+ break;
+
case LVN_ENDLABELEDITA:
case LVN_ENDLABELEDITW:
// logic here is inverted compared to all the other messages