4 * Copyright 1998 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
6 * Copyright 2003 Maxime Bellenge
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * - Imagelist support (partially).
24 * - Callback items (under construction).
25 * - Hottrack support (partially).
26 * - Custom draw support (including Notifications).
27 * - Drag and Drop support (including Notifications).
29 * - Use notification format
30 * - Correct the order maintenance code to preserve valid order
39 #include "wine/unicode.h"
45 #include "imagelist.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(header
);
58 INT iOrder
; /* see documentation of HD_ITEM */
60 BOOL bDown
; /* is item pressed? (used for drawing) */
61 RECT rect
; /* bounding rectangle of the item */
67 HWND hwndNotify
; /* Owner window to send notifications to */
68 INT nNotifyFormat
; /* format used for WM_NOTIFY messages */
69 UINT uNumItem
; /* number of items (columns) */
70 INT nHeight
; /* height of the header (pixels) */
71 HFONT hFont
; /* handle to the current font */
72 HCURSOR hcurArrow
; /* handle to the arrow cursor */
73 HCURSOR hcurDivider
; /* handle to a cursor (used over dividers) <-|-> */
74 HCURSOR hcurDivopen
; /* handle to a cursor (used over dividers) <-||-> */
75 BOOL bCaptured
; /* Is the mouse captured? */
76 BOOL bPressed
; /* Is a header item pressed (down)? */
77 BOOL bTracking
; /* Is in tracking mode? */
78 BOOL bUnicode
; /* Unicode flag */
79 INT iMoveItem
; /* index of tracked item. (Tracking mode) */
80 INT xTrackOffset
; /* distance between the right side of the tracked item and the cursor */
81 INT xOldTrack
; /* track offset (see above) after the last WM_MOUSEMOVE */
82 INT nOldWidth
; /* width of a sizing item after the last WM_MOUSEMOVE */
83 INT iHotItem
; /* index of hot item (cursor is over this item) */
84 INT iMargin
; /* width of the margin that surrounds a bitmap */
86 HIMAGELIST himl
; /* handle to an image list (may be 0) */
87 HEADER_ITEM
*items
; /* pointer to array of HEADER_ITEM's */
88 BOOL bRectsValid
; /* validity flag for bounding rectangles */
93 #define DIVIDER_WIDTH 10
95 #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongPtrW(hwnd,0))
99 HEADER_IndexToOrder (HWND hwnd
, INT iItem
)
101 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
102 HEADER_ITEM
*lpItem
= &infoPtr
->items
[iItem
];
103 return lpItem
->iOrder
;
108 HEADER_OrderToIndex(HWND hwnd
, WPARAM wParam
)
110 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
111 INT iorder
= (INT
)wParam
;
114 if ((iorder
<0) || iorder
>infoPtr
->uNumItem
)
116 for (i
=0; i
<infoPtr
->uNumItem
; i
++)
117 if (HEADER_IndexToOrder(hwnd
,i
) == iorder
)
123 HEADER_SetItemBounds (HWND hwnd
)
125 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
131 infoPtr
->bRectsValid
= TRUE
;
133 if (infoPtr
->uNumItem
== 0)
136 GetClientRect (hwnd
, &rect
);
139 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
140 phdi
= &infoPtr
->items
[HEADER_OrderToIndex(hwnd
,i
)];
141 phdi
->rect
.top
= rect
.top
;
142 phdi
->rect
.bottom
= rect
.bottom
;
144 phdi
->rect
.right
= phdi
->rect
.left
+ ((phdi
->cxy
>0)?phdi
->cxy
:0);
145 x
= phdi
->rect
.right
;
150 HEADER_Size (HWND hwnd
, WPARAM wParam
)
152 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
154 infoPtr
->bRectsValid
= FALSE
;
161 HEADER_DrawItem (HWND hwnd
, HDC hdc
, INT iItem
, BOOL bHotTrack
)
163 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
164 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
166 INT oldBkMode
, cxEdge
= GetSystemMetrics(SM_CXEDGE
);
168 TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem
, bHotTrack
, infoPtr
->bUnicode
);
170 if (!infoPtr
->bRectsValid
)
171 HEADER_SetItemBounds(hwnd
);
174 if (r
.right
- r
.left
== 0)
175 return phdi
->rect
.right
;
177 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) {
179 DrawEdge (hdc
, &r
, BDR_RAISEDOUTER
,
180 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
185 DrawEdge (hdc
, &r
, EDGE_RAISED
,
186 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
189 DrawEdge (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
194 if (phdi
->fmt
& HDF_OWNERDRAW
) {
198 nmcd
.hdr
.hwndFrom
= hwnd
;
199 nmcd
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
200 nmcd
.hdr
.code
= NM_CUSTOMDRAW
;
201 nmcd
.dwDrawStage
= CDDS_PREPAINT
| CDDS_ITEM
| CDDS_ITEMPOSTERASE
;
203 nmcd
.dwItemSpec
= iItem
;
205 nmcd
.uItemState
= phdi
->bDown
? CDIS_SELECTED
: 0;
206 nmcd
.lItemlParam
= phdi
->lParam
;
208 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
209 (WPARAM
)nmcd
.hdr
.idFrom
, (LPARAM
)&nmcd
);
211 dis
.CtlType
= ODT_HEADER
;
212 dis
.CtlID
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
214 dis
.itemAction
= ODA_DRAWENTIRE
;
215 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
219 dis
.itemData
= phdi
->lParam
;
220 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
221 SendMessageW (infoPtr
->hwndNotify
, WM_DRAWITEM
,
222 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
223 if (oldBkMode
!= TRANSPARENT
)
224 SetBkMode(hdc
, oldBkMode
);
227 UINT rw
, rh
, /* width and height of r */
228 *x
= NULL
, *w
= NULL
; /* x and width of the pic (bmp or img) which is part of cnt */
229 /* cnt,txt,img,bmp */
234 cw
= tw
= iw
= bw
= 0;
235 rw
= r
.right
- r
.left
;
236 rh
= r
.bottom
- r
.top
;
238 if (phdi
->fmt
& HDF_STRING
) {
241 DrawTextW (hdc
, phdi
->pszText
, -1,
242 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
243 cw
= textRect
.right
- textRect
.left
+ 2 * infoPtr
->iMargin
;
246 if ((phdi
->fmt
& HDF_IMAGE
) && (infoPtr
->himl
)) {
247 iw
= infoPtr
->himl
->cx
+ 2 * infoPtr
->iMargin
;
252 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->hbm
)) {
253 GetObjectW (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
254 bw
= bmp
.bmWidth
+ 2 * infoPtr
->iMargin
;
264 /* align cx using the unclipped cw */
265 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_LEFT
)
267 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
268 cx
= r
.left
+ rw
/ 2 - cw
/ 2;
275 if (cx
+ cw
> r
.right
)
278 tx
= cx
+ infoPtr
->iMargin
;
279 /* since cw might have changed we have to recalculate tw */
280 tw
= cw
- infoPtr
->iMargin
* 2;
284 if (phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) {
285 /* put pic behind text */
286 *x
= cx
+ tw
+ infoPtr
->iMargin
* 3;
288 *x
= cx
+ infoPtr
->iMargin
;
289 /* move text behind pic */
295 /* since we're done with the layout we can
296 now calculate the position of bmp which
297 has no influence on alignment and layout
299 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
300 bx
= cx
- bw
+ infoPtr
->iMargin
;
302 bx
= cx
+ cw
+ infoPtr
->iMargin
;
306 HDC hClipDC
= GetDC(hwnd
);
307 HRGN hClipRgn
= CreateRectRgn(r
.left
, r
.top
, r
.right
, r
.bottom
);
308 SelectClipRgn(hClipDC
, hClipRgn
);
311 HDC hdcBitmap
= CreateCompatibleDC (hClipDC
);
312 SelectObject (hdcBitmap
, phdi
->hbm
);
313 BitBlt (hClipDC
, bx
, r
.top
+ ((INT
)rh
- bmp
.bmHeight
) / 2,
314 bmp
.bmWidth
, bmp
.bmHeight
, hdcBitmap
, 0, 0, SRCCOPY
);
315 DeleteDC (hdcBitmap
);
319 ImageList_DrawEx (infoPtr
->himl
, phdi
->iImage
, hClipDC
,
320 ix
, r
.top
+ ((INT
)rh
- infoPtr
->himl
->cy
) / 2,
321 infoPtr
->himl
->cx
, infoPtr
->himl
->cy
, CLR_DEFAULT
, CLR_DEFAULT
, 0);
324 DeleteObject(hClipRgn
);
328 if (((phdi
->fmt
& HDF_STRING
)
329 || (!(phdi
->fmt
& (HDF_OWNERDRAW
|HDF_STRING
|HDF_BITMAP
|
330 HDF_BITMAP_ON_RIGHT
|HDF_IMAGE
)))) /* no explicit format specified? */
331 && (phdi
->pszText
)) {
332 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
333 SetTextColor (hdc
, (bHotTrack
) ? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
336 DrawTextW (hdc
, phdi
->pszText
, -1,
337 &r
, DT_LEFT
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
338 if (oldBkMode
!= TRANSPARENT
)
339 SetBkMode(hdc
, oldBkMode
);
343 return phdi
->rect
.right
;
348 HEADER_Refresh (HWND hwnd
, HDC hdc
)
350 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
351 HFONT hFont
, hOldFont
;
357 /* get rect for the bar, adjusted for the border */
358 GetClientRect (hwnd
, &rect
);
360 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
361 hOldFont
= SelectObject (hdc
, hFont
);
363 /* draw Background */
364 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
365 FillRect(hdc
, &rect
, hbrBk
);
368 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
369 x
= HEADER_DrawItem (hwnd
, hdc
, HEADER_OrderToIndex(hwnd
,i
), FALSE
);
372 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
374 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
)
375 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
377 DrawEdge (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
380 SelectObject (hdc
, hOldFont
);
385 HEADER_RefreshItem (HWND hwnd
, HDC hdc
, INT iItem
)
387 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
388 HFONT hFont
, hOldFont
;
390 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
391 hOldFont
= SelectObject (hdc
, hFont
);
392 HEADER_DrawItem (hwnd
, hdc
, iItem
, FALSE
);
393 SelectObject (hdc
, hOldFont
);
398 HEADER_InternalHitTest (HWND hwnd
, LPPOINT lpPt
, UINT
*pFlags
, INT
*pItem
)
400 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
406 GetClientRect (hwnd
, &rect
);
410 if (PtInRect (&rect
, *lpPt
))
412 if (infoPtr
->uNumItem
== 0) {
413 *pFlags
|= HHT_NOWHERE
;
419 /* somewhere inside */
420 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
421 rect
= infoPtr
->items
[iCount
].rect
;
422 width
= rect
.right
- rect
.left
;
427 if (PtInRect (&rect
, *lpPt
)) {
428 if (width
<= 2 * DIVIDER_WIDTH
) {
429 *pFlags
|= HHT_ONHEADER
;
431 TRACE("ON HEADER %d\n", iCount
);
436 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
437 if (PtInRect (&rcTest
, *lpPt
)) {
439 *pFlags
|= HHT_ONDIVOPEN
;
441 TRACE("ON DIVOPEN %d\n", *pItem
);
445 *pFlags
|= HHT_ONDIVIDER
;
447 TRACE("ON DIVIDER %d\n", *pItem
);
453 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
454 if (PtInRect (&rcTest
, *lpPt
)) {
455 *pFlags
|= HHT_ONDIVIDER
;
457 TRACE("ON DIVIDER %d\n", *pItem
);
461 *pFlags
|= HHT_ONHEADER
;
463 TRACE("ON HEADER %d\n", iCount
);
468 /* check for last divider part (on nowhere) */
469 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
470 rect
.left
= rect
.right
;
471 rect
.right
+= DIVIDER_WIDTH
;
472 if (PtInRect (&rect
, *lpPt
)) {
474 *pFlags
|= HHT_ONDIVOPEN
;
475 *pItem
= infoPtr
->uNumItem
- 1;
476 TRACE("ON DIVOPEN %d\n", *pItem
);
480 *pFlags
|= HHT_ONDIVIDER
;
481 *pItem
= infoPtr
->uNumItem
-1;
482 TRACE("ON DIVIDER %d\n", *pItem
);
487 *pFlags
|= HHT_NOWHERE
;
494 if (lpPt
->x
< rect
.left
) {
496 *pFlags
|= HHT_TOLEFT
;
498 else if (lpPt
->x
> rect
.right
) {
500 *pFlags
|= HHT_TORIGHT
;
503 if (lpPt
->y
< rect
.top
) {
505 *pFlags
|= HHT_ABOVE
;
507 else if (lpPt
->y
> rect
.bottom
) {
509 *pFlags
|= HHT_BELOW
;
514 TRACE("flags=0x%X\n", *pFlags
);
520 HEADER_DrawTrackLine (HWND hwnd
, HDC hdc
, INT x
)
526 GetClientRect (hwnd
, &rect
);
528 hOldPen
= SelectObject (hdc
, GetStockObject (BLACK_PEN
));
529 oldRop
= SetROP2 (hdc
, R2_XORPEN
);
530 MoveToEx (hdc
, x
, rect
.top
, NULL
);
531 LineTo (hdc
, x
, rect
.bottom
);
532 SetROP2 (hdc
, oldRop
);
533 SelectObject (hdc
, hOldPen
);
538 HEADER_SendSimpleNotify (HWND hwnd
, UINT code
)
540 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
543 nmhdr
.hwndFrom
= hwnd
;
544 nmhdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
547 return (BOOL
)SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
548 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
552 HEADER_SendHeaderNotify (HWND hwnd
, UINT code
, INT iItem
, INT mask
)
554 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
558 nmhdr
.hdr
.hwndFrom
= hwnd
;
559 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
560 nmhdr
.hdr
.code
= code
;
563 nmhdr
.pitem
= &nmitem
;
565 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
566 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
567 nmitem
.pszText
= NULL
;
568 nmitem
.cchTextMax
= 0;
569 /* nmitem.pszText = infoPtr->items[iItem].pszText; */
570 /* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
571 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
572 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
573 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
574 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
576 return (BOOL
)SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
577 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
582 HEADER_SendClickNotify (HWND hwnd
, UINT code
, INT iItem
)
584 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
587 nmhdr
.hdr
.hwndFrom
= hwnd
;
588 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
589 nmhdr
.hdr
.code
= code
;
594 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
595 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
600 HEADER_CreateDragImage (HWND hwnd
, WPARAM wParam
)
602 FIXME("empty stub!\n");
608 HEADER_DeleteItem (HWND hwnd
, WPARAM wParam
)
610 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
611 INT iItem
= (INT
)wParam
;
613 TRACE("[iItem=%d]\n", iItem
);
615 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
618 if (infoPtr
->uNumItem
== 1) {
619 TRACE("Simple delete!\n");
620 if (infoPtr
->items
[0].pszText
)
621 Free (infoPtr
->items
[0].pszText
);
622 Free (infoPtr
->items
);
624 infoPtr
->uNumItem
= 0;
627 HEADER_ITEM
*oldItems
= infoPtr
->items
;
631 TRACE("Complex delete! [iItem=%d]\n", iItem
);
633 if (infoPtr
->items
[iItem
].pszText
)
634 Free (infoPtr
->items
[iItem
].pszText
);
635 iOrder
= infoPtr
->items
[iItem
].iOrder
;
638 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
639 /* pre delete copy */
641 memcpy (&infoPtr
->items
[0], &oldItems
[0],
642 iItem
* sizeof(HEADER_ITEM
));
645 /* post delete copy */
646 if (iItem
< infoPtr
->uNumItem
) {
647 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
648 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
651 /* Correct the orders */
652 for (i
=infoPtr
->uNumItem
, pItem
= infoPtr
->items
; i
; i
--, pItem
++)
654 if (pItem
->iOrder
> iOrder
)
660 HEADER_SetItemBounds (hwnd
);
662 InvalidateRect(hwnd
, NULL
, FALSE
);
669 HEADER_GetImageList (HWND hwnd
)
671 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
673 return (LRESULT
)infoPtr
->himl
;
678 HEADER_GetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
680 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
681 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
682 INT nItem
= (INT
)wParam
;
688 TRACE("[nItem=%d]\n", nItem
);
693 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
)) {
697 lpItem
= &infoPtr
->items
[nItem
];
700 if (phdi
->mask
& HDI_BITMAP
)
701 phdi
->hbm
= (lpItem
!= NULL
) ? lpItem
->hbm
: 0;
703 if (phdi
->mask
& HDI_FORMAT
)
704 phdi
->fmt
= (lpItem
!= NULL
) ? lpItem
->fmt
: 0;
706 if (phdi
->mask
& HDI_WIDTH
)
707 phdi
->cxy
= (lpItem
!= NULL
) ? lpItem
->cxy
: 0;
709 if (phdi
->mask
& HDI_LPARAM
)
710 phdi
->lParam
= (lpItem
!= NULL
) ? lpItem
->lParam
: 0;
712 if (phdi
->mask
& HDI_TEXT
) {
713 if (lpItem
== NULL
) {
716 else if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
718 WideCharToMultiByte (CP_ACP
, 0, lpItem
->pszText
, -1,
719 phdi
->pszText
, phdi
->cchTextMax
, NULL
, NULL
);
724 phdi
->pszText
= LPSTR_TEXTCALLBACKA
;
727 if (phdi
->mask
& HDI_IMAGE
)
728 phdi
->iImage
= (lpItem
!= NULL
) ? lpItem
->iImage
: 0;
730 if (phdi
->mask
& HDI_ORDER
)
731 phdi
->iOrder
= (lpItem
!= NULL
) ? lpItem
->iOrder
: 0;
738 HEADER_GetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
740 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
741 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
742 INT nItem
= (INT
)wParam
;
748 TRACE("[nItem=%d]\n", nItem
);
753 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
)) {
757 lpItem
= &infoPtr
->items
[nItem
];
760 if (phdi
->mask
& HDI_BITMAP
)
761 phdi
->hbm
= (lpItem
!= NULL
) ? lpItem
->hbm
: 0;
763 if (phdi
->mask
& HDI_FORMAT
)
764 phdi
->fmt
= (lpItem
!= NULL
) ? lpItem
->fmt
: 0;
766 if (phdi
->mask
& HDI_WIDTH
)
767 phdi
->cxy
= (lpItem
!= NULL
) ? lpItem
->cxy
: 0;
769 if (phdi
->mask
& HDI_LPARAM
)
770 phdi
->lParam
= (lpItem
!= NULL
) ? lpItem
->lParam
: 0;
772 if (phdi
->mask
& HDI_TEXT
) {
773 if (lpItem
== NULL
) {
776 else if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
778 lstrcpynW (phdi
->pszText
, lpItem
->pszText
, phdi
->cchTextMax
);
783 phdi
->pszText
= LPSTR_TEXTCALLBACKW
;
786 if (phdi
->mask
& HDI_IMAGE
)
787 phdi
->iImage
= (lpItem
!= NULL
) ? lpItem
->iImage
: 0;
789 if (phdi
->mask
& HDI_ORDER
)
790 phdi
->iOrder
= (lpItem
!= NULL
) ? lpItem
->iOrder
: 0;
796 inline static LRESULT
797 HEADER_GetItemCount (HWND hwnd
)
799 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
800 return infoPtr
->uNumItem
;
805 HEADER_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
807 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
808 INT iItem
= (INT
)wParam
;
809 LPRECT lpRect
= (LPRECT
)lParam
;
811 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
814 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
815 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
816 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
817 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
824 HEADER_GetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
827 LPINT order
= (LPINT
) lParam
;
828 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
830 if ((unsigned int)wParam
<infoPtr
->uNumItem
)
832 for (i
=0; i
<(int)wParam
; i
++)
833 *order
++=HEADER_OrderToIndex(hwnd
,i
);
838 HEADER_SetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
841 LPINT order
= (LPINT
) lParam
;
842 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
845 if ((unsigned int)wParam
<infoPtr
->uNumItem
)
847 for (i
=0; i
<(int)wParam
; i
++)
849 lpItem
= &infoPtr
->items
[*order
++];
852 infoPtr
->bRectsValid
=0;
853 InvalidateRect(hwnd
, NULL
, FALSE
);
857 inline static LRESULT
858 HEADER_GetUnicodeFormat (HWND hwnd
)
860 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
861 return infoPtr
->bUnicode
;
866 HEADER_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
868 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
870 HEADER_InternalHitTest (hwnd
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
872 if (phti
->flags
== HHT_NOWHERE
)
880 HEADER_InsertItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
882 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
883 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
884 INT nItem
= (INT
)wParam
;
889 if ((phdi
== NULL
) || (nItem
< 0))
892 if (nItem
> infoPtr
->uNumItem
)
893 nItem
= infoPtr
->uNumItem
;
895 iOrder
= (phdi
->mask
& HDI_ORDER
) ? phdi
->iOrder
: nItem
;
897 if (infoPtr
->uNumItem
== 0) {
898 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
));
902 HEADER_ITEM
*oldItems
= infoPtr
->items
;
905 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
907 memcpy (&infoPtr
->items
[1], &oldItems
[0],
908 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
912 /* pre insert copy */
914 memcpy (&infoPtr
->items
[0], &oldItems
[0],
915 nItem
* sizeof(HEADER_ITEM
));
918 /* post insert copy */
919 if (nItem
< infoPtr
->uNumItem
- 1) {
920 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
921 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
928 for (i
=0; i
< infoPtr
->uNumItem
; i
++)
930 if (infoPtr
->items
[i
].iOrder
>= iOrder
)
931 infoPtr
->items
[i
].iOrder
++;
934 lpItem
= &infoPtr
->items
[nItem
];
935 lpItem
->bDown
= FALSE
;
937 if (phdi
->mask
& HDI_WIDTH
)
938 lpItem
->cxy
= phdi
->cxy
;
940 if (phdi
->mask
& HDI_TEXT
) {
941 if (!phdi
->pszText
) /* null pointer check */
943 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
944 len
= MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, NULL
, 0);
945 lpItem
->pszText
= Alloc( len
*sizeof(WCHAR
) );
946 MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, lpItem
->pszText
, len
);
949 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
952 if (phdi
->mask
& HDI_FORMAT
)
953 lpItem
->fmt
= phdi
->fmt
;
955 if (lpItem
->fmt
== 0)
956 lpItem
->fmt
= HDF_LEFT
;
958 if (!(lpItem
->fmt
& HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
960 lpItem
->fmt
|= HDF_STRING
;
962 if (phdi
->mask
& HDI_BITMAP
)
963 lpItem
->hbm
= phdi
->hbm
;
965 if (phdi
->mask
& HDI_LPARAM
)
966 lpItem
->lParam
= phdi
->lParam
;
968 if (phdi
->mask
& HDI_IMAGE
)
969 lpItem
->iImage
= phdi
->iImage
;
971 lpItem
->iOrder
= iOrder
;
973 HEADER_SetItemBounds (hwnd
);
975 InvalidateRect(hwnd
, NULL
, FALSE
);
982 HEADER_InsertItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
984 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
985 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
986 INT nItem
= (INT
)wParam
;
991 if ((phdi
== NULL
) || (nItem
< 0))
994 if (nItem
> infoPtr
->uNumItem
)
995 nItem
= infoPtr
->uNumItem
;
997 iOrder
= (phdi
->mask
& HDI_ORDER
) ? phdi
->iOrder
: nItem
;
999 if (infoPtr
->uNumItem
== 0) {
1000 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
));
1001 infoPtr
->uNumItem
++;
1004 HEADER_ITEM
*oldItems
= infoPtr
->items
;
1006 infoPtr
->uNumItem
++;
1007 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
1009 memcpy (&infoPtr
->items
[1], &oldItems
[0],
1010 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
1014 /* pre insert copy */
1016 memcpy (&infoPtr
->items
[0], &oldItems
[0],
1017 nItem
* sizeof(HEADER_ITEM
));
1020 /* post insert copy */
1021 if (nItem
< infoPtr
->uNumItem
- 1) {
1022 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
1023 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
1030 for (i
=0; i
< infoPtr
->uNumItem
; i
++)
1032 if (infoPtr
->items
[i
].iOrder
>= iOrder
)
1033 infoPtr
->items
[i
].iOrder
++;
1036 lpItem
= &infoPtr
->items
[nItem
];
1037 lpItem
->bDown
= FALSE
;
1039 if (phdi
->mask
& HDI_WIDTH
)
1040 lpItem
->cxy
= phdi
->cxy
;
1042 if (phdi
->mask
& HDI_TEXT
) {
1043 WCHAR wide_null_char
= 0;
1044 if (!phdi
->pszText
) /* null pointer check */
1045 phdi
->pszText
= &wide_null_char
;
1046 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1047 len
= strlenW (phdi
->pszText
);
1048 lpItem
->pszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1049 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1052 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1055 if (phdi
->mask
& HDI_FORMAT
)
1056 lpItem
->fmt
= phdi
->fmt
;
1058 if (lpItem
->fmt
== 0)
1059 lpItem
->fmt
= HDF_LEFT
;
1061 if (!(lpItem
->fmt
&HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
1063 lpItem
->fmt
|= HDF_STRING
;
1065 if (phdi
->mask
& HDI_BITMAP
)
1066 lpItem
->hbm
= phdi
->hbm
;
1068 if (phdi
->mask
& HDI_LPARAM
)
1069 lpItem
->lParam
= phdi
->lParam
;
1071 if (phdi
->mask
& HDI_IMAGE
)
1072 lpItem
->iImage
= phdi
->iImage
;
1074 lpItem
->iOrder
= iOrder
;
1076 HEADER_SetItemBounds (hwnd
);
1078 InvalidateRect(hwnd
, NULL
, FALSE
);
1085 HEADER_Layout (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1087 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1088 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
1090 lpLayout
->pwpos
->hwnd
= hwnd
;
1091 lpLayout
->pwpos
->hwndInsertAfter
= 0;
1092 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
1093 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
1094 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
1095 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_HIDDEN
)
1096 lpLayout
->pwpos
->cy
= 0;
1098 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
1099 lpLayout
->prc
->top
+= infoPtr
->nHeight
;
1101 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
1103 TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
1104 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
1105 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
1107 infoPtr
->bRectsValid
= FALSE
;
1114 HEADER_SetImageList (HWND hwnd
, HIMAGELIST himl
)
1116 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1119 TRACE("(himl 0x%x)\n", (int)himl
);
1120 himlOld
= infoPtr
->himl
;
1121 infoPtr
->himl
= himl
;
1123 /* FIXME: Refresh needed??? */
1125 return (LRESULT
)himlOld
;
1130 HEADER_GetBitmapMargin(HWND hwnd
)
1132 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
1134 return infoPtr
->iMargin
;
1138 HEADER_SetBitmapMargin(HWND hwnd
, WPARAM wParam
)
1140 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1141 INT oldMargin
= infoPtr
->iMargin
;
1143 infoPtr
->iMargin
= (INT
)wParam
;
1149 HEADER_SetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1151 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1152 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
1153 INT nItem
= (INT
)wParam
;
1154 HEADER_ITEM
*lpItem
;
1158 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1161 TRACE("[nItem=%d]\n", nItem
);
1163 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, nItem
, phdi
->mask
))
1166 lpItem
= &infoPtr
->items
[nItem
];
1167 if (phdi
->mask
& HDI_BITMAP
)
1168 lpItem
->hbm
= phdi
->hbm
;
1170 if (phdi
->mask
& HDI_FORMAT
)
1171 lpItem
->fmt
= phdi
->fmt
;
1173 if (phdi
->mask
& HDI_LPARAM
)
1174 lpItem
->lParam
= phdi
->lParam
;
1176 if (phdi
->mask
& HDI_TEXT
) {
1177 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
1178 if (lpItem
->pszText
) {
1179 Free (lpItem
->pszText
);
1180 lpItem
->pszText
= NULL
;
1182 if (phdi
->pszText
) {
1183 INT len
= MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,NULL
,0);
1184 lpItem
->pszText
= Alloc( len
*sizeof(WCHAR
) );
1185 MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,lpItem
->pszText
,len
);
1189 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1192 if (phdi
->mask
& HDI_WIDTH
)
1193 lpItem
->cxy
= phdi
->cxy
;
1195 if (phdi
->mask
& HDI_IMAGE
)
1196 lpItem
->iImage
= phdi
->iImage
;
1198 if (phdi
->mask
& HDI_ORDER
)
1200 lpItem
->iOrder
= phdi
->iOrder
;
1203 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGEDA
, nItem
, phdi
->mask
);
1205 HEADER_SetItemBounds (hwnd
);
1207 InvalidateRect(hwnd
, NULL
, FALSE
);
1214 HEADER_SetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1216 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1217 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
1218 INT nItem
= (INT
)wParam
;
1219 HEADER_ITEM
*lpItem
;
1223 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1226 TRACE("[nItem=%d]\n", nItem
);
1228 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
))
1231 lpItem
= &infoPtr
->items
[nItem
];
1232 if (phdi
->mask
& HDI_BITMAP
)
1233 lpItem
->hbm
= phdi
->hbm
;
1235 if (phdi
->mask
& HDI_FORMAT
)
1236 lpItem
->fmt
= phdi
->fmt
;
1238 if (phdi
->mask
& HDI_LPARAM
)
1239 lpItem
->lParam
= phdi
->lParam
;
1241 if (phdi
->mask
& HDI_TEXT
) {
1242 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1243 if (lpItem
->pszText
) {
1244 Free (lpItem
->pszText
);
1245 lpItem
->pszText
= NULL
;
1247 if (phdi
->pszText
) {
1248 INT len
= strlenW (phdi
->pszText
);
1249 lpItem
->pszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1250 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1254 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1257 if (phdi
->mask
& HDI_WIDTH
)
1258 lpItem
->cxy
= phdi
->cxy
;
1260 if (phdi
->mask
& HDI_IMAGE
)
1261 lpItem
->iImage
= phdi
->iImage
;
1263 if (phdi
->mask
& HDI_ORDER
)
1265 lpItem
->iOrder
= phdi
->iOrder
;
1268 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDW
, nItem
, phdi
->mask
);
1270 HEADER_SetItemBounds (hwnd
);
1272 InvalidateRect(hwnd
, NULL
, FALSE
);
1277 inline static LRESULT
1278 HEADER_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
)
1280 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1281 BOOL bTemp
= infoPtr
->bUnicode
;
1283 infoPtr
->bUnicode
= (BOOL
)wParam
;
1290 HEADER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1292 HEADER_INFO
*infoPtr
;
1297 infoPtr
= (HEADER_INFO
*)Alloc (sizeof(HEADER_INFO
));
1298 SetWindowLongPtrW (hwnd
, 0, (DWORD_PTR
)infoPtr
);
1300 infoPtr
->hwndNotify
= ((LPCREATESTRUCTA
)lParam
)->hwndParent
;
1301 infoPtr
->uNumItem
= 0;
1304 infoPtr
->bRectsValid
= FALSE
;
1305 infoPtr
->hcurArrow
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1306 infoPtr
->hcurDivider
= LoadCursorW (COMCTL32_hModule
, MAKEINTRESOURCEW(IDC_DIVIDER
));
1307 infoPtr
->hcurDivopen
= LoadCursorW (COMCTL32_hModule
, MAKEINTRESOURCEW(IDC_DIVIDEROPEN
));
1308 infoPtr
->bPressed
= FALSE
;
1309 infoPtr
->bTracking
= FALSE
;
1310 infoPtr
->iMoveItem
= 0;
1312 infoPtr
->iHotItem
= -1;
1313 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
1314 infoPtr
->iMargin
= 3*GetSystemMetrics(SM_CXEDGE
);
1315 infoPtr
->nNotifyFormat
=
1316 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
1319 hOldFont
= SelectObject (hdc
, GetStockObject (SYSTEM_FONT
));
1320 GetTextMetricsW (hdc
, &tm
);
1321 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1322 SelectObject (hdc
, hOldFont
);
1330 HEADER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1332 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1333 HEADER_ITEM
*lpItem
;
1336 if (infoPtr
->items
) {
1337 lpItem
= infoPtr
->items
;
1338 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
1339 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
))
1340 Free (lpItem
->pszText
);
1342 Free (infoPtr
->items
);
1346 ImageList_Destroy (infoPtr
->himl
);
1348 SetWindowLongPtrW (hwnd
, 0, 0);
1354 static inline LRESULT
1355 HEADER_GetFont (HWND hwnd
)
1357 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1359 return (LRESULT
)infoPtr
->hFont
;
1364 HEADER_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1370 pt
.x
= (INT
)LOWORD(lParam
);
1371 pt
.y
= (INT
)HIWORD(lParam
);
1372 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1374 if ((GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
1375 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMDBLCLICKA
, nItem
,0);
1376 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
1377 HEADER_SendHeaderNotify (hwnd
, HDN_DIVIDERDBLCLICKA
, nItem
,0);
1384 HEADER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1386 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1387 DWORD dwStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
1393 pt
.x
= (INT
)LOWORD(lParam
);
1394 pt
.y
= (INT
)HIWORD(lParam
);
1395 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1397 if ((dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
1399 infoPtr
->bCaptured
= TRUE
;
1400 infoPtr
->bPressed
= TRUE
;
1401 infoPtr
->iMoveItem
= nItem
;
1403 infoPtr
->items
[nItem
].bDown
= TRUE
;
1405 /* Send WM_CUSTOMDRAW */
1407 HEADER_RefreshItem (hwnd
, hdc
, nItem
);
1408 ReleaseDC (hwnd
, hdc
);
1410 TRACE("Pressed item %d!\n", nItem
);
1412 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
1413 if (!(HEADER_SendHeaderNotify (hwnd
, HDN_BEGINTRACKA
, nItem
,0))) {
1415 infoPtr
->bCaptured
= TRUE
;
1416 infoPtr
->bTracking
= TRUE
;
1417 infoPtr
->iMoveItem
= nItem
;
1418 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
1419 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
1421 if (!(dwStyle
& HDS_FULLDRAG
)) {
1422 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
1424 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1425 ReleaseDC (hwnd
, hdc
);
1428 TRACE("Begin tracking item %d!\n", nItem
);
1437 HEADER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1439 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1441 *DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
1448 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1449 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1450 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1452 if (infoPtr
->bPressed
) {
1453 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1454 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1456 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1457 ReleaseDC (hwnd
, hdc
);
1459 HEADER_SendClickNotify (hwnd
, HDN_ITEMCLICKA
, infoPtr
->iMoveItem
);
1461 else if (flags
== HHT_ONHEADER
)
1463 HEADER_ITEM
*lpItem
;
1464 INT newindex
= HEADER_IndexToOrder(hwnd
,nItem
);
1465 INT oldindex
= HEADER_IndexToOrder(hwnd
,infoPtr
->iMoveItem
);
1467 TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
1468 infoPtr
->iMoveItem
,oldindex
,nItem
,newindex
);
1469 lpItem
= &infoPtr
->items
[nItem
];
1470 lpItem
->iOrder
=oldindex
;
1472 lpItem
= &infoPtr
->items
[infoPtr
->iMoveItem
];
1473 lpItem
->iOrder
= newindex
;
1475 infoPtr
->bRectsValid
= FALSE
;
1476 InvalidateRect(hwnd
, NULL
, FALSE
);
1477 /* FIXME: Should some WM_NOTIFY be sent */
1480 TRACE("Released item %d!\n", infoPtr
->iMoveItem
);
1481 infoPtr
->bPressed
= FALSE
;
1483 else if (infoPtr
->bTracking
) {
1484 TRACE("End tracking item %d!\n", infoPtr
->iMoveItem
);
1485 infoPtr
->bTracking
= FALSE
;
1487 HEADER_SendHeaderNotify (hwnd
, HDN_ENDTRACKA
, infoPtr
->iMoveItem
,HDI_WIDTH
);
1490 * we want to do this even for HDS_FULLDRAG because this is where
1491 * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications
1493 * if (!(dwStyle & HDS_FULLDRAG)) {
1497 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1498 ReleaseDC (hwnd
, hdc
);
1499 if (HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1501 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1504 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1507 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1510 HEADER_SetItemBounds (hwnd
);
1511 InvalidateRect(hwnd
, NULL
, TRUE
);
1512 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1518 if (infoPtr
->bCaptured
) {
1519 infoPtr
->bCaptured
= FALSE
;
1521 HEADER_SendSimpleNotify (hwnd
, NM_RELEASEDCAPTURE
);
1529 HEADER_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1531 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1536 return infoPtr
->nNotifyFormat
;
1539 infoPtr
->nNotifyFormat
=
1540 SendMessageW ((HWND
)wParam
, WM_NOTIFYFORMAT
,
1541 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1542 return infoPtr
->nNotifyFormat
;
1550 HEADER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1552 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1553 DWORD dwStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
1559 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1560 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1561 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1563 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1564 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1565 infoPtr
->iHotItem
= nItem
;
1567 infoPtr
->iHotItem
= -1;
1568 InvalidateRect(hwnd
, NULL
, FALSE
);
1571 if (infoPtr
->bCaptured
) {
1572 if (infoPtr
->bPressed
) {
1573 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1574 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1576 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1578 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1579 ReleaseDC (hwnd
, hdc
);
1581 TRACE("Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1583 else if (infoPtr
->bTracking
) {
1584 if (dwStyle
& HDS_FULLDRAG
) {
1585 if (HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1587 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1590 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1591 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1593 HEADER_SetItemBounds (hwnd
);
1597 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1598 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1599 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1600 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1601 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1602 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1603 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1604 ReleaseDC (hwnd
, hdc
);
1605 HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1608 TRACE("Tracking item %d!\n", infoPtr
->iMoveItem
);
1612 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1613 FIXME("hot track support!\n");
1621 HEADER_Paint (HWND hwnd
, WPARAM wParam
)
1626 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1627 HEADER_Refresh (hwnd
, hdc
);
1629 EndPaint (hwnd
, &ps
);
1635 HEADER_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1640 pt
.x
= LOWORD(lParam
);
1641 pt
.y
= HIWORD(lParam
);
1643 /* Send a Notify message */
1644 bRet
= HEADER_SendSimpleNotify (hwnd
, NM_RCLICK
);
1646 /* Change to screen coordinate for WM_CONTEXTMENU */
1647 ClientToScreen(hwnd
, &pt
);
1649 /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */
1650 SendMessageW( hwnd
, WM_CONTEXTMENU
, (WPARAM
) hwnd
, MAKELPARAM(pt
.x
, pt
.y
));
1657 HEADER_SetCursor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1659 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1664 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1667 ScreenToClient (hwnd
, &pt
);
1669 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1671 if (flags
== HHT_ONDIVIDER
)
1672 SetCursor (infoPtr
->hcurDivider
);
1673 else if (flags
== HHT_ONDIVOPEN
)
1674 SetCursor (infoPtr
->hcurDivopen
);
1676 SetCursor (infoPtr
->hcurArrow
);
1683 HEADER_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1685 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1687 HFONT hFont
, hOldFont
;
1690 infoPtr
->hFont
= (HFONT
)wParam
;
1692 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
1695 hOldFont
= SelectObject (hdc
, hFont
);
1696 GetTextMetricsW (hdc
, &tm
);
1697 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1698 SelectObject (hdc
, hOldFont
);
1701 infoPtr
->bRectsValid
= FALSE
;
1704 InvalidateRect(hwnd
, NULL
, FALSE
);
1711 static LRESULT WINAPI
1712 HEADER_WindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1714 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1715 if (!HEADER_GetInfoPtr (hwnd
) && (msg
!= WM_CREATE
))
1716 return DefWindowProcW (hwnd
, msg
, wParam
, lParam
);
1718 /* case HDM_CLEARFILTER: */
1720 case HDM_CREATEDRAGIMAGE
:
1721 return HEADER_CreateDragImage (hwnd
, wParam
);
1723 case HDM_DELETEITEM
:
1724 return HEADER_DeleteItem (hwnd
, wParam
);
1726 /* case HDM_EDITFILTER: */
1728 case HDM_GETBITMAPMARGIN
:
1729 return HEADER_GetBitmapMargin(hwnd
);
1731 case HDM_GETIMAGELIST
:
1732 return HEADER_GetImageList (hwnd
);
1735 return HEADER_GetItemA (hwnd
, wParam
, lParam
);
1738 return HEADER_GetItemW (hwnd
, wParam
, lParam
);
1740 case HDM_GETITEMCOUNT
:
1741 return HEADER_GetItemCount (hwnd
);
1743 case HDM_GETITEMRECT
:
1744 return HEADER_GetItemRect (hwnd
, wParam
, lParam
);
1746 case HDM_GETORDERARRAY
:
1747 return HEADER_GetOrderArray(hwnd
, wParam
, lParam
);
1749 case HDM_GETUNICODEFORMAT
:
1750 return HEADER_GetUnicodeFormat (hwnd
);
1753 return HEADER_HitTest (hwnd
, wParam
, lParam
);
1755 case HDM_INSERTITEMA
:
1756 return HEADER_InsertItemA (hwnd
, wParam
, lParam
);
1758 case HDM_INSERTITEMW
:
1759 return HEADER_InsertItemW (hwnd
, wParam
, lParam
);
1762 return HEADER_Layout (hwnd
, wParam
, lParam
);
1764 case HDM_ORDERTOINDEX
:
1765 return HEADER_OrderToIndex(hwnd
, wParam
);
1767 case HDM_SETBITMAPMARGIN
:
1768 return HEADER_SetBitmapMargin(hwnd
, wParam
);
1770 /* case HDM_SETFILTERCHANGETIMEOUT: */
1772 /* case HDM_SETHOTDIVIDER: */
1774 case HDM_SETIMAGELIST
:
1775 return HEADER_SetImageList (hwnd
, (HIMAGELIST
)lParam
);
1778 return HEADER_SetItemA (hwnd
, wParam
, lParam
);
1781 return HEADER_SetItemW (hwnd
, wParam
, lParam
);
1783 case HDM_SETORDERARRAY
:
1784 return HEADER_SetOrderArray(hwnd
, wParam
, lParam
);
1786 case HDM_SETUNICODEFORMAT
:
1787 return HEADER_SetUnicodeFormat (hwnd
, wParam
);
1790 return HEADER_Create (hwnd
, wParam
, lParam
);
1793 return HEADER_Destroy (hwnd
, wParam
, lParam
);
1799 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1802 return HEADER_GetFont (hwnd
);
1804 case WM_LBUTTONDBLCLK
:
1805 return HEADER_LButtonDblClk (hwnd
, wParam
, lParam
);
1807 case WM_LBUTTONDOWN
:
1808 return HEADER_LButtonDown (hwnd
, wParam
, lParam
);
1811 return HEADER_LButtonUp (hwnd
, wParam
, lParam
);
1814 return HEADER_MouseMove (hwnd
, wParam
, lParam
);
1816 case WM_NOTIFYFORMAT
:
1817 return HEADER_NotifyFormat (hwnd
, wParam
, lParam
);
1820 return HEADER_Size (hwnd
, wParam
);
1823 return HEADER_Paint (hwnd
, wParam
);
1826 return HEADER_RButtonUp (hwnd
, wParam
, lParam
);
1829 return HEADER_SetCursor (hwnd
, wParam
, lParam
);
1832 return HEADER_SetFont (hwnd
, wParam
, lParam
);
1835 if ((msg
>= WM_USER
) && (msg
< WM_APP
))
1836 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1837 msg
, wParam
, lParam
);
1838 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1844 HEADER_Register (void)
1848 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
1849 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1850 wndClass
.lpfnWndProc
= HEADER_WindowProc
;
1851 wndClass
.cbClsExtra
= 0;
1852 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1853 wndClass
.hCursor
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1854 wndClass
.lpszClassName
= WC_HEADERW
;
1856 RegisterClassW (&wndClass
);
1861 HEADER_Unregister (void)
1863 UnregisterClassW (WC_HEADERW
, NULL
);