X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/bfc8138f91d8fd51b14e0329997c92b9f088de20..b5df4fc722412fe5f6764c490925b26293c5f662:/src/msw/listctrl.cpp?ds=sidebyside diff --git a/src/msw/listctrl.cpp b/src/msw/listctrl.cpp index 56c4430c64..3e9b5966cb 100644 --- a/src/msw/listctrl.cpp +++ b/src/msw/listctrl.cpp @@ -45,6 +45,14 @@ #include "wx/msw/private.h" +#if defined(__WXWINCE__) + #include + #include + #if _WIN32_WCE < 400 + #include + #endif +#endif + // include "properly" #include "wx/msw/wrapcctl.h" @@ -73,60 +81,77 @@ static void wxConvertToMSWListCol(int col, const wxListItem& item, // ---------------------------------------------------------------------------- // We have to handle both fooW and fooA notifications in several cases -// because of broken commctl.dll and/or unicows.dll. This class is used to +// because of broken comctl32.dll and/or unicows.dll. This class is used to // convert LV_ITEMA and LV_ITEMW to LV_ITEM (which is either LV_ITEMA or // LV_ITEMW depending on wxUSE_UNICODE setting), so that it can be processed // by wxConvertToMSWListItem(). +#if wxUSE_UNICODE + #define LV_ITEM_NATIVE LV_ITEMW + #define LV_ITEM_OTHER LV_ITEMA + + #define LV_CONV_TO_WX cMB2WX + #define LV_CONV_BUF wxMB2WXbuf +#else // ANSI + #define LV_ITEM_NATIVE LV_ITEMA + #define LV_ITEM_OTHER LV_ITEMW + + #define LV_CONV_TO_WX cWC2WX + #define LV_CONV_BUF wxWC2WXbuf +#endif // Unicode/ANSI + class wxLV_ITEM { public: - ~wxLV_ITEM() { delete m_buf; } - operator LV_ITEM&() const { return *m_item; } + // default ctor, use Init() later + wxLV_ITEM() { m_buf = NULL; m_pItem = NULL; } -#if wxUSE_UNICODE - wxLV_ITEM(LV_ITEMW &item) : m_buf(NULL), m_item(&item) {} - wxLV_ITEM(LV_ITEMA &item) + // init without conversion + void Init(LV_ITEM_NATIVE& item) { - m_item = new LV_ITEM((LV_ITEM&)item); - if ( (item.mask & LVIF_TEXT) && item.pszText ) - { - m_buf = new wxMB2WXbuf(wxConvLocal.cMB2WX(item.pszText)); - m_item->pszText = (wxChar*)m_buf->data(); - } - else - m_buf = NULL; + wxASSERT_MSG( !m_pItem, _T("Init() called twice?") ); + + m_pItem = &item; } -private: - wxMB2WXbuf *m_buf; -#else // !wxUSE_UNICODE - wxLV_ITEM(LV_ITEMW &item) + // init with conversion + void Init(LV_ITEM_OTHER& item) { - m_item = new LV_ITEM((LV_ITEM&)item); + // avoid unnecessary dynamic memory allocation, jjust make m_pItem + // point to our own m_item + + // memcpy() can't work if the struct sizes are different + wxCOMPILE_TIME_ASSERT( sizeof(LV_ITEM_OTHER) == sizeof(LV_ITEM_NATIVE), + CodeCantWorkIfDiffSizes); - // the code below doesn't compile without wxUSE_WCHAR_T and as I don't - // know if it's useful to have it at all (do we ever get Unicode - // notifications in ANSI mode? I don't think so...) I'm not going to - // write alternative implementation right now - // - // but if it is indeed used, we should simply directly use - // ::WideCharToMultiByte() here -#if wxUSE_WCHAR_T + memcpy(&m_item, &item, sizeof(LV_ITEM_NATIVE)); + + // convert text from ANSI to Unicod if necessary if ( (item.mask & LVIF_TEXT) && item.pszText ) { - m_buf = new wxWC2WXbuf(wxConvLocal.cWC2WX(item.pszText)); - m_item->pszText = (wxChar*)m_buf->data(); + m_buf = new LV_CONV_BUF(wxConvLocal.LV_CONV_TO_WX(item.pszText)); + m_item.pszText = (wxChar *)m_buf->data(); } - else -#endif // wxUSE_WCHAR_T - m_buf = NULL; } - wxLV_ITEM(LV_ITEMA &item) : m_buf(NULL), m_item(&item) {} + + // ctor without conversion + wxLV_ITEM(LV_ITEM_NATIVE& item) : m_buf(NULL), m_pItem(&item) { } + + // ctor with conversion + wxLV_ITEM(LV_ITEM_OTHER& item) : m_buf(NULL) + { + Init(item); + } + + ~wxLV_ITEM() { delete m_buf; } + + // conversion to the real LV_ITEM + operator LV_ITEM_NATIVE&() const { return *m_pItem; } + private: - wxWC2WXbuf *m_buf; -#endif // wxUSE_UNICODE/!wxUSE_UNICODE + LV_CONV_BUF *m_buf; - LV_ITEM *m_item; + LV_ITEM_NATIVE *m_pItem; + LV_ITEM_NATIVE m_item; DECLARE_NO_COPY_CLASS(wxLV_ITEM) }; @@ -232,14 +257,14 @@ wxBEGIN_FLAGS( wxListCtrlStyle ) wxFLAGS_MEMBER(wxDOUBLE_BORDER) wxFLAGS_MEMBER(wxRAISED_BORDER) wxFLAGS_MEMBER(wxSTATIC_BORDER) - wxFLAGS_MEMBER(wxNO_BORDER) + wxFLAGS_MEMBER(wxBORDER) // standard window styles wxFLAGS_MEMBER(wxTAB_TRAVERSAL) wxFLAGS_MEMBER(wxCLIP_CHILDREN) wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW) wxFLAGS_MEMBER(wxWANTS_CHARS) - wxFLAGS_MEMBER(wxNO_FULL_REPAINT_ON_RESIZE) + wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE) wxFLAGS_MEMBER(wxALWAYS_SHOW_SB ) wxFLAGS_MEMBER(wxVSCROLL) wxFLAGS_MEMBER(wxHSCROLL) @@ -318,7 +343,7 @@ bool wxListCtrl::Create(wxWindow *parent, const wxPoint& pos, const wxSize& size, long style, - const wxValidator& validator, + const wxValidator& wxVALIDATOR_PARAM(validator), const wxString& name) { #if wxUSE_VALIDATORS @@ -1032,6 +1057,25 @@ bool wxListCtrl::SetItemData(long item, long data) return SetItem(info); } +wxRect wxListCtrl::GetViewRect() const +{ + wxASSERT_MSG( !HasFlag(wxLC_REPORT | wxLC_LIST), + _T("wxListCtrl::GetViewRect() only works in icon mode") ); + + RECT rc; + if ( !ListView_GetViewRect(GetHwnd(), &rc) ) + { + wxLogDebug(_T("ListView_GetViewRect() failed.")); + + wxZeroMemory(rc); + } + + wxRect rect; + wxCopyRECTToRect(rc, rect); + + return rect; +} + // Gets the item rectangle bool wxListCtrl::GetItemRect(long item, wxRect& rect, int code) const { @@ -1084,9 +1128,13 @@ int wxListCtrl::GetItemCount() const return m_count; } -// Retrieves the spacing between icons in pixels. -// If small is TRUE, gets the spacing for the small icon -// view, otherwise the large icon view. +wxSize wxListCtrl::GetItemSpacing() const +{ + const int spacing = ListView_GetItemSpacing(GetHwnd(), (BOOL)HasFlag(wxLC_SMALL_ICON)); + + return wxSize(LOWORD(spacing), HIWORD(spacing)); +} + int wxListCtrl::GetItemSpacing(bool isSmall) const { return ListView_GetItemSpacing(GetHwnd(), (BOOL) isSmall); @@ -1762,6 +1810,9 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) event.m_col = nmHDR->iItem; break; +#if defined(__WXWINCE__) && _WIN32_WCE < 400 + case GN_CONTEXTMENU: +#endif //__WXWINCE__ case NM_RCLICK: { eventType = wxEVT_COMMAND_LIST_COL_RIGHT_CLICK; @@ -1773,6 +1824,11 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) // where did the click occur? POINT ptClick; +#if defined(__WXWINCE__) && _WIN32_WCE < 400 + if(nmhdr->code == GN_CONTEXTMENU) { + ptClick = ((NMRGINFO*)nmhdr)->ptAction; + } else +#endif //__WXWINCE__ if ( !::GetCursorPos(&ptClick) ) { wxLogLastError(_T("GetCursorPos")); @@ -1873,55 +1929,43 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) break; // NB: we have to handle both *A and *W versions here because some - // versions of comctl32.dll send ANSI message to an Unicode app + // versions of comctl32.dll send ANSI messages even to the + // Unicode windows case LVN_BEGINLABELEDITA: - { - eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOA *)lParam)->item); - wxConvertFromMSWListItem(GetHwnd(), event.m_item, item); - event.m_itemIndex = event.m_item.m_itemId; - } - break; case LVN_BEGINLABELEDITW: { + wxLV_ITEM item; + if ( nmhdr->code == LVN_BEGINLABELEDITA ) + { + item.Init(((LV_DISPINFOA *)lParam)->item); + } + else // LVN_BEGINLABELEDITW + { + item.Init(((LV_DISPINFOW *)lParam)->item); + } + eventType = wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOW *)lParam)->item); wxConvertFromMSWListItem(GetHwnd(), event.m_item, item); event.m_itemIndex = event.m_item.m_itemId; } break; case LVN_ENDLABELEDITA: + case LVN_ENDLABELEDITW: { - eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOA *)lParam)->item); - wxConvertFromMSWListItem(NULL, event.m_item, item); - if ( ((LV_ITEM)item).pszText == NULL || - ((LV_ITEM)item).iItem == -1 ) + wxLV_ITEM item; + if ( nmhdr->code == LVN_ENDLABELEDITA ) { - // don't keep a stale wxTextCtrl around - if ( m_textCtrl ) - { - // EDIT control will be deleted by the list control itself so - // prevent us from deleting it as well - m_textCtrl->UnsubclassWin(); - m_textCtrl->SetHWND(0); - delete m_textCtrl; - m_textCtrl = NULL; - } - return FALSE; + item.Init(((LV_DISPINFOA *)lParam)->item); + } + else // LVN_ENDLABELEDITW + { + item.Init(((LV_DISPINFOW *)lParam)->item); } - event.m_itemIndex = event.m_item.m_itemId; - } - break; - case LVN_ENDLABELEDITW: - { - eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT; - wxLV_ITEM item(((LV_DISPINFOW *)lParam)->item); - wxConvertFromMSWListItem(NULL, event.m_item, item); - if ( ((LV_ITEM)item).pszText == NULL || - ((LV_ITEM)item).iItem == -1 ) + // was editing cancelled? + const LV_ITEM& lvi = (LV_ITEM)item; + if ( !lvi.pszText || lvi.iItem == -1 ) { // don't keep a stale wxTextCtrl around if ( m_textCtrl ) @@ -1933,9 +1977,12 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) delete m_textCtrl; m_textCtrl = NULL; } - return FALSE; + + event.SetEditCanceled(true); } + eventType = wxEVT_COMMAND_LIST_END_LABEL_EDIT; + wxConvertFromMSWListItem(NULL, event.m_item, item); event.m_itemIndex = event.m_item.m_itemId; } break; @@ -2097,6 +2144,9 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) event.m_item.m_data = GetItemData(iItem); break; +#if defined(__WXWINCE__) && _WIN32_WCE < 400 + case GN_CONTEXTMENU: +#endif //__WXWINCE__ case NM_RCLICK: // if the user processes it in wxEVT_COMMAND_RIGHT_CLICK(), // don't do anything else @@ -2109,6 +2159,11 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result) LV_HITTESTINFO lvhti; wxZeroMemory(lvhti); +#if defined(__WXWINCE__) && _WIN32_WCE < 400 + if(nmhdr->code == GN_CONTEXTMENU) { + lvhti.pt = ((NMRGINFO*)nmhdr)->ptAction; + } else +#endif //__WXWINCE__ ::GetCursorPos(&(lvhti.pt)); ::ScreenToClient(GetHwnd(),&(lvhti.pt)); if ( ListView_HitTest(GetHwnd(),&lvhti) != -1 ) @@ -2429,7 +2484,8 @@ void wxListCtrl::SetItemCount(long count) { wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") ); - if ( !::SendMessage(GetHwnd(), LVM_SETITEMCOUNT, (WPARAM)count, LVSICF_NOSCROLL) ) + if ( !::SendMessage(GetHwnd(), LVM_SETITEMCOUNT, (WPARAM)count, + LVSICF_NOSCROLL | LVSICF_NOINVALIDATEALL) ) { wxLogLastError(_T("ListView_SetItemCount")); }