+bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
+{
+ NMHEADER * const nmhdr = (NMHEADER *)lParam;
+
+ wxEventType evtType = wxEVT_NULL;
+ int width = 0;
+ int order = -1;
+ bool veto = false;
+ const UINT code = nmhdr->hdr.code;
+
+ // we don't have the index for all events, e.g. not for NM_RELEASEDCAPTURE
+ // so only access for header control events (and yes, the direction of
+ // comparisons with FIRST/LAST is correct even if it seems inverted)
+ int idx = code <= HDN_FIRST && code > HDN_LAST ? nmhdr->iItem : -1;
+ if ( idx != -1 )
+ {
+ // we also get bogus HDN_BEGINDRAG with -1 index so don't call
+ // MSWFromNativeIdx() unconditionally for nmhdr->iItem
+ idx = MSWFromNativeIdx(idx);
+ }
+
+ switch ( code )
+ {
+ // click events
+ // ------------
+
+ case HDN_ITEMCLICK:
+ case HDN_ITEMDBLCLICK:
+ evtType = GetClickEventType(code == HDN_ITEMDBLCLICK, nmhdr->iButton);
+
+ // We're not dragging any more.
+ m_colBeingDragged = -1;
+ break;
+
+ // although we should get the notifications about the right clicks
+ // via HDN_ITEM[DBL]CLICK too according to MSDN this simply doesn't
+ // happen in practice on any Windows system up to 2003
+ case NM_RCLICK:
+ case NM_RDBLCLK:
+ {
+ POINT pt;
+ idx = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
+ if ( idx != wxNOT_FOUND )
+ {
+ idx = MSWFromNativeIdx(idx);
+
+ // due to a bug in mingw32 headers NM_RDBLCLK is signed
+ // there so we need a cast to avoid warnings about signed/
+ // unsigned comparison
+ evtType = GetClickEventType(
+ code == static_cast<UINT>(NM_RDBLCLK), 1);
+ }
+ //else: ignore clicks outside any column
+ }
+ break;
+
+ case HDN_DIVIDERDBLCLICK:
+ 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-resizable columns can't be resized no matter what, don't
+ // even generate any events for them
+ if ( !GetColumn(idx).IsResizeable() )
+ {
+ veto = true;
+ break;
+ }
+
+ evtType = wxEVT_COMMAND_HEADER_BEGIN_RESIZE;
+ // 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;
+
+ // The control is not supposed to send HDN_TRACK when using
+ // HDS_FULLDRAG (which we do use) but apparently some versions of
+ // comctl32.dll still do it, see #13506, so catch both messages
+ // just in case we are dealing with one of these buggy versions.
+ case HDN_TRACK:
+ case HDN_ITEMCHANGING:
+ if ( nmhdr->pitem && (nmhdr->pitem->mask & HDI_WIDTH) )
+ {
+ // prevent the column from being shrunk beneath its min width
+ width = nmhdr->pitem->cxy;
+ if ( width < GetColumn(idx).GetMinWidth() )
+ {
+ // don't generate any events and prevent the change from
+ // happening
+ veto = true;
+ }
+ else // width is acceptable
+ {
+ // generate the resizing event from here as we don't seem
+ // to be getting HDN_TRACK events at all, at least with
+ // comctl32.dll v6
+ evtType = wxEVT_COMMAND_HEADER_RESIZING;
+ }
+ }
+ break;
+
+
+ // column reordering events
+ // ------------------------
+
+ case HDN_BEGINDRAG:
+ // Windows sometimes sends us events with invalid column indices
+ if ( nmhdr->iItem == -1 )
+ break;
+
+ // If we are dragging a column that is not draggable and the mouse
+ // is moved over a different column then we get the column number from
+ // the column under the mouse. This results in an unexpected behaviour
+ // if this column is draggable. To prevent this remember the column we
+ // are dragging for the complete drag and drop cycle.
+ if ( m_colBeingDragged == -1 )
+ {
+ m_colBeingDragged = idx;
+ }
+
+ // column must have the appropriate flag to be draggable
+ if ( !GetColumn(m_colBeingDragged).IsReorderable() )
+ {
+ veto = true;
+ break;
+ }
+
+ evtType = wxEVT_COMMAND_HEADER_BEGIN_REORDER;
+ break;
+
+ case HDN_ENDDRAG:
+ wxASSERT_MSG( nmhdr->pitem->mask & HDI_ORDER, "should have order" );
+ order = nmhdr->pitem->iOrder;
+
+ // we also get messages with invalid order when column reordering
+ // is cancelled (e.g. by pressing Esc)
+ if ( order == -1 )
+ break;
+
+ order = MSWFromNativeOrder(order);
+
+ evtType = wxEVT_COMMAND_HEADER_END_REORDER;
+
+ // We (successfully) ended dragging the column.
+ m_colBeingDragged = -1;
+ break;
+
+ case NM_RELEASEDCAPTURE:
+ evtType = wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED;
+
+ // Dragging the column was cancelled.
+ m_colBeingDragged = -1;
+ 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 ( order != -1 )
+ event.SetNewOrder(order);
+
+ const bool processed = GetEventHandler()->ProcessEvent(event);
+
+ if ( processed && !event.IsAllowed() )
+ veto = true;
+
+ if ( !veto )
+ {
+ // special post-processing for HDN_ENDDRAG: we need to update the
+ // internal column indices array if this is allowed to go ahead as
+ // the native control is going to reorder its columns now
+ if ( evtType == wxEVT_COMMAND_HEADER_END_REORDER )
+ MoveColumnInOrderArray(m_colIndices, idx, order);
+
+ if ( processed )
+ {
+ // skip default processing below
+ return true;
+ }
+ }
+ }
+
+ if ( veto )
+ {
+ // 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);
+}
+
+#endif // wxHAS_GENERIC_HEADERCTRL
+
+#endif // wxUSE_HEADERCTRL