#include "wx/intl.h"
#include "wx/log.h"
#include "wx/settings.h"
+ #include "wx/stopwatch.h"
#include "wx/dcclient.h"
#include "wx/textctrl.h"
#endif
BEGIN_EVENT_TABLE(wxListCtrl, wxControl)
EVT_PAINT(wxListCtrl::OnPaint)
+ EVT_CHAR_HOOK(wxListCtrl::OnCharHook)
END_EVENT_TABLE()
// ============================================================================
m_textCtrl->SubclassWin(hWnd);
m_textCtrl->SetParent(this);
- // we must disallow TABbing away from the control while the edit contol is
+ // we must disallow TABbing away from the control while the edit control is
// shown because this leaves it in some strange state (just try removing
// this line and then pressing TAB while editing an item in listctrl
// inside a panel)
if ( !hwnd )
return false;
- // 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);
- }
+ // Newer versions of Windows have a special ListView_CancelEditLabel()
+ // message for cancelling editing but it, rather counter-intuitively, keeps
+ // the last text entered in the dialog while cancelling as we do it below
+ // restores the original text which is the more expected behaviour.
+
+ // 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;
}
wxListItem info;
info.m_image = imageIndex;
info.m_text = label;
- info.m_mask = wxLIST_MASK_IMAGE | wxLIST_MASK_TEXT;
+ info.m_mask = wxLIST_MASK_TEXT;
+ if (imageIndex > -1)
+ info.m_mask |= wxLIST_MASK_IMAGE;
info.m_itemId = index;
return InsertItem(info);
}
wxMSWListItemData *data1 = (wxMSWListItemData *) lParam1;
wxMSWListItemData *data2 = (wxMSWListItemData *) lParam2;
- long d1 = (data1 == NULL ? 0 : data1->lParam);
- long d2 = (data2 == NULL ? 0 : data2->lParam);
+ wxIntPtr d1 = (data1 == NULL ? 0 : data1->lParam);
+ wxIntPtr d2 = (data2 == NULL ? 0 : data2->lParam);
return internalData->user_fn(d1, d2, internalData->data);
}
else
#endif //__WXWINCE__
- if ( !::GetCursorPos(ptClick) )
{
- wxLogLastError(wxT("GetCursorPos"));
+ wxGetCursorPosMSW(ptClick);
}
// we need to use listctrl coordinates for the event point so this is what
else
#endif //__WXWINCE__
{
- ::GetCursorPos(&(lvhti.pt));
+ wxGetCursorPosMSW(&(lvhti.pt));
}
::ScreenToClient(GetHwnd(), &lvhti.pt);
#ifdef HAVE_NMLVFINDITEM
case LVN_ODFINDITEM:
- // this message is only used with the virtual list control but
- // even there we don't want to always use it: in a control with
- // sufficiently big number of items (defined as > 1000 here),
- // accidentally pressing a key could result in hanging an
- // application waiting while it performs linear search
- if ( IsVirtual() && GetItemCount() <= 1000 )
+ // Find an item in a (necessarily virtual) list control.
+ if ( IsVirtual() )
{
NMLVFINDITEM* pFindInfo = (NMLVFINDITEM*)lParam;
startPos = 0;
}
+ // Linear search in a control with a lot of items can take
+ // a long time so we limit the total time of the search to
+ // ensure that the program doesn't appear to hang.
+#if wxUSE_STOPWATCH
+ wxStopWatch sw;
+#endif // wxUSE_STOPWATCH
for ( int currentPos = startPos; ; )
{
// does this item begin with searchstr?
// item by default in this case.
return true;
}
+
+#if wxUSE_STOPWATCH
+ // Check the time elapsed only every thousand
+ // iterations for performance reasons: if we did it
+ // more often calling wxStopWatch::Time() could take
+ // noticeable time on its own.
+ if ( !((currentPos - startPos)%1000) )
+ {
+ // We use half a second to limit the search time
+ // which is about as long as we can take without
+ // annoying the user.
+ if ( sw.Time() > 500 )
+ {
+ // As above, return true to prevent the control
+ // from selecting the first item by default.
+ return true;
+ }
+ }
+#endif // wxUSE_STOPWATCH
+
}
SetItemState(*result,
}
}
+void wxListCtrl::OnCharHook(wxKeyEvent& event)
+{
+ if ( GetEditControl() )
+ {
+ // We need to ensure that Escape is not stolen from the in-place editor
+ // by the containing dialog.
+ //
+ // Notice that we don't have to care about Enter key here as we return
+ // false from MSWShouldPreProcessMessage() for it.
+ if ( event.GetKeyCode() == WXK_ESCAPE )
+ {
+ EndEditLabel(true /* cancel */);
+
+ // Don't call Skip() below.
+ return;
+ }
+ }
+
+ event.Skip();
+}
+
WXLRESULT
wxListCtrl::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
{