]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/headerctrl.cpp
use a slightly less ugly way to conditionally suppress unused parameter warnings
[wxWidgets.git] / src / msw / headerctrl.cpp
index 8df0e8286cc0dac891205cfcb858bfd3d103a667..d6ad5ccddaad6e63e8d7e36efe1fbf91b81c7be7 100644 (file)
@@ -151,16 +151,22 @@ void wxHeaderCtrl::DoSetCount(unsigned int count)
     // and add the new ones
     for ( n = 0; n < count; n++ )
     {
-        DoSetOrInsertItem(Insert, n);
+        DoInsertItem(n);
     }
 }
 
 void wxHeaderCtrl::DoUpdate(unsigned int idx)
 {
-    DoSetOrInsertItem(Set, idx);
+    // the native control does provide Header_SetItem() but it's inconvenient
+    // to use it because it sends HDN_ITEMCHANGING messages and we'd have to
+    // arrange not to block setting the width from there and the logic would be
+    // more complicated as we'd have to reset the old values as well as setting
+    // the new ones -- so instead just recreate the column
+    Header_DeleteItem(GetHwnd(), idx);
+    DoInsertItem(idx);
 }
 
-void wxHeaderCtrl::DoSetOrInsertItem(Operation oper, unsigned int idx)
+void wxHeaderCtrl::DoInsertItem(unsigned int idx)
 {
     const wxHeaderColumnBase& col = GetColumn(idx);
 
@@ -168,41 +174,44 @@ void wxHeaderCtrl::DoSetOrInsertItem(Operation oper, unsigned int idx)
 
     // notice that we need to store the string we use the pointer to until we
     // pass it to the control
-    wxWxCharBuffer buf;
-    if ( !col.GetTitle().empty() )
-    {
-        hdi.mask |= HDI_TEXT;
-
-        buf = col.GetTitle().wx_str();
-        hdi.pszText = buf.data();
-        hdi.cchTextMax = wxStrlen(buf);
-    }
+    hdi.mask |= HDI_TEXT;
+    wxWxCharBuffer buf = col.GetTitle().wx_str();
+    hdi.pszText = buf.data();
+    hdi.cchTextMax = wxStrlen(buf);
 
     const wxBitmap bmp = col.GetBitmap();
     if ( bmp.IsOk() )
     {
-        const int bmpWidth = bmp.GetWidth(),
-                  bmpHeight = bmp.GetHeight();
+        hdi.mask |= HDI_IMAGE;
 
-        if ( !m_imageList )
+        if ( bmp.IsOk() )
         {
-            m_imageList = new wxImageList(bmpWidth, bmpHeight);
-            Header_SetImageList(GetHwnd(), GetHimagelistOf(m_imageList));
+            const int bmpWidth = bmp.GetWidth(),
+                      bmpHeight = bmp.GetHeight();
+
+            if ( !m_imageList )
+            {
+                m_imageList = new wxImageList(bmpWidth, bmpHeight);
+                Header_SetImageList(GetHwnd(), GetHimagelistOf(m_imageList));
+            }
+            else // already have an image list
+            {
+                // check that all bitmaps we use have the same size
+                int imageWidth,
+                    imageHeight;
+                m_imageList->GetSize(0, imageWidth, imageHeight);
+
+                wxASSERT_MSG( imageWidth == bmpWidth && imageHeight == bmpHeight,
+                              "all column bitmaps must have the same size" );
+            }
+
+            m_imageList->Add(bmp);
+            hdi.iImage = m_imageList->GetImageCount() - 1;
         }
-        else // already have an image list
+        else // no bitmap but we still need to update the item
         {
-            // check that all bitmaps we use have the same size
-            int imageWidth,
-                imageHeight;
-            m_imageList->GetSize(0, imageWidth, imageHeight);
-
-            wxASSERT_MSG( imageWidth == bmpWidth && imageHeight == bmpHeight,
-                          "all column bitmaps must have the same size" );
+            hdi.iImage = I_IMAGENONE;
         }
-
-        m_imageList->Add(bmp);
-        hdi.mask |= HDI_IMAGE;
-        hdi.iImage = m_imageList->GetImageCount() - 1;
     }
 
     if ( col.GetAlignment() != wxALIGN_NOT )
@@ -240,19 +249,9 @@ void wxHeaderCtrl::DoSetOrInsertItem(Operation oper, unsigned int idx)
         hdi.cxy = col.IsHidden() ? 0 : col.GetWidth();
     }
 
-    const LRESULT rc = ::SendMessage(GetHwnd(),
-                                     oper == Set ? HDM_SETITEM : HDM_INSERTITEM,
-                                     idx,
-                                     (LPARAM)&hdi);
-    if ( oper == Set )
+    if ( ::SendMessage(GetHwnd(), HDM_INSERTITEM, idx, (LPARAM)&hdi) == -1 )
     {
-        if ( !rc )
-            wxLogLastError(_T("Header_SetItem()"));
-    }
-    else // Insert
-    {
-        if ( rc == -1 )
-            wxLogLastError(_T("Header_InsertItem()"));
+        wxLogLastError(_T("Header_InsertItem()"));
     }
 }
 
@@ -260,16 +259,7 @@ void wxHeaderCtrl::DoSetOrInsertItem(Operation oper, unsigned int idx)
 // wxHeaderCtrl events
 // ----------------------------------------------------------------------------
 
-bool wxHeaderCtrl::SendEvent(wxEventType evtType, unsigned int idx)
-{
-    wxHeaderCtrlEvent event(evtType, GetId());
-    event.SetEventObject(this);
-    event.SetColumn(idx);
-
-    return GetEventHandler()->ProcessEvent(event);
-}
-
-bool wxHeaderCtrl::SendClickEvent(bool dblclk, int button, unsigned int idx)
+wxEventType wxHeaderCtrl::GetClickEventType(bool dblclk, int button)
 {
     wxEventType evtType;
     switch ( button )
@@ -291,23 +281,29 @@ bool wxHeaderCtrl::SendClickEvent(bool dblclk, int button, unsigned int idx)
 
         default:
             wxFAIL_MSG( wxS("unexpected event type") );
-            return false;
+            evtType = wxEVT_NULL;
     }
 
-    return SendEvent(evtType, idx);
+    return evtType;
 }
 
 bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
 {
     NMHEADER * const nmhdr = (NMHEADER *)lParam;
 
-    const int idx = nmhdr->iItem;
-    switch ( const UINT code = nmhdr->hdr.code )
+    wxEventType evtType = wxEVT_NULL;
+    int idx = nmhdr->iItem;
+    int width = 0;
+    bool cancelled = false;
+    const UINT code = nmhdr->hdr.code;
+    switch ( code )
     {
+        // click events
+        // ------------
+
         case HDN_ITEMCLICK:
         case HDN_ITEMDBLCLICK:
-            if ( SendClickEvent(code == HDN_ITEMDBLCLICK, nmhdr->iButton, idx) )
-                return true;
+            evtType = GetClickEventType(code == HDN_ITEMDBLCLICK, nmhdr->iButton);
             break;
 
             // although we should get the notifications about the right clicks
@@ -317,20 +313,99 @@ bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
         case NM_RDBLCLK:
             {
                 POINT pt;
-                const int col = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
-                if ( col != wxNOT_FOUND )
-                {
-                    if ( SendClickEvent(code == NM_RDBLCLK, 1, col) )
-                        return true;
-                }
+                idx = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
+                if ( idx != wxNOT_FOUND )
+                    evtType = GetClickEventType(code == NM_RDBLCLK, 1);
                 //else: ignore clicks outside any column
             }
             break;
 
         case HDN_DIVIDERDBLCLICK:
-            if ( SendEvent(wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK, idx) )
+            evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
+            break;
+
+
+        // column resizing events
+        // ----------------------
+
+        // see comments in wxListCtrl::MSWOnNotify() for why we catch both
+        // ASCII and Unicode versions of this message
+        case HDN_BEGINTRACKA:
+        case HDN_BEGINTRACKW:
+            // non-resizeable columns can't be resized no matter what, don't
+            // even generate any events for them
+            if ( !GetColumn(idx).IsResizeable() )
+            {
+                *result = TRUE;
+
                 return true;
+            }
+
+            evtType = wxEVT_COMMAND_HEADER_BEGIN_RESIZE;
+            // fall through
+
+        case HDN_TRACKA:
+        case HDN_TRACKW:
+            if ( evtType == wxEVT_NULL )
+                evtType = wxEVT_COMMAND_HEADER_RESIZING;
+            // fall through
+
+        case HDN_ENDTRACKA:
+        case HDN_ENDTRACKW:
+            width = nmhdr->pitem->cxy;
+
+            if ( evtType == wxEVT_NULL )
+            {
+                evtType = wxEVT_COMMAND_HEADER_END_RESIZE;
+
+                // don't generate events with invalid width
+                const int minWidth = GetColumn(idx).GetMinWidth();
+                if ( width < minWidth )
+                    width = minWidth;
+            }
+            break;
+
+        case HDN_ITEMCHANGING:
+            if ( nmhdr->pitem && (nmhdr->pitem->mask & HDI_WIDTH) )
+            {
+                // prevent the column from being shrunk beneath its min width
+                if ( nmhdr->pitem->cxy < GetColumn(idx).GetMinWidth() )
+                {
+                    *result = TRUE;
+
+                    return true;
+                }
+            }
             break;
+
+        case NM_RELEASEDCAPTURE:
+            cancelled = true;
+            break;
+    }
+
+
+    // do generate the corresponding wx event
+    if ( evtType != wxEVT_NULL )
+    {
+        wxHeaderCtrlEvent event(evtType, GetId());
+        event.SetEventObject(this);
+        event.SetColumn(idx);
+        event.SetWidth(width);
+        if ( cancelled )
+            event.SetCancelled();
+
+        if ( GetEventHandler()->ProcessEvent(event) )
+        {
+            if ( !event.IsAllowed() )
+            {
+                // all of HDN_BEGIN{DRAG,TRACK}, HDN_TRACK and HDN_ITEMCHANGING
+                // interpret TRUE return value as meaning to stop the control
+                // default handling of the message
+                *result = TRUE;
+            }
+
+            return true;
+        }
     }
 
     return wxHeaderCtrlBase::MSWOnNotify(idCtrl, lParam, result);