#include "wx/msw/private.h"
-#if defined(__WXWINCE__)
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__)
#include <ole2.h>
#include <shellapi.h>
#if _WIN32_WCE < 400
// memcpy() can't work if the struct sizes are different
wxCOMPILE_TIME_ASSERT( sizeof(LV_ITEM_OTHER) == sizeof(LV_ITEM_NATIVE),
- CodeCantWorkIfDiffSizes);
+ CodeCantWorkIfDiffSizes);
memcpy(&m_item, &item, sizeof(LV_ITEM_NATIVE));
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS)
+#if WXWIN_COMPATIBILITY_2_4
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO)
+#endif
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED)
DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN)
wxFLAGS_MEMBER(wxBORDER_RAISED)
wxFLAGS_MEMBER(wxBORDER_STATIC)
wxFLAGS_MEMBER(wxBORDER_NONE)
-
+
// old style border flags
wxFLAGS_MEMBER(wxSIMPLE_BORDER)
wxFLAGS_MEMBER(wxSUNKEN_BORDER)
IMPLEMENT_DYNAMIC_CLASS_XTI(wxListCtrl, wxControl,"wx/listctrl.h")
wxBEGIN_PROPERTIES_TABLE(wxListCtrl)
- wxEVENT_PROPERTY( TextUpdated , wxEVT_COMMAND_TEXT_UPDATED , wxCommandEvent )
+ wxEVENT_PROPERTY( TextUpdated , wxEVT_COMMAND_TEXT_UPDATED , wxCommandEvent )
wxPROPERTY_FLAGS( WindowStyle , wxListCtrlStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
wxEND_PROPERTIES_TABLE()
wxBEGIN_HANDLERS_TABLE(wxListCtrl)
wxEND_HANDLERS_TABLE()
-wxCONSTRUCTOR_5( wxListCtrl , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
+wxCONSTRUCTOR_5( wxListCtrl , wxWindow* , Parent , wxWindowID , Id , wxPoint , Position , wxSize , Size , long , WindowStyle )
/*
TODO : Expose more information of a list's layout etc. via appropriate objects (à la NotebookPageInfo)
m_imageListNormal = NULL;
m_imageListSmall = NULL;
m_imageListState = NULL;
- m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = FALSE;
+ m_ownsImageListNormal = m_ownsImageListSmall = m_ownsImageListState = false;
m_colCount = 0;
m_count = 0;
- m_ignoreChangeMessages = FALSE;
+ m_ignoreChangeMessages = false;
m_textCtrl = NULL;
- m_AnyInternalData = FALSE;
- m_hasAnyAttr = FALSE;
+ m_AnyInternalData = false;
+ m_hasAnyAttr = false;
}
bool wxListCtrl::Create(wxWindow *parent,
const wxString& name)
{
if ( !CreateControl(parent, id, pos, size, style, validator, name) )
- return FALSE;
+ return false;
if ( !MSWCreateControl(WC_LISTVIEW, _T(""), pos, size) )
- return FALSE;
+ return false;
// explicitly say that we want to use Unicode because otherwise we get ANSI
// versions of _some_ messages (notably LVN_GETDISPINFOA) in MSLU build
0, LVS_EX_FULLROWSELECT);
}
- return TRUE;
+ return true;
}
WXDWORD wxListCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
// The new window view style
DWORD dwStyleNew = MSWGetStyle(m_windowStyle, NULL);
+ // some styles are not returned by MSWGetStyle()
+ if ( IsShown() )
+ dwStyleNew |= WS_VISIBLE;
+
// Get the current window style.
DWORD dwStyleOld = ::GetWindowLong(GetHwnd(), GWL_STYLE);
+ // we don't have wxVSCROLL style, but the list control may have it,
+ // don't change it then
+ dwStyleNew |= dwStyleOld & (WS_HSCROLL | WS_VSCROLL);
+
// Only set the window style if the view bits have changed.
if ( dwStyleOld != dwStyleNew )
{
if (m_AnyInternalData)
{
int n = GetItemCount();
- int i = 0;
- m_ignoreChangeMessages = TRUE;
- for (i = 0; i < n; i++)
+ m_ignoreChangeMessages = true;
+ for (int i = 0; i < n; i++)
wxDeleteInternalData(this, i);
- m_ignoreChangeMessages = FALSE;
+ m_ignoreChangeMessages = false;
+
+ m_AnyInternalData = false;
- m_AnyInternalData = FALSE;
+ m_count = 0;
}
}
flag = flag & ~wxLC_MASK_SORT;
}
- if ( flag & style )
- {
- if ( !add )
- flag -= style;
- }
+ if ( add )
+ flag |= style;
else
- {
- if ( add )
- {
- flag |= style;
- }
- }
-
- m_windowStyle = flag;
+ flag &= ~style;
- UpdateStyle();
+ SetWindowStyleFlag(flag);
}
// Set the whole window style
void wxListCtrl::SetWindowStyleFlag(long flag)
{
- m_windowStyle = flag;
+ if ( flag != m_windowStyle )
+ {
+ m_windowStyle = flag;
+
+ UpdateStyle();
- UpdateStyle();
+ Refresh();
+ }
}
// ----------------------------------------------------------------------------
bool wxListCtrl::SetForegroundColour(const wxColour& col)
{
if ( !wxWindow::SetForegroundColour(col) )
- return FALSE;
+ return false;
ListView_SetTextColor(GetHwnd(), wxColourToRGB(col));
- return TRUE;
+ return true;
}
// Sets the background colour
bool wxListCtrl::SetBackgroundColour(const wxColour& col)
{
if ( !wxWindow::SetBackgroundColour(col) )
- return FALSE;
+ return false;
// we set the same colour for both the "empty" background and the items
// background
ListView_SetBkColor(GetHwnd(), color);
ListView_SetTextBkColor(GetHwnd(), color);
- return TRUE;
+ return true;
}
// Gets information about this column
if (! data)
{
// need to set it
- m_AnyInternalData = TRUE;
+ m_AnyInternalData = true;
data = new wxListItemInternalData();
item.lParam = (LPARAM) data;
item.mask |= LVIF_PARAM;
{
wxLogDebug(_T("ListView_SetItem() failed"));
- return FALSE;
+ return false;
}
}
// check whether it has any custom attributes
if ( info.HasAttributes() )
{
- m_hasAnyAttr = TRUE;
+ m_hasAnyAttr = true;
// if the colour has changed, we must redraw the item
- updateNow = TRUE;
+ updateNow = true;
}
if ( updateNow )
RefreshItem(item.iItem);
}
- return TRUE;
+ return true;
}
long wxListCtrl::SetItem(long index, int col, const wxString& label, int imageId)
{
wxLogLastError(_T("ListView_SetItemState"));
- return FALSE;
+ return false;
}
if ( focusOld != -1 )
}
}
- return TRUE;
+ return true;
}
// Sets the item image
}
// Gets the item data
-long wxListCtrl::GetItemData(long item) const
+wxUIntPtr wxListCtrl::GetItemData(long item) const
{
wxListItem info;
flags = LVSIL_NORMAL;
if (m_ownsImageListNormal) delete m_imageListNormal;
m_imageListNormal = imageList;
- m_ownsImageListNormal = FALSE;
+ m_ownsImageListNormal = false;
}
else if ( which == wxIMAGE_LIST_SMALL )
{
flags = LVSIL_SMALL;
if (m_ownsImageListSmall) delete m_imageListSmall;
m_imageListSmall = imageList;
- m_ownsImageListSmall = FALSE;
+ m_ownsImageListSmall = false;
}
else if ( which == wxIMAGE_LIST_STATE )
{
flags = LVSIL_STATE;
if (m_ownsImageListState) delete m_imageListState;
m_imageListState = imageList;
- m_ownsImageListState = FALSE;
+ m_ownsImageListState = false;
}
ListView_SetImageList(GetHwnd(), (HIMAGELIST) imageList ? imageList->GetHIMAGELIST() : 0, flags);
}
{
SetImageList(imageList, which);
if ( which == wxIMAGE_LIST_NORMAL )
- m_ownsImageListNormal = TRUE;
+ m_ownsImageListNormal = true;
else if ( which == wxIMAGE_LIST_SMALL )
- m_ownsImageListSmall = TRUE;
+ m_ownsImageListSmall = true;
else if ( which == wxIMAGE_LIST_STATE )
- m_ownsImageListState = TRUE;
+ m_ownsImageListState = true;
}
// ----------------------------------------------------------------------------
if ( !ListView_DeleteItem(GetHwnd(), (int) item) )
{
wxLogLastError(_T("ListView_DeleteItem"));
- return FALSE;
+ return false;
}
m_count -= 1;
RefreshRect(rectWin);
}
- return TRUE;
+ return true;
}
// Deletes all items
bool wxListCtrl::DeleteAllItems()
{
- FreeAllInternalData();
return ListView_DeleteAllItems(GetHwnd()) != 0;
}
{
wxLogLastError(wxT("ListView_DeleteColumn"));
- return FALSE;
+ return false;
}
m_colCount--;
wxASSERT_MSG( m_colCount == 0, wxT("no columns should be left") );
- return TRUE;
+ return true;
}
// Deletes a column
{
wxFAIL_MSG( _T("not implemented") );
- return FALSE;
+ return false;
}
// Ensures this item is visible
bool wxListCtrl::EnsureVisible(long item)
{
- return ListView_EnsureVisible(GetHwnd(), (int) item, FALSE) != 0;
+ return ListView_EnsureVisible(GetHwnd(), (int) item, FALSE) != FALSE;
}
// Find an item whose label matches this string, starting from the item after 'start'
// NOTE : Lindsay Mathieson - 14-July-2002
// No longer use ListView_FindItem as the data attribute is now stored
// in a wxListItemInternalData structure refernced by the actual lParam
-long wxListCtrl::FindItem(long start, long data)
+long wxListCtrl::FindItem(long start, wxUIntPtr data)
{
long idx = start + 1;
long count = GetItemCount();
ListView_HitTest(GetHwnd(), & hitTestInfo);
flags = 0;
+
if ( hitTestInfo.flags & LVHT_ABOVE )
flags |= wxLIST_HITTEST_ABOVE;
if ( hitTestInfo.flags & LVHT_BELOW )
flags |= wxLIST_HITTEST_BELOW;
- if ( hitTestInfo.flags & LVHT_NOWHERE )
- flags |= wxLIST_HITTEST_NOWHERE;
- if ( hitTestInfo.flags & LVHT_ONITEMICON )
- flags |= wxLIST_HITTEST_ONITEMICON;
- if ( hitTestInfo.flags & LVHT_ONITEMLABEL )
- flags |= wxLIST_HITTEST_ONITEMLABEL;
- if ( hitTestInfo.flags & LVHT_ONITEMSTATEICON )
- flags |= wxLIST_HITTEST_ONITEMSTATEICON;
if ( hitTestInfo.flags & LVHT_TOLEFT )
flags |= wxLIST_HITTEST_TOLEFT;
if ( hitTestInfo.flags & LVHT_TORIGHT )
flags |= wxLIST_HITTEST_TORIGHT;
+ if ( hitTestInfo.flags & LVHT_NOWHERE )
+ flags |= wxLIST_HITTEST_NOWHERE;
+
+ // note a bug or at least a very strange feature of comtl32.dll (tested
+ // with version 4.0 under Win95 and 6.0 under Win 2003): if you click to
+ // the right of the item label, ListView_HitTest() returns a combination of
+ // LVHT_ONITEMICON, LVHT_ONITEMLABEL and LVHT_ONITEMSTATEICON -- filter out
+ // the bits which don't make sense
+ if ( hitTestInfo.flags & LVHT_ONITEMLABEL )
+ {
+ flags |= wxLIST_HITTEST_ONITEMLABEL;
+
+ // do not translate LVHT_ONITEMICON here, as per above
+ }
+ else
+ {
+ if ( hitTestInfo.flags & LVHT_ONITEMICON )
+ flags |= wxLIST_HITTEST_ONITEMICON;
+ if ( hitTestInfo.flags & LVHT_ONITEMSTATEICON )
+ flags |= wxLIST_HITTEST_ONITEMSTATEICON;
+ }
+
return (long) hitTestInfo.iItem;
}
bool needInternalData = ((info.m_mask & wxLIST_MASK_DATA) || info.HasAttributes());
if (needInternalData)
{
- m_AnyInternalData = TRUE;
+ m_AnyInternalData = true;
item.mask |= LVIF_PARAM;
// internal stucture that manages data
data->attr = new wxListItemAttr(*info.GetAttributes());
// and remember that we have some now...
- m_hasAnyAttr = TRUE;
+ m_hasAnyAttr = true;
}
};
{
wxLogDebug(_T("ListView_Scroll(%d, %d) failed"), dx, dy);
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
// Sort items.
{
wxLogDebug(_T("ListView_SortItems() failed"));
- return FALSE;
+ return false;
}
- return TRUE;
+ return true;
}
wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, id);
event.SetEventObject( this );
ProcessCommand(event);
- return TRUE;
+ return true;
}
else if (cmd == EN_KILLFOCUS)
{
wxCommandEvent event(wxEVT_KILL_FOCUS, id);
event.SetEventObject( this );
ProcessCommand(event);
- return TRUE;
+ return true;
}
else
- return FALSE;
+ return false;
}
bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
event.m_col = nmHDR->iItem;
break;
-#if defined(__WXWINCE__) && _WIN32_WCE < 400
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
case GN_CONTEXTMENU:
#endif //__WXWINCE__
case NM_RCLICK:
// where did the click occur?
POINT ptClick;
-#if defined(__WXWINCE__) && _WIN32_WCE < 400
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
if(nmhdr->code == GN_CONTEXTMENU) {
ptClick = ((NMRGINFO*)nmhdr)->ptAction;
- } else
+ } else
#endif //__WXWINCE__
if ( !::GetCursorPos(&ptClick) )
{
wxLogLastError(_T("GetCursorPos"));
}
- if ( !::ScreenToClient(hwndHdr, &ptClick) )
+ if ( !::ScreenToClient(GetHwnd(), &ptClick) )
{
wxLogLastError(_T("ScreenToClient(listctrl header)"));
}
break;
case HDN_GETDISPINFOW:
- {
- LPNMHDDISPINFOW info = (LPNMHDDISPINFOW) lParam;
- // This is a fix for a strange bug under XP.
- // Normally, info->iItem is a valid index, but
- // sometimes this is a silly (large) number
- // and when we return FALSE via wxControl::MSWOnNotify
- // to indicate that it hasn't yet been processed,
- // there's a GPF in Windows.
- // By returning TRUE here, we avoid further processing
- // of this strange message.
- if ( (unsigned)info->iItem >= (unsigned)GetColumnCount() )
- return TRUE;
- }
- // fall through
+ // letting Windows XP handle this message results in mysterious
+ // crashes in comctl32.dll seemingly because of bad message
+ // parameters
+ //
+ // I have no idea what is the real cause of the bug (which is,
+ // just to make things interesting, is impossible to reproduce
+ // reliably) but ignoring all these messages does fix it and
+ // doesn't seem to have any negative consequences
+ return true;
default:
return wxControl::MSWOnNotify(idCtrl, lParam, result);
if ( m_ignoreChangeMessages &&
( (nmLV->hdr.code == LVN_ITEMCHANGED) || (nmLV->hdr.code == LVN_ITEMCHANGING)))
{
- return TRUE;
+ return true;
}
break;
case LVN_DELETEALLITEMS:
- m_count = 0;
eventType = wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS;
event.m_itemIndex = -1;
break;
if (m_count == 0)
// this should be prevented by the post-processing code below,
// but "just in case"
- return FALSE;
+ return false;
eventType = wxEVT_COMMAND_LIST_DELETE_ITEM;
event.m_itemIndex = iItem;
wxDeleteInternalData(this, iItem);
break;
+#if WXWIN_COMPATIBILITY_2_4
case LVN_SETDISPINFO:
{
eventType = wxEVT_COMMAND_LIST_SET_INFO;
wxConvertFromMSWListItem(GetHwnd(), event.m_item, info->item);
}
break;
+#endif
case LVN_INSERTITEM:
eventType = wxEVT_COMMAND_LIST_INSERT_ITEM;
if ( eventType == wxEVT_NULL )
{
// not an interesting event for us
- return FALSE;
+ return false;
}
break;
// anything else
if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
{
- return TRUE;
+ return true;
}
// else translate it into wxEVT_COMMAND_LIST_ITEM_ACTIVATED event
if ( iItem == -1 )
{
// not on item
- return FALSE;
+ return false;
}
eventType = wxEVT_COMMAND_LIST_ITEM_ACTIVATED;
event.m_item.m_data = GetItemData(iItem);
break;
-#if defined(__WXWINCE__) && _WIN32_WCE < 400
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
case GN_CONTEXTMENU:
#endif //__WXWINCE__
case NM_RCLICK:
// don't do anything else
if ( wxControl::MSWOnNotify(idCtrl, lParam, result) )
{
- return TRUE;
+ return true;
}
// else translate it into wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK event
LV_HITTESTINFO lvhti;
wxZeroMemory(lvhti);
-#if defined(__WXWINCE__) && _WIN32_WCE < 400
+#if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
if(nmhdr->code == GN_CONTEXTMENU) {
lvhti.pt = ((NMRGINFO*)nmhdr)->ptAction;
- } else
+ } else
#endif //__WXWINCE__
::GetCursorPos(&(lvhti.pt));
::ScreenToClient(GetHwnd(),&(lvhti.pt));
case NM_CUSTOMDRAW:
*result = OnCustomDraw(lParam);
- return TRUE;
+ return true;
#endif // _WIN32_IE >= 0x300
case LVN_ODCACHEHINT:
// deleting an item, for items in invalid range -- filter
// this garbage out
if ( cacheHint->iFrom > cacheHint->iTo )
- return FALSE;
+ return false;
event.m_oldItemIndex = cacheHint->iFrom;
wxASSERT_MSG( !(lvi.mask & LVIF_STATE),
_T("we don't support state callbacks yet!") );
- return TRUE;
+ return true;
}
// fall through
else
{
// where did this one come from?
- return FALSE;
+ return false;
}
// process the event
switch ( nmhdr->code )
{
case LVN_DELETEALLITEMS:
- // always return TRUE to suppress all additional LVN_DELETEITEM
+ // always return true to suppress all additional LVN_DELETEITEM
// notifications - this makes deleting all items from a list ctrl
// much faster
*result = TRUE;
- return TRUE;
+
+ // also, we may free all user data now (couldn't do it before as
+ // the user should have access to it in OnDeleteAllItems() handler)
+ FreeAllInternalData();
+ return true;
case LVN_ENDLABELEDITA:
case LVN_ENDLABELEDITW:
m_textCtrl = NULL;
}
- return TRUE;
+ return true;
}
if ( processed )
wxSize clientSize = GetClientSize();
wxRect itemRect;
- int cy=0;
int itemCount = GetItemCount();
int i;
{
if (GetItemRect(i, itemRect))
{
- cy = itemRect.GetTop();
+ int cy = itemRect.GetTop();
if (i != 0) // Don't draw the first one
{
dc.DrawLine(0, cy, clientSize.x, cy);
int wxListCtrl::OnGetItemImage(long WXUNUSED(item)) const
{
- // same as above
- wxFAIL_MSG( _T("wxListCtrl::OnGetItemImage not supposed to be called") );
-
+ wxCHECK_MSG(!GetImageList(wxIMAGE_LIST_SMALL),
+ -1,
+ wxT("List control has an image list, OnGetItemImage should be overridden."));
return -1;
}
long oldMask = lvItem.mask;
- bool needText = FALSE;
+ bool needText = false;
if (hwndListCtrl != 0)
{
if ( lvItem.mask & LVIF_TEXT )
- needText = FALSE;
+ needText = false;
else
- needText = TRUE;
+ needText = true;
if ( needText )
{