]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/listctrl.cpp
don't compile in wx hash code unless we really use it (#9532:12)
[wxWidgets.git] / src / msw / listctrl.cpp
index a32c13669629cdab8e934e580dbff383f8b0ad93..239b9b20b37b4a49fa2941066a0fcba396e3f816 100644 (file)
@@ -353,7 +353,11 @@ void wxListCtrl::MSWSetExListStyles()
         ::SendMessage
         (
             GetHwnd(), LVM_SETEXTENDEDLISTVIEWSTYLE, 0,
+            // LVS_EX_LABELTIP shouldn't be used under Windows CE where it's
+            // not defined in the SDK headers
+#ifdef LVS_EX_LABELTIP
             LVS_EX_LABELTIP |
+#endif
             LVS_EX_FULLROWSELECT |
             LVS_EX_SUBITEMIMAGES |
             // normally this should be governed by a style as it's probably not
@@ -484,10 +488,8 @@ void wxListCtrl::FreeAllInternalData()
     }
 }
 
-wxListCtrl::~wxListCtrl()
+void wxListCtrl::DeleteEditControl()
 {
-    FreeAllInternalData();
-
     if ( m_textCtrl )
     {
         m_textCtrl->UnsubclassWin();
@@ -495,6 +497,13 @@ wxListCtrl::~wxListCtrl()
         delete m_textCtrl;
         m_textCtrl = NULL;
     }
+}
+
+wxListCtrl::~wxListCtrl()
+{
+    FreeAllInternalData();
+
+    DeleteEditControl();
 
     if (m_ownsImageListNormal)
         delete m_imageListNormal;
@@ -537,7 +546,7 @@ void wxListCtrl::SetWindowStyleFlag(long flag)
 {
     if ( flag != m_windowStyle )
     {
-        m_windowStyle = flag;
+        wxControl::SetWindowStyleFlag(flag);
 
         UpdateStyle();
 
@@ -757,6 +766,25 @@ int wxListCtrl::GetCountPerPage() const
 // Gets the edit control for editing labels.
 wxTextCtrl* wxListCtrl::GetEditControl() const
 {
+    // first check corresponds to the case when the label editing was started
+    // by user and hence m_textCtrl wasn't created by EditLabel() at all, while
+    // the second case corresponds to us being called from inside EditLabel()
+    // (e.g. from a user wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT handler): in this
+    // case EditLabel() did create the control but it didn't have an HWND to
+    // initialize it with yet
+    if ( !m_textCtrl || !m_textCtrl->GetHWND() )
+    {
+        HWND hwndEdit = ListView_GetEditControl(GetHwnd());
+        if ( hwndEdit )
+        {
+            wxListCtrl * const self = wx_const_cast(wxListCtrl *, this);
+
+            if ( !m_textCtrl )
+                self->m_textCtrl = new wxTextCtrl;
+            self->InitEditControl((WXHWND)hwndEdit);
+        }
+    }
+
     return m_textCtrl;
 }
 
@@ -1446,38 +1474,49 @@ void wxListCtrl::ClearAll()
         DeleteAllColumns();
 }
 
+void wxListCtrl::InitEditControl(WXHWND hWnd)
+{
+    m_textCtrl->SetHWND(hWnd);
+    m_textCtrl->SubclassWin(hWnd);
+    m_textCtrl->SetParent(this);
+
+    // we must disallow TABbing away from the control while the edit contol 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)
+    m_textCtrl->SetWindowStyle(m_textCtrl->GetWindowStyle() | wxTE_PROCESS_TAB);
+}
+
 wxTextCtrl* wxListCtrl::EditLabel(long item, wxClassInfo* textControlClass)
 {
-    wxASSERT( (textControlClass->IsKindOf(CLASSINFO(wxTextCtrl))) );
+    wxCHECK_MSG( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)), NULL,
+                  "control used for label editing must be a wxTextCtrl" );
 
     // ListView_EditLabel requires that the list has focus.
     SetFocus();
 
+    // create m_textCtrl here before calling ListView_EditLabel() because it
+    // generates wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT event from inside it and
+    // the user handler for it can call GetEditControl() resulting in an on
+    // demand creation of a stock wxTextCtrl instead of the control of a
+    // (possibly) custom wxClassInfo
+    DeleteEditControl();
+    m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject();
+
     WXHWND hWnd = (WXHWND) ListView_EditLabel(GetHwnd(), item);
     if ( !hWnd )
     {
         // failed to start editing
-        return NULL;
-    }
-
-    // [re]create the text control wrapping the HWND we got
-    if ( m_textCtrl )
-    {
-        m_textCtrl->UnsubclassWin();
-        m_textCtrl->SetHWND(0);
         delete m_textCtrl;
-    }
+        m_textCtrl = NULL;
 
-    m_textCtrl = (wxTextCtrl *)textControlClass->CreateObject();
-    m_textCtrl->SetHWND(hWnd);
-    m_textCtrl->SubclassWin(hWnd);
-    m_textCtrl->SetParent(this);
+        return NULL;
+    }
 
-    // we must disallow TABbing away from the control while the edit contol 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)
-    m_textCtrl->SetWindowStyle(m_textCtrl->GetWindowStyle() | wxTE_PROCESS_TAB);
+    // if GetEditControl() hasn't been called, we need to initialize the edit
+    // control ourselves
+    if ( !m_textCtrl->GetHWND() )
+        InitEditControl(hWnd);
 
     return m_textCtrl;
 }
@@ -1863,15 +1902,12 @@ bool wxListCtrl::MSWCommand(WXUINT cmd, WXWORD id_)
 // utility used by wxListCtrl::MSWOnNotify and by wxDataViewHeaderWindowMSW::MSWOnNotify
 int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick)
 {
-    wxASSERT(nmhdr && ptClick);
-
-    // find the column clicked: we have to search for it
-    // ourselves as the notification message doesn't provide
-    // this info
+    // find the column clicked: we have to search for it ourselves as the
+    // notification message doesn't provide this info
 
     // where did the click occur?
 #if defined(__WXWINCE__) && !defined(__HANDHELDPC__) && _WIN32_WCE < 400
-    if (nmhdr->code == GN_CONTEXTMENU)
+    if ( nmhdr->code == GN_CONTEXTMENU )
     {
         *ptClick = ((NMRGINFO*)nmhdr)->ptAction;
     }
@@ -1882,19 +1918,27 @@ int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick)
         wxLogLastError(_T("GetCursorPos"));
     }
 
-    if ( !::ScreenToClient(nmhdr->hwndFrom, ptClick) )
+    // we need to use listctrl coordinates for the event point so this is what
+    // we return in ptClick, but for comparison with Header_GetItemRect()
+    // result below we need to use header window coordinates
+    POINT ptClickHeader = *ptClick;
+    if ( !::ScreenToClient(nmhdr->hwndFrom, &ptClickHeader) )
     {
-        wxLogLastError(_T("ScreenToClient(header)"));
+        wxLogLastError(_T("ScreenToClient(listctrl header)"));
     }
 
-    int colCount = Header_GetItemCount(nmhdr->hwndFrom);
+    if ( !::ScreenToClient(::GetParent(nmhdr->hwndFrom), ptClick) )
+    {
+        wxLogLastError(_T("ScreenToClient(listctrl)"));
+    }
 
-    RECT rect;
+    const int colCount = Header_GetItemCount(nmhdr->hwndFrom);
     for ( int col = 0; col < colCount; col++ )
     {
+        RECT rect;
         if ( Header_GetItemRect(nmhdr->hwndFrom, col, &rect) )
         {
-            if ( ::PtInRect(&rect, *ptClick) )
+            if ( ::PtInRect(&rect, ptClickHeader) )
             {
                 return col;
             }
@@ -2084,16 +2128,9 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
                     const LV_ITEM& lvi = (LV_ITEM)item;
                     if ( !lvi.pszText || lvi.iItem == -1 )
                     {
-                        // 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;
-                        }
+                        // EDIT control will be deleted by the list control
+                        // itself so prevent us from deleting it as well
+                        DeleteEditControl();
 
                         event.SetEditCanceled(true);
                     }
@@ -2466,16 +2503,9 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
             // logic here is inverted compared to all the other messages
             *result = event.IsAllowed();
 
-            // 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;
-            }
+            // EDIT control will be deleted by the list control itself so
+            // prevent us from deleting it as well
+            DeleteEditControl();
 
             return true;
     }
@@ -2792,7 +2822,7 @@ void wxListCtrl::OnPaint(wxPaintEvent& event)
     // Reset the device origin since it may have been set
     dc.SetDeviceOrigin(0, 0);
 
-    wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT), 1, wxSOLID);
+    wxPen pen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT));
     dc.SetPen(pen);
     dc.SetBrush(* wxTRANSPARENT_BRUSH);