]> git.saurik.com Git - wxWidgets.git/commitdiff
implement column resizing events in wxHeaderCtrl
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 8 Dec 2008 14:40:42 +0000 (14:40 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 8 Dec 2008 14:40:42 +0000 (14:40 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57190 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/generic/dataview.h
include/wx/generic/headerctrlg.h
include/wx/headerctrl.h
include/wx/msw/headerctrl.h
interface/wx/headerctrl.h
src/common/headerctrlcmn.cpp
src/generic/datavgen.cpp
src/generic/headerctrlg.cpp
src/msw/headerctrl.cpp

index 05ce149b3d2b7335b88dd94ed1cc6683a39ad661..953c2931427478ebdfa2376f7fc3eec5b47855f7 100644 (file)
@@ -359,11 +359,6 @@ private:
         m_sortAscending = true;
     }
 
-    // like SetWidth() but does not ask the header window of the
-    // wxDataViewCtrl to reflect the width-change.
-    void SetInternalWidth(int width);
-
-
     wxString m_title;
     int m_width,
         m_minWidth;
@@ -482,8 +477,11 @@ public:     // utility functions not part of the API
     // called by header window after reorder
     void ColumnMoved( wxDataViewColumn* col, unsigned int new_pos );
 
-    // updates the header window after a change in a column setting
-    void OnColumnChange();
+    // update the display after a change to an individual column
+    void OnColumnChange(unsigned int idx);
+
+    // update after a change to the number of columns
+    void OnColumnsCountChanged();
 
     wxWindow *GetMainWindow() { return (wxWindow*) m_clientArea; }
 
index 7c86e97730d2a9c50790789e56b5621bd6320a32..756d9c53cb1b957eb084f16367342a77b4d41e67 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "wx/event.h"
 #include "wx/vector.h"
+#include "wx/overlay.h"
 
 // ----------------------------------------------------------------------------
 // wxHeaderCtrl
@@ -64,6 +65,7 @@ private:
     // event handlers
     void OnPaint(wxPaintEvent& event);
     void OnMouse(wxMouseEvent& event);
+    void OnCaptureLost(wxMouseCaptureLostEvent& event);
 
     // return the horizontal start position of the given column
     int GetColStart(unsigned int idx) const;
@@ -84,6 +86,17 @@ private:
     // column 1 but close enough to the divider separating it from column 0)
     int FindColumnAtPos(int x, bool& onSeparator) const;
 
+    // end any drag operation currently in progress (resizing or reordering)
+    void EndDragging();
+
+    // and the resizing operation currently in progress and generate an event
+    // about it with its cancelled flag set if width is -1
+    void EndResizing(int width);
+
+    // update the current position of the resizing marker if xPhysical is a
+    // valid physical coordinate value or remove it entirely if it is -1
+    void UpdateResizingMarker(int xPhysical);
+
 
     // number of columns in the control currently
     unsigned int m_numColumns;
@@ -91,9 +104,16 @@ private:
     // index of the column under mouse or -1 if none
     unsigned int m_hover;
 
+    // the column being resized or -1 if there is no resizing operation in
+    // progress
+    unsigned int m_colBeingResized;
+
     // the horizontal scroll offset
     int m_scrollOffset;
 
+    // the overlay display used during the dragging operations
+    wxOverlay m_overlay;
+
 
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxHeaderCtrl)
index bf3a6632ba1837e6890ccf67bf2390a647fe8e48..51481efb67020999048219ac7c0f126d51d43869 100644 (file)
@@ -269,25 +269,45 @@ class WXDLLIMPEXP_CORE wxHeaderCtrlEvent : public wxNotifyEvent
 {
 public:
     wxHeaderCtrlEvent(wxEventType commandType = wxEVT_NULL, int winid = 0)
-        : wxNotifyEvent(commandType, winid)
+        : wxNotifyEvent(commandType, winid),
+          m_col(-1),
+          m_width(0),
+          m_cancelled(false)
     {
     }
 
     wxHeaderCtrlEvent(const wxHeaderCtrlEvent& event)
         : wxNotifyEvent(event),
-          m_col(event.m_col)
+          m_col(event.m_col),
+          m_width(event.m_width),
+          m_cancelled(event.m_cancelled)
     {
     }
 
+    // the column which this event pertains to: valid for all header events
     int GetColumn() const { return m_col; }
     void SetColumn(int col) { m_col = col; }
 
+    // the width of the column: valid for column resizing/dragging events only
+    int GetWidth() const { return m_width; }
+    void SetWidth(int width) { m_width = width; }
+
+    // was the drag operation cancelled or did it complete successfully?
+    bool IsCancelled() const { return m_cancelled; }
+    void SetCancelled() { m_cancelled = true; }
+
     virtual wxEvent *Clone() const { return new wxHeaderCtrlEvent(*this); }
 
 protected:
     // the column affected by the event
     int m_col;
 
+    // the current width for the dragging events
+    int m_width;
+
+    // was the drag operation cancelled?
+    bool m_cancelled;
+
 private:
     DECLARE_DYNAMIC_CLASS_NO_ASSIGN(wxHeaderCtrlEvent)
 };
@@ -303,6 +323,10 @@ extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK;
 
 extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
 
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_BEGIN_DRAG;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_DRAGGING;
+extern WXDLLIMPEXP_CORE const wxEventType wxEVT_COMMAND_HEADER_END_DRAG;
+
 typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
 
 #define wxHeaderCtrlEventHandler(func) \
@@ -322,4 +346,8 @@ typedef void (wxEvtHandler::*wxHeaderCtrlEventFunction)(wxHeaderCtrlEvent&);
 
 #define EVT_HEADER_SEPARATOR_DCLICK(id, fn) wx__DECLARE_HEADER_EVT(SEPARATOR_DCLICK, id, fn)
 
+#define EVT_HEADER_BEGIN_DRAG(id, fn) wx__DECLARE_HEADER_EVT(BEGIN_DRAG, id, fn)
+#define EVT_HEADER_DRAGGING(id, fn) wx__DECLARE_HEADER_EVT(DRAGGING, id, fn)
+#define EVT_HEADER_END_DRAG(id, fn) wx__DECLARE_HEADER_EVT(END_DRAG, id, fn)
+
 #endif // _WX_HEADERCTRL_H_
index 8a48ef0d56661d1d4ebc678a94ce9fc973a6dc8e..b0a3ae5c0b902fa39babfa23ebc92000b5f914e1 100644 (file)
@@ -71,13 +71,10 @@ private:
     enum Operation { Set, Insert };
     void DoSetOrInsertItem(Operation oper, unsigned int idx);
 
-    // send an event of the given type for the given column, return true if it
-    // was processed
-    bool SendEvent(wxEventType evtType, unsigned int idx);
-
-    // send a click or double click event (depending on dblclk value) for the
-    // click with the given button on the given item
-    bool SendClickEvent(bool dblclk, int button, unsigned int idx);
+    // get the event type corresponding to a click or double click event
+    // (depending on dblclk value) with the specified (using MSW convention)
+    // mouse button
+    wxEventType GetClickEventType(bool dblclk, int button);
 
 
     // the image list: initially NULL, created on demand
index cca13106383d3444e2e7a5f05de9780a12dc130c..8bb10c924d2043ab6d260a2cd433b72e7d3c1be7 100644 (file)
             (this action is commonly used to resize the column to fit its
             contents width and the control provides UpdateColumnWidthToFit() method
             to make implementing this easier).
+
+        @event{EVT_HEADER_BEGIN_DRAG(id, func)}
+            The user started to drag the column with the specified index (this
+            can only happen if wxHeaderColumn::IsResizeable() returned true for
+            this column). The event can be vetoed to prevent the control from
+            being resized, if it isn't, the dragging and end drag events will
+            be generated later.
+        @event{EVT_HEADER_DRAGGING(id, func)}
+            The user is dragging the column with the specified index and its
+            current width is wxHeaderCtrlEvent::GetWidth(). The event can be
+            vetoed to stop the dragging operation completely at any time.
+        @event{EVT_HEADER_END_DRAG(id, func)}
+            The user stopped dragging the column. If
+            wxHeaderCtrlEvent::IsCancelled() returns @true, nothing should
+            be done, otherwise the column should normally be resized to the
+            value of wxHeaderCtrlEvent::GetWidth().
     @endEventTable
 
     @library{wxcore}
@@ -389,6 +405,22 @@ class wxHeaderCtrlEvent : public wxNotifyEvent
 public:
     /**
         Return the index of the column affected by this event.
+
+        This method can be called for all header control events.
      */
     int GetColumn() const;
+
+    /**
+        Return the current width of the column.
+
+        This method can only be called for the dragging events.
+     */
+    int GetWidth() const;
+
+    /**
+        Return @true if the drag operation was cancelled.
+
+        This method can only be called for the end drag event.
+     */
+    bool IsCancelled() const;
 };
index a424e924d2a759630055011f2f31bad8a4a0feeb..f17c3f8d71092b264bb40ce9ec685f954da70236 100644 (file)
@@ -177,3 +177,7 @@ const wxEventType wxEVT_COMMAND_HEADER_RIGHT_DCLICK = wxNewEventType();
 const wxEventType wxEVT_COMMAND_HEADER_MIDDLE_DCLICK = wxNewEventType();
 
 const wxEventType wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK = wxNewEventType();
+
+const wxEventType wxEVT_COMMAND_HEADER_BEGIN_DRAG = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_DRAGGING = wxNewEventType();
+const wxEventType wxEVT_COMMAND_HEADER_END_DRAG = wxNewEventType();
index 0fbcc1510c6f2e9656ff62c625ad984b4ac0766e..3091a3adcab44d1186181f32f980c584f4cd0d98 100644 (file)
@@ -102,6 +102,7 @@ protected:
 
         int widthContents = owner->GetBestColumnWidth(idx);
         owner->GetColumn(idx)->SetWidth(wxMax(widthTitle, widthContents));
+        owner->OnColumnChange(idx);
 
         return true;
     }
@@ -136,6 +137,28 @@ private:
             event.Skip();
     }
 
+    void OnBeginDrag(wxHeaderCtrlEvent& event)
+    {
+        if ( !GetColumn(event.GetColumn()).IsResizeable() )
+            event.Veto();
+    }
+
+    void OnDragging(wxHeaderCtrlEvent& event)
+    {
+        const wxHeaderColumnBase& col = GetColumn(event.GetColumn());
+
+        const int minWidth = col.GetMinWidth();
+        if ( event.GetWidth() < minWidth )
+            event.Veto();
+    }
+
+    void OnEndDrag(wxHeaderCtrlEvent& event)
+    {
+        const unsigned col = event.GetColumn();
+        GetColumn(col).SetWidth(event.GetWidth());
+        GetOwner()->OnColumnChange(col);
+    }
+
     DECLARE_EVENT_TABLE()
     DECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow)
 };
@@ -143,6 +166,10 @@ private:
 BEGIN_EVENT_TABLE(wxDataViewHeaderWindow, wxHeaderCtrl)
     EVT_HEADER_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnClick)
     EVT_HEADER_RIGHT_CLICK(wxID_ANY, wxDataViewHeaderWindow::OnRClick)
+
+    EVT_HEADER_BEGIN_DRAG(wxID_ANY, wxDataViewHeaderWindow::OnBeginDrag)
+    EVT_HEADER_DRAGGING(wxID_ANY, wxDataViewHeaderWindow::OnDragging)
+    EVT_HEADER_END_DRAG(wxID_ANY, wxDataViewHeaderWindow::OnEndDrag)
 END_EVENT_TABLE()
 
 //-----------------------------------------------------------------------------
@@ -3288,7 +3315,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
         return false;
 
     m_cols.Append( col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
@@ -3298,7 +3325,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col )
         return false;
 
     m_cols.Insert( col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
@@ -3308,11 +3335,19 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
         return false;
 
     m_cols.Insert( pos, col );
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
-void wxDataViewCtrl::OnColumnChange()
+void wxDataViewCtrl::OnColumnChange(unsigned int idx)
+{
+    if ( m_headerArea )
+        m_headerArea->UpdateColumn(idx);
+
+    m_clientArea->UpdateDisplay();
+}
+
+void wxDataViewCtrl::OnColumnsCountChanged()
 {
     if (m_headerArea)
         m_headerArea->SetColumnCount(GetColumnCount());
@@ -3335,20 +3370,9 @@ unsigned int wxDataViewCtrl::GetColumnCount() const
     return m_cols.GetCount();
 }
 
-wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int pos ) const
+wxDataViewColumn* wxDataViewCtrl::GetColumn( unsigned int idx ) const
 {
-    wxDataViewColumnList::const_iterator iter;
-    unsigned int i = 0;
-    for (iter = m_cols.begin(); iter!=m_cols.end(); iter++)
-    {
-        if (i == pos)
-            return *iter;
-
-        if ((*iter)->IsHidden())
-            continue;
-        i ++;
-    }
-    return NULL;
+    return m_cols[idx];
 }
 
 void wxDataViewCtrl::ColumnMoved( wxDataViewColumn* col, unsigned int new_pos )
@@ -3371,7 +3395,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
         return false;
 
     m_cols.Erase(ret);
-    OnColumnChange();
+    OnColumnsCountChanged();
 
     return true;
 }
@@ -3379,7 +3403,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
 bool wxDataViewCtrl::ClearColumns()
 {
     m_cols.Clear();
-    OnColumnChange();
+    OnColumnsCountChanged();
     return true;
 }
 
index 8d8adc9fc42c2a9bdae0ccdc98f82d47274c471a..be040a5ac6745d0083ff121854c30384102d428d 100644 (file)
@@ -57,7 +57,8 @@ const unsigned COL_NONE = (unsigned)-1;
 void wxHeaderCtrl::Init()
 {
     m_numColumns = 0;
-    m_hover = COL_NONE;
+    m_hover =
+    m_colBeingResized = COL_NONE;
     m_scrollOffset = 0;
 }
 
@@ -209,6 +210,55 @@ void wxHeaderCtrl::RefreshColsAfter(unsigned int idx)
     RefreshRect(rect);
 }
 
+// ----------------------------------------------------------------------------
+// wxHeaderCtrl dragging
+// ----------------------------------------------------------------------------
+
+void wxHeaderCtrl::UpdateResizingMarker(int xPhysical)
+{
+    // unfortunately drawing the marker over the parent window doesn't work as
+    // it's usually covered by another window (the main control view) so just
+    // draw the marker over the header itself, even if it makes it not very
+    // useful
+    wxClientDC dc(this);
+
+    wxDCOverlay dcover(m_overlay, &dc);
+    dcover.Clear();
+
+    if ( xPhysical != -1 )
+    {
+        dc.SetPen(*wxLIGHT_GREY_PEN);
+        dc.DrawLine(xPhysical, 0, xPhysical, GetClientSize().y);
+    }
+}
+
+void wxHeaderCtrl::EndDragging()
+{
+    UpdateResizingMarker(-1);
+
+    m_overlay.Reset();
+}
+
+void wxHeaderCtrl::EndResizing(int width)
+{
+    wxASSERT_MSG( m_colBeingResized != COL_NONE,
+                  "shouldn't be called if we're not resizing" );
+
+    EndDragging();
+
+    wxHeaderCtrlEvent event(wxEVT_COMMAND_HEADER_END_DRAG, GetId());
+    event.SetEventObject(this);
+    event.SetColumn(m_colBeingResized);
+    if ( width == -1 )
+        event.SetCancelled();
+    else
+        event.SetWidth(width);
+
+    GetEventHandler()->ProcessEvent(event);
+
+    m_colBeingResized = COL_NONE;
+}
+
 // ----------------------------------------------------------------------------
 // wxHeaderCtrl event handlers
 // ----------------------------------------------------------------------------
@@ -217,6 +267,8 @@ BEGIN_EVENT_TABLE(wxHeaderCtrl, wxHeaderCtrlBase)
     EVT_PAINT(wxHeaderCtrl::OnPaint)
 
     EVT_MOUSE_EVENTS(wxHeaderCtrl::OnMouse)
+
+    EVT_MOUSE_CAPTURE_LOST(wxHeaderCtrl::OnCaptureLost)
 END_EVENT_TABLE()
 
 void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
@@ -283,18 +335,42 @@ void wxHeaderCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
     }
 }
 
+void wxHeaderCtrl::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event))
+{
+    if ( m_colBeingResized != COL_NONE )
+        EndResizing(-1);
+}
+
 void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
 {
+    // do this in advance to allow simply returning if we're not interested,
+    // we'll undo it if we do handle the event below
     mevent.Skip();
 
+
     // account for the control displacement
-    const int x = mevent.GetX() - m_scrollOffset;
+    const int xPhysical = mevent.GetX();
+    const int xLogical = xPhysical - m_scrollOffset;
+
+    // first deal with the [continuation of any] dragging operations in
+    // progress
+    if ( m_colBeingResized != COL_NONE )
+    {
+        if ( mevent.LeftUp() )
+            EndResizing(xLogical - GetColStart(m_colBeingResized));
+        else // update the live separator position
+            UpdateResizingMarker(xPhysical);
+
+        return;
+    }
+
 
     // find if the event is over a column at all
     bool onSeparator;
     const unsigned col = mevent.Leaving()
                             ? (onSeparator = false, COL_NONE)
-                            : FindColumnAtPos(x, onSeparator);
+                            : FindColumnAtPos(xLogical, onSeparator);
+
 
     // update the highlighted column if it changed
     if ( col != m_hover )
@@ -306,9 +382,6 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
         RefreshColIfNotNone(m_hover);
     }
 
-    if ( col == COL_NONE )
-        return;
-
     // update mouse cursor as it moves around
     if ( mevent.Moving() )
     {
@@ -316,20 +389,30 @@ void wxHeaderCtrl::OnMouse(wxMouseEvent& mevent)
         return;
     }
 
+    // all the other events only make sense when they happen over a column
+    if ( col == COL_NONE )
+        return;
+
+
+    // enter various dragging modes on left mouse press
     if ( mevent.LeftDown() )
     {
-        // TODO
         if ( onSeparator )
-            // resize column
-            ;
-        else
-            // drag column
+        {
+            // start resizing the column
+            m_colBeingResized = col;
+            UpdateResizingMarker(xPhysical);
+        }
+        else // on column itself
+        {
+            // TODO: drag column
             ;
+        }
 
         return;
     }
 
-    // determine the type of header event corresponding to this mouse event
+    // determine the type of header event corresponding to click events
     wxEventType evtType = wxEVT_NULL;
     const bool click = mevent.ButtonUp(),
                dblclk = mevent.ButtonDClick();
index 8df0e8286cc0dac891205cfcb858bfd3d103a667..e60b1bbc1bd9d50f427471d66b6566f9787460d6 100644 (file)
@@ -260,16 +260,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 +282,27 @@ 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;
+    wxEventType evtType = wxEVT_NULL;
+    int idx = nmhdr->iItem;
+    int width = 0;
     switch ( const UINT code = nmhdr->hdr.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,22 +312,66 @@ 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) )
-                return true;
+            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:
+            evtType = wxEVT_COMMAND_HEADER_BEGIN_DRAG;
+            // fall through
+
+        case HDN_TRACKA:
+        case HDN_TRACKW:
+            if ( evtType == wxEVT_NULL )
+                evtType = wxEVT_COMMAND_HEADER_DRAGGING;
+            // fall through
+
+        case HDN_ENDTRACKA:
+        case HDN_ENDTRACKW:
+            if ( evtType == wxEVT_NULL )
+                evtType = wxEVT_COMMAND_HEADER_END_DRAG;
+
+            width = nmhdr->pitem->cxy;
             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 ( 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);
 }