]> git.saurik.com Git - wxWidgets.git/blame - src/msw/headerctrl.cpp
Use the app name, not display name, as debug report name,
[wxWidgets.git] / src / msw / headerctrl.cpp
CommitLineData
56873923
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/headerctrl.cpp
3// Purpose: implementation of wxHeaderCtrl for wxMSW
4// Author: Vadim Zeitlin
5// Created: 2008-12-01
6// RCS-ID: $Id$
7// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
e721a2a2
VZ
26#if wxUSE_HEADERCTRL
27
56873923 28#ifndef WX_PRECOMP
9485b24f 29 #include "wx/app.h"
9ef3e400 30 #include "wx/log.h"
56873923
VZ
31#endif // WX_PRECOMP
32
33#include "wx/headerctrl.h"
3bfaa5a7
VZ
34
35#ifndef wxHAS_GENERIC_HEADERCTRL
36
56873923
VZ
37#include "wx/imaglist.h"
38
39#include "wx/msw/wrapcctl.h"
9ef3e400 40#include "wx/msw/private.h"
56873923 41
9b66a1d3
VZ
42#ifndef HDM_SETBITMAPMARGIN
43 #define HDM_SETBITMAPMARGIN 0x1234
44#endif
45
46#ifndef Header_SetBitmapMargin
47 #define Header_SetBitmapMargin(hwnd, margin) \
48 ::SendMessage((hwnd), HDM_SETBITMAPMARGIN, (WPARAM)(margin), 0)
49#endif
50
fa3d4aaf
VZ
51// from src/msw/listctrl.cpp
52extern int WXDLLIMPEXP_CORE wxMSWGetColumnClicked(NMHDR *nmhdr, POINT *ptClick);
53
56873923
VZ
54// ============================================================================
55// wxHeaderCtrl implementation
56// ============================================================================
57
58// ----------------------------------------------------------------------------
59// wxHeaderCtrl construction/destruction
60// ----------------------------------------------------------------------------
61
62void wxHeaderCtrl::Init()
63{
040b9528 64 m_numColumns = 0;
56873923 65 m_imageList = NULL;
38cd07c4 66 m_scrollOffset = 0;
56873923
VZ
67}
68
69bool wxHeaderCtrl::Create(wxWindow *parent,
70 wxWindowID id,
71 const wxPoint& pos,
72 const wxSize& size,
73 long style,
74 const wxString& name)
75{
76 // notice that we don't need InitCommonControlsEx(ICC_LISTVIEW_CLASSES)
77 // here as we already call InitCommonControls() in wxApp initialization
78 // code which covers this
79
80 if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) )
81 return false;
82
9a83f860 83 if ( !MSWCreateControl(WC_HEADER, wxT(""), pos, size) )
56873923
VZ
84 return false;
85
9485b24f
VZ
86 // special hack for margins when using comctl32.dll v6 or later: the
87 // default margin is too big and results in label truncation when the
88 // column width is just about right to show it together with the sort
89 // indicator, so reduce it to a smaller value (in principle we could even
90 // use 0 here but this starts to look ugly)
91 if ( wxApp::GetComCtl32Version() >= 600 )
92 {
93 Header_SetBitmapMargin(GetHwnd(), ::GetSystemMetrics(SM_CXEDGE));
94 }
95
56873923
VZ
96 return true;
97}
98
99WXDWORD wxHeaderCtrl::MSWGetStyle(long style, WXDWORD *exstyle) const
100{
101 WXDWORD msStyle = wxControl::MSWGetStyle(style, exstyle);
102
613de0e8 103 if ( style & wxHD_ALLOW_REORDER )
56873923
VZ
104 msStyle |= HDS_DRAGDROP;
105
106 // the control looks nicer with these styles and there doesn't seem to be
107 // any reason to not use them so we always do (as for HDS_HORZ it is 0
108 // anyhow but include it for clarity)
cf3fd63e
FM
109 // NOTE: don't use however HDS_FLAT because it makes the control look
110 // non-native when running WinXP in classic mode
111 msStyle |= HDS_HORZ | HDS_BUTTONS | HDS_FULLDRAG | HDS_HOTTRACK;
56873923
VZ
112
113 return msStyle;
114}
115
116wxHeaderCtrl::~wxHeaderCtrl()
117{
118 delete m_imageList;
119}
120
f24f6579
VZ
121// ----------------------------------------------------------------------------
122// wxHeaderCtrl scrolling
123// ----------------------------------------------------------------------------
124
38cd07c4
VZ
125void wxHeaderCtrl::DoSetSize(int x, int y,
126 int w, int h,
127 int sizeFlags)
128{
129 wxHeaderCtrlBase::DoSetSize(x + m_scrollOffset, y, w - m_scrollOffset, h,
130 sizeFlags);
131}
132
d8fc3398 133void wxHeaderCtrl::DoScrollHorz(int dx)
f24f6579 134{
d8fc3398
VZ
135 // as the native control doesn't support offsetting its contents, we use a
136 // hack here to make it appear correctly when the parent is scrolled:
137 // instead of scrolling or repainting we simply move the control window
138 // itself: to be precise, offset it by the scroll increment to the left and
139 // increment its width to still extend to the right boundary to compensate
140 // for it (notice that dx is negative when scrolling to the right)
38cd07c4
VZ
141 m_scrollOffset += dx;
142
143 wxHeaderCtrlBase::DoSetSize(GetPosition().x + dx, -1,
144 GetSize().x - dx, -1,
145 wxSIZE_USE_EXISTING);
f24f6579
VZ
146}
147
56873923
VZ
148// ----------------------------------------------------------------------------
149// wxHeaderCtrl geometry calculation
150// ----------------------------------------------------------------------------
151
152wxSize wxHeaderCtrl::DoGetBestSize() const
153{
154 RECT rc = wxGetClientRect(GetHwndOf(GetParent()));
155 WINDOWPOS wpos;
156 HDLAYOUT layout = { &rc, &wpos };
157 if ( !Header_Layout(GetHwnd(), &layout) )
158 {
9a83f860 159 wxLogLastError(wxT("Header_Layout"));
56873923
VZ
160 return wxControl::DoGetBestSize();
161 }
162
163 return wxSize(wpos.cx, wpos.cy);
164}
165
166// ----------------------------------------------------------------------------
167// wxHeaderCtrl columns managements
168// ----------------------------------------------------------------------------
169
170unsigned int wxHeaderCtrl::DoGetCount() const
171{
040b9528
VZ
172 // we can't use Header_GetItemCount() here because it doesn't take the
173 // hidden columns into account and we can't find the hidden columns after
174 // the last shown one in MSWFromNativeIdx() without knowing where to stop
175 // so we have to store the columns count internally
176 return m_numColumns;
177}
178
179int wxHeaderCtrl::GetShownColumnsCount() const
180{
181 const int numItems = Header_GetItemCount(GetHwnd());
182
183 wxASSERT_MSG( numItems >= 0 && (unsigned)numItems <= m_numColumns,
184 "unexpected number of items in the native control" );
185
186 return numItems;
56873923
VZ
187}
188
e2bfe673 189void wxHeaderCtrl::DoSetCount(unsigned int count)
56873923 190{
e2bfe673
VZ
191 unsigned n;
192
193 // first delete all old columns
040b9528 194 const unsigned countOld = GetShownColumnsCount();
e2bfe673
VZ
195 for ( n = 0; n < countOld; n++ )
196 {
197 if ( !Header_DeleteItem(GetHwnd(), 0) )
198 {
9a83f860 199 wxLogLastError(wxT("Header_DeleteItem"));
e2bfe673
VZ
200 }
201 }
202
040b9528
VZ
203 // update the column indices order array before changing m_numColumns
204 DoResizeColumnIndices(m_colIndices, count);
205
e2bfe673 206 // and add the new ones
040b9528
VZ
207 m_numColumns = count;
208 m_isHidden.resize(m_numColumns);
e2bfe673
VZ
209 for ( n = 0; n < count; n++ )
210 {
040b9528
VZ
211 const wxHeaderColumn& col = GetColumn(n);
212 if ( col.IsShown() )
213 {
214 m_isHidden[n] = false;
215
216 DoInsertItem(col, n);
217 }
218 else // hidden initially
219 {
220 m_isHidden[n] = true;
221 }
e2bfe673
VZ
222 }
223}
224
225void wxHeaderCtrl::DoUpdate(unsigned int idx)
226{
4de60a27
VZ
227 // the native control does provide Header_SetItem() but it's inconvenient
228 // to use it because it sends HDN_ITEMCHANGING messages and we'd have to
229 // arrange not to block setting the width from there and the logic would be
230 // more complicated as we'd have to reset the old values as well as setting
231 // the new ones -- so instead just recreate the column
702f5349 232
040b9528
VZ
233 const wxHeaderColumn& col = GetColumn(idx);
234 if ( col.IsHidden() )
235 {
236 // column is hidden now
237 if ( !m_isHidden[idx] )
238 {
239 // but it wasn't hidden before, so remove it
240 Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx));
241
242 m_isHidden[idx] = true;
243 }
244 //else: nothing to do, updating hidden column doesn't have any effect
245 }
246 else // column is shown now
247 {
248 if ( m_isHidden[idx] )
249 {
250 m_isHidden[idx] = false;
251 }
252 else // and it was shown before as well
253 {
254 // we need to remove the old column
255 Header_DeleteItem(GetHwnd(), MSWToNativeIdx(idx));
256 }
257
258 DoInsertItem(col, idx);
259 }
e2bfe673
VZ
260}
261
040b9528 262void wxHeaderCtrl::DoInsertItem(const wxHeaderColumn& col, unsigned int idx)
e2bfe673 263{
040b9528 264 wxASSERT_MSG( !col.IsHidden(), "should only be called for shown columns" );
e2bfe673
VZ
265
266 wxHDITEM hdi;
267
268 // notice that we need to store the string we use the pointer to until we
269 // pass it to the control
89c73d54
VZ
270 hdi.mask |= HDI_TEXT;
271 wxWxCharBuffer buf = col.GetTitle().wx_str();
272 hdi.pszText = buf.data();
273 hdi.cchTextMax = wxStrlen(buf);
56873923
VZ
274
275 const wxBitmap bmp = col.GetBitmap();
4de60a27 276 if ( bmp.IsOk() )
56873923 277 {
89c73d54 278 hdi.mask |= HDI_IMAGE;
56873923 279
89c73d54 280 if ( bmp.IsOk() )
56873923 281 {
89c73d54
VZ
282 const int bmpWidth = bmp.GetWidth(),
283 bmpHeight = bmp.GetHeight();
284
285 if ( !m_imageList )
286 {
287 m_imageList = new wxImageList(bmpWidth, bmpHeight);
288 Header_SetImageList(GetHwnd(), GetHimagelistOf(m_imageList));
289 }
290 else // already have an image list
291 {
292 // check that all bitmaps we use have the same size
293 int imageWidth,
294 imageHeight;
295 m_imageList->GetSize(0, imageWidth, imageHeight);
296
297 wxASSERT_MSG( imageWidth == bmpWidth && imageHeight == bmpHeight,
298 "all column bitmaps must have the same size" );
299 }
300
301 m_imageList->Add(bmp);
302 hdi.iImage = m_imageList->GetImageCount() - 1;
56873923 303 }
89c73d54 304 else // no bitmap but we still need to update the item
56873923 305 {
89c73d54 306 hdi.iImage = I_IMAGENONE;
56873923 307 }
56873923
VZ
308 }
309
4de60a27 310 if ( col.GetAlignment() != wxALIGN_NOT )
a0009205 311 {
9485b24f 312 hdi.mask |= HDI_FORMAT | HDF_LEFT;
e2bfe673
VZ
313 switch ( col.GetAlignment() )
314 {
315 case wxALIGN_LEFT:
316 hdi.fmt |= HDF_LEFT;
317 break;
56873923 318
e2bfe673
VZ
319 case wxALIGN_CENTER:
320 case wxALIGN_CENTER_HORIZONTAL:
321 hdi.fmt |= HDF_CENTER;
322 break;
56873923 323
e2bfe673
VZ
324 case wxALIGN_RIGHT:
325 hdi.fmt |= HDF_RIGHT;
326 break;
56873923 327
e2bfe673
VZ
328 default:
329 wxFAIL_MSG( "invalid column header alignment" );
330 }
331 }
a0009205 332
e2bfe673 333 if ( col.IsSortKey() )
a0009205 334 {
e2bfe673
VZ
335 hdi.mask |= HDI_FORMAT;
336 hdi.fmt |= col.IsSortOrderAscending() ? HDF_SORTUP : HDF_SORTDOWN;
a0009205
VZ
337 }
338
040b9528 339 if ( col.GetWidth() != wxCOL_WIDTH_DEFAULT )
a0009205 340 {
e2bfe673 341 hdi.mask |= HDI_WIDTH;
040b9528 342 hdi.cxy = col.GetWidth();
a0009205 343 }
a0009205 344
040b9528 345 hdi.mask |= HDI_ORDER;
2e733ec7 346 hdi.iOrder = MSWToNativeOrder(m_colIndices.Index(idx));
702f5349 347
040b9528
VZ
348 if ( ::SendMessage(GetHwnd(), HDM_INSERTITEM,
349 MSWToNativeIdx(idx), (LPARAM)&hdi) == -1 )
56873923 350 {
9a83f860 351 wxLogLastError(wxT("Header_InsertItem()"));
56873923
VZ
352 }
353}
354
702f5349
VZ
355void wxHeaderCtrl::DoSetColumnsOrder(const wxArrayInt& order)
356{
040b9528
VZ
357 wxArrayInt orderShown;
358 orderShown.reserve(m_numColumns);
359
360 for ( unsigned n = 0; n < m_numColumns; n++ )
361 {
362 const int idx = order[n];
363 if ( GetColumn(idx).IsShown() )
364 orderShown.push_back(MSWToNativeIdx(idx));
365 }
366
367 if ( !Header_SetOrderArray(GetHwnd(), orderShown.size(), &orderShown[0]) )
702f5349 368 {
9a83f860 369 wxLogLastError(wxT("Header_GetOrderArray"));
702f5349 370 }
040b9528
VZ
371
372 m_colIndices = order;
702f5349
VZ
373}
374
375wxArrayInt wxHeaderCtrl::DoGetColumnsOrder() const
376{
040b9528
VZ
377 // we don't use Header_GetOrderArray() here because it doesn't return
378 // information about the hidden columns, instead we just save the columns
379 // order array in DoSetColumnsOrder() and update it when they're reordered
380 return m_colIndices;
381}
382
2e733ec7
VZ
383// ----------------------------------------------------------------------------
384// wxHeaderCtrl indexes and positions translation
385// ----------------------------------------------------------------------------
386
040b9528
VZ
387int wxHeaderCtrl::MSWToNativeIdx(int idx)
388{
389 // don't check for GetColumn(idx).IsShown() as it could have just became
390 // false and we may be called from DoUpdate() to delete the old column
391 wxASSERT_MSG( !m_isHidden[idx],
392 "column must be visible to have an "
393 "index in the native control" );
394
2e733ec7 395 int item = idx;
040b9528 396 for ( int i = 0; i < idx; i++ )
702f5349 397 {
040b9528 398 if ( GetColumn(i).IsHidden() )
2e733ec7 399 item--; // one less column the native control knows about
040b9528
VZ
400 }
401
2e733ec7
VZ
402 wxASSERT_MSG( item >= 0 && item <= GetShownColumnsCount(), "logic error" );
403
404 return item;
040b9528
VZ
405}
406
407int wxHeaderCtrl::MSWFromNativeIdx(int item)
408{
409 wxASSERT_MSG( item >= 0 && item < GetShownColumnsCount(),
410 "column index out of range" );
411
412 // reverse the above function
2e733ec7
VZ
413
414 unsigned idx = item;
415 for ( unsigned n = 0; n < m_numColumns; n++ )
040b9528 416 {
2e733ec7
VZ
417 if ( n > idx )
418 break;
419
420 if ( GetColumn(n).IsHidden() )
421 idx++;
040b9528
VZ
422 }
423
2e733ec7
VZ
424 wxASSERT_MSG( MSWToNativeIdx(idx) == item, "logic error" );
425
426 return idx;
040b9528
VZ
427}
428
2e733ec7 429int wxHeaderCtrl::MSWToNativeOrder(int pos)
040b9528 430{
2e733ec7 431 wxASSERT_MSG( pos >= 0 && static_cast<unsigned>(pos) < m_numColumns,
040b9528
VZ
432 "column position out of range" );
433
2e733ec7
VZ
434 int order = pos;
435 for ( int n = 0; n < pos; n++ )
040b9528 436 {
2e733ec7
VZ
437 if ( GetColumn(m_colIndices[n]).IsHidden() )
438 order--;
702f5349
VZ
439 }
440
2e733ec7
VZ
441 wxASSERT_MSG( order >= 0 && order <= GetShownColumnsCount(), "logic error" );
442
702f5349
VZ
443 return order;
444}
445
2e733ec7
VZ
446int wxHeaderCtrl::MSWFromNativeOrder(int order)
447{
448 wxASSERT_MSG( order >= 0 && order < GetShownColumnsCount(),
449 "native column position out of range" );
450
451 unsigned pos = order;
452 for ( unsigned n = 0; n < m_numColumns; n++ )
453 {
454 if ( n > pos )
455 break;
456
457 if ( GetColumn(m_colIndices[n]).IsHidden() )
458 pos++;
459 }
460
461 wxASSERT_MSG( MSWToNativeOrder(pos) == order, "logic error" );
462
463 return pos;
464}
465
fa3d4aaf
VZ
466// ----------------------------------------------------------------------------
467// wxHeaderCtrl events
468// ----------------------------------------------------------------------------
469
aef252d9 470wxEventType wxHeaderCtrl::GetClickEventType(bool dblclk, int button)
fa3d4aaf
VZ
471{
472 wxEventType evtType;
473 switch ( button )
474 {
475 case 0:
476 evtType = dblclk ? wxEVT_COMMAND_HEADER_DCLICK
477 : wxEVT_COMMAND_HEADER_CLICK;
478 break;
479
480 case 1:
481 evtType = dblclk ? wxEVT_COMMAND_HEADER_RIGHT_DCLICK
482 : wxEVT_COMMAND_HEADER_RIGHT_CLICK;
483 break;
484
485 case 2:
486 evtType = dblclk ? wxEVT_COMMAND_HEADER_MIDDLE_DCLICK
487 : wxEVT_COMMAND_HEADER_MIDDLE_CLICK;
488 break;
489
490 default:
491 wxFAIL_MSG( wxS("unexpected event type") );
aef252d9 492 evtType = wxEVT_NULL;
fa3d4aaf
VZ
493 }
494
aef252d9 495 return evtType;
fa3d4aaf
VZ
496}
497
498bool wxHeaderCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
499{
500 NMHEADER * const nmhdr = (NMHEADER *)lParam;
501
aef252d9 502 wxEventType evtType = wxEVT_NULL;
aef252d9 503 int width = 0;
702f5349 504 int order = -1;
702f5349 505 bool veto = false;
0c9c5b43 506 const UINT code = nmhdr->hdr.code;
040b9528
VZ
507
508 // we don't have the index for all events, e.g. not for NM_RELEASEDCAPTURE
509 // so only access for header control events (and yes, the direction of
510 // comparisons with FIRST/LAST is correct even if it seems inverted)
511 int idx = code <= HDN_FIRST && code > HDN_LAST ? nmhdr->iItem : -1;
512 if ( idx != -1 )
513 {
514 // we also get bogus HDN_BEGINDRAG with -1 index so don't call
515 // MSWFromNativeIdx() unconditionally for nmhdr->iItem
516 idx = MSWFromNativeIdx(idx);
517 }
518
0c9c5b43 519 switch ( code )
fa3d4aaf 520 {
aef252d9
VZ
521 // click events
522 // ------------
523
fa3d4aaf
VZ
524 case HDN_ITEMCLICK:
525 case HDN_ITEMDBLCLICK:
aef252d9 526 evtType = GetClickEventType(code == HDN_ITEMDBLCLICK, nmhdr->iButton);
fa3d4aaf
VZ
527 break;
528
529 // although we should get the notifications about the right clicks
530 // via HDN_ITEM[DBL]CLICK too according to MSDN this simply doesn't
531 // happen in practice on any Windows system up to 2003
532 case NM_RCLICK:
533 case NM_RDBLCLK:
534 {
535 POINT pt;
aef252d9
VZ
536 idx = wxMSWGetColumnClicked(&nmhdr->hdr, &pt);
537 if ( idx != wxNOT_FOUND )
040b9528
VZ
538 {
539 idx = MSWFromNativeIdx(idx);
36e5a9a7
VZ
540
541 // due to a bug in mingw32 headers NM_RDBLCLK is signed
542 // there so we need a cast to avoid warnings about signed/
543 // unsigned comparison
544 evtType = GetClickEventType(
545 code == static_cast<UINT>(NM_RDBLCLK), 1);
040b9528 546 }
fa3d4aaf
VZ
547 //else: ignore clicks outside any column
548 }
549 break;
3bfaa5a7
VZ
550
551 case HDN_DIVIDERDBLCLICK:
aef252d9
VZ
552 evtType = wxEVT_COMMAND_HEADER_SEPARATOR_DCLICK;
553 break;
554
555
556 // column resizing events
557 // ----------------------
558
559 // see comments in wxListCtrl::MSWOnNotify() for why we catch both
560 // ASCII and Unicode versions of this message
561 case HDN_BEGINTRACKA:
562 case HDN_BEGINTRACKW:
0b2e1483
VZ
563 // non-resizeable columns can't be resized no matter what, don't
564 // even generate any events for them
565 if ( !GetColumn(idx).IsResizeable() )
566 {
702f5349
VZ
567 veto = true;
568 break;
0b2e1483
VZ
569 }
570
396825dc 571 evtType = wxEVT_COMMAND_HEADER_BEGIN_RESIZE;
aef252d9
VZ
572 // fall through
573
aef252d9
VZ
574 case HDN_ENDTRACKA:
575 case HDN_ENDTRACKW:
a45caa71
VZ
576 width = nmhdr->pitem->cxy;
577
aef252d9 578 if ( evtType == wxEVT_NULL )
a45caa71 579 {
396825dc 580 evtType = wxEVT_COMMAND_HEADER_END_RESIZE;
aef252d9 581
a45caa71
VZ
582 // don't generate events with invalid width
583 const int minWidth = GetColumn(idx).GetMinWidth();
584 if ( width < minWidth )
585 width = minWidth;
586 }
587 break;
588
589 case HDN_ITEMCHANGING:
590 if ( nmhdr->pitem && (nmhdr->pitem->mask & HDI_WIDTH) )
591 {
592 // prevent the column from being shrunk beneath its min width
93e4e62b
VZ
593 width = nmhdr->pitem->cxy;
594 if ( width < GetColumn(idx).GetMinWidth() )
595 {
596 // don't generate any events and prevent the change from
597 // happening
702f5349 598 veto = true;
93e4e62b
VZ
599 }
600 else // width is acceptable
601 {
602 // generate the resizing event from here as we don't seem
603 // to be getting HDN_TRACK events at all, at least with
604 // comctl32.dll v6
605 evtType = wxEVT_COMMAND_HEADER_RESIZING;
606 }
702f5349
VZ
607 }
608 break;
609
610
611 // column reordering events
612 // ------------------------
613
614 case HDN_BEGINDRAG:
615 // Windows sometimes sends us events with invalid column indices
040b9528 616 if ( nmhdr->iItem == -1 )
702f5349 617 break;
a45caa71 618
702f5349
VZ
619 // column must have the appropriate flag to be draggable
620 if ( !GetColumn(idx).IsReorderable() )
621 {
622 veto = true;
623 break;
a45caa71 624 }
702f5349
VZ
625
626 evtType = wxEVT_COMMAND_HEADER_BEGIN_REORDER;
627 break;
628
629 case HDN_ENDDRAG:
702f5349
VZ
630 wxASSERT_MSG( nmhdr->pitem->mask & HDI_ORDER, "should have order" );
631 order = nmhdr->pitem->iOrder;
040b9528
VZ
632
633 // we also get messages with invalid order when column reordering
634 // is cancelled (e.g. by pressing Esc)
635 if ( order == -1 )
636 break;
637
638 order = MSWFromNativeOrder(order);
639
640 evtType = wxEVT_COMMAND_HEADER_END_REORDER;
a45caa71
VZ
641 break;
642
643 case NM_RELEASEDCAPTURE:
565804f2 644 evtType = wxEVT_COMMAND_HEADER_DRAGGING_CANCELLED;
3bfaa5a7 645 break;
fa3d4aaf
VZ
646 }
647
aef252d9
VZ
648
649 // do generate the corresponding wx event
650 if ( evtType != wxEVT_NULL )
651 {
652 wxHeaderCtrlEvent event(evtType, GetId());
653 event.SetEventObject(this);
654 event.SetColumn(idx);
655 event.SetWidth(width);
702f5349
VZ
656 if ( order != -1 )
657 event.SetNewOrder(order);
aef252d9
VZ
658
659 if ( GetEventHandler()->ProcessEvent(event) )
660 {
702f5349 661 if ( event.IsAllowed() )
040b9528 662 return true; // skip default message handling below
aef252d9 663
702f5349
VZ
664 // we need to veto the default handling of this message, don't
665 // return to execute the code in the "if veto" branch below
666 veto = true;
aef252d9 667 }
040b9528
VZ
668 else // not processed
669 {
670 // special post-processing for HDN_ENDDRAG: we need to update the
671 // internal column indices array if this is allowed to go ahead as
672 // the native control is going to reorder its columns now
673 if ( evtType == wxEVT_COMMAND_HEADER_END_REORDER )
674 MoveColumnInOrderArray(m_colIndices, idx, order);
675 }
aef252d9
VZ
676 }
677
702f5349
VZ
678 if ( veto )
679 {
680 // all of HDN_BEGIN{DRAG,TRACK}, HDN_TRACK and HDN_ITEMCHANGING
681 // interpret TRUE return value as meaning to stop the control
682 // default handling of the message
683 *result = TRUE;
684
685 return true;
686 }
687
fa3d4aaf
VZ
688 return wxHeaderCtrlBase::MSWOnNotify(idCtrl, lParam, result);
689}
3bfaa5a7
VZ
690
691#endif // wxHAS_GENERIC_HEADERCTRL
e721a2a2
VZ
692
693#endif // wxUSE_HEADERCTRL