4 * Copyright 1998 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
8 * - Imagelist support (partially).
9 * - Callback items (under construction).
10 * - Hottrack support (partially).
11 * - Custom draw support (including Notifications).
12 * - Drag and Drop support (including Notifications).
14 * - Use notification format
17 * - Little flaw when drawing a bitmap on the right side of the text.
23 #include "wine/unicode.h"
26 #include "imagelist.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(header
);
39 INT iOrder
; /* see documentation of HD_ITEM */
41 BOOL bDown
; /* is item pressed? (used for drawing) */
42 RECT rect
; /* bounding rectangle of the item */
48 HWND hwndNotify
; /* Owner window to send notifications to */
49 INT nNotifyFormat
; /* format used for WM_NOTIFY messages */
50 UINT uNumItem
; /* number of items (columns) */
51 INT nHeight
; /* height of the header (pixels) */
52 HFONT hFont
; /* handle to the current font */
53 HCURSOR hcurArrow
; /* handle to the arrow cursor */
54 HCURSOR hcurDivider
; /* handle to a cursor (used over dividers) <-|-> */
55 HCURSOR hcurDivopen
; /* handle to a cursor (used over dividers) <-||-> */
56 BOOL bCaptured
; /* Is the mouse captured? */
57 BOOL bPressed
; /* Is a header item pressed (down)? */
58 BOOL bTracking
; /* Is in tracking mode? */
59 BOOL bUnicode
; /* Unicode flag */
60 INT iMoveItem
; /* index of tracked item. (Tracking mode) */
61 INT xTrackOffset
; /* distance between the right side of the tracked item and the cursor */
62 INT xOldTrack
; /* track offset (see above) after the last WM_MOUSEMOVE */
63 INT nOldWidth
; /* width of a sizing item after the last WM_MOUSEMOVE */
64 INT iHotItem
; /* index of hot item (cursor is over this item) */
66 HIMAGELIST himl
; /* handle to a image list (may be 0) */
67 HEADER_ITEM
*items
; /* pointer to array of HEADER_ITEM's */
68 BOOL bRectsValid
; /* validity flag for bounding rectangles */
73 #define DIVIDER_WIDTH 10
75 #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongA(hwnd,0))
79 HEADER_IndexToOrder (HWND hwnd
, INT iItem
)
81 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
82 HEADER_ITEM
*lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[iItem
];
83 return lpItem
->iOrder
;
88 HEADER_OrderToIndex(HWND hwnd
, WPARAM wParam
)
90 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
91 INT i
,iorder
= (INT
)wParam
;
94 if ((iorder
<0) || iorder
>infoPtr
->uNumItem
)
96 for (i
=0; i
<infoPtr
->uNumItem
; i
++)
97 if (HEADER_IndexToOrder(hwnd
,i
) == iorder
)
103 HEADER_SetItemBounds (HWND hwnd
)
105 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
110 infoPtr
->bRectsValid
= TRUE
;
112 if (infoPtr
->uNumItem
== 0)
115 GetClientRect (hwnd
, &rect
);
118 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
119 phdi
= &infoPtr
->items
[HEADER_OrderToIndex(hwnd
,i
)];
120 phdi
->rect
.top
= rect
.top
;
121 phdi
->rect
.bottom
= rect
.bottom
;
123 phdi
->rect
.right
= phdi
->rect
.left
+ ((phdi
->cxy
>0)?phdi
->cxy
:0);
124 x
= phdi
->rect
.right
;
129 HEADER_Size (HWND hwnd
, WPARAM wParam
)
131 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
133 infoPtr
->bRectsValid
= FALSE
;
140 HEADER_DrawItem (HWND hwnd
, HDC hdc
, INT iItem
, BOOL bHotTrack
)
142 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
143 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
147 TRACE("DrawItem(iItem %d bHotTrack %d)\n", iItem
, bHotTrack
);
149 if (!infoPtr
->bRectsValid
)
150 HEADER_SetItemBounds(hwnd
);
153 if (r
.right
- r
.left
== 0)
154 return phdi
->rect
.right
;
156 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) {
158 DrawEdge (hdc
, &r
, BDR_RAISEDOUTER
,
159 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
164 DrawEdge (hdc
, &r
, EDGE_RAISED
,
165 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
168 DrawEdge (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
170 if (phdi
->fmt
& HDF_OWNERDRAW
) {
172 dis
.CtlType
= ODT_HEADER
;
173 dis
.CtlID
= GetWindowLongA (hwnd
, GWL_ID
);
175 dis
.itemAction
= ODA_DRAWENTIRE
;
176 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
180 dis
.itemData
= phdi
->lParam
;
181 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
182 SendMessageA (GetParent (hwnd
), WM_DRAWITEM
,
183 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
184 if (oldBkMode
!= TRANSPARENT
)
185 SetBkMode(hdc
, oldBkMode
);
188 UINT uTextJustify
= DT_LEFT
;
190 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
191 uTextJustify
= DT_CENTER
;
192 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
193 uTextJustify
= DT_RIGHT
;
195 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->hbm
)) {
198 INT yD
, yS
, cx
, cy
, rx
, ry
;
200 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
202 ry
= r
.bottom
- r
.top
;
203 rx
= r
.right
- r
.left
;
205 if (ry
>= bmp
.bmHeight
) {
207 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
213 yS
= (bmp
.bmHeight
- ry
) / 2;
217 if (rx
>= bmp
.bmWidth
+ 6) {
224 hdcBitmap
= CreateCompatibleDC (hdc
);
225 SelectObject (hdcBitmap
, phdi
->hbm
);
226 BitBlt (hdc
, r
.left
+ 3, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
227 DeleteDC (hdcBitmap
);
229 r
.left
+= (bmp
.bmWidth
+ 3);
233 if ((phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
236 INT xD
, yD
, yS
, cx
, cy
, rx
, ry
, tx
;
239 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
242 DrawTextW (hdc
, phdi
->pszText
, -1,
243 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
244 tx
= textRect
.right
- textRect
.left
;
245 ry
= r
.bottom
- r
.top
;
246 rx
= r
.right
- r
.left
;
248 if (ry
>= bmp
.bmHeight
) {
250 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
256 yS
= (bmp
.bmHeight
- ry
) / 2;
260 if (r
.left
+ tx
+ bmp
.bmWidth
+ 9 <= r
.right
) {
262 xD
= r
.left
+ tx
+ 6;
265 if (rx
>= bmp
.bmWidth
+ 6) {
267 xD
= r
.right
- bmp
.bmWidth
- 3;
277 hdcBitmap
= CreateCompatibleDC (hdc
);
278 SelectObject (hdcBitmap
, phdi
->hbm
);
279 BitBlt (hdc
, xD
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
280 DeleteDC (hdcBitmap
);
283 if ((phdi
->fmt
& HDF_IMAGE
) && (infoPtr
->himl
)) {
285 /* FIXME: (r.bottom- (infoPtr->himl->cy))/2 should horicontal center the image
286 It looks like it doesn't work as expected*/
287 ImageList_Draw (infoPtr
->himl
, phdi
->iImage
,hdc
,r
.left
, (r
.bottom
- (infoPtr
->himl
->cy
))/2,0);
288 r
.left
+= infoPtr
->himl
->cx
;
291 if (((phdi
->fmt
& HDF_STRING
)
292 || (!(phdi
->fmt
& (HDF_OWNERDRAW
|HDF_STRING
|HDF_BITMAP
|
293 HDF_BITMAP_ON_RIGHT
|HDF_IMAGE
)))) /* no explicit format specified? */
294 && (phdi
->pszText
)) {
295 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
298 SetTextColor (hdc
, (bHotTrack
) ? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
299 DrawTextW (hdc
, phdi
->pszText
, -1,
300 &r
, uTextJustify
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
301 if (oldBkMode
!= TRANSPARENT
)
302 SetBkMode(hdc
, oldBkMode
);
306 return phdi
->rect
.right
;
311 HEADER_Refresh (HWND hwnd
, HDC hdc
)
313 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
314 HFONT hFont
, hOldFont
;
319 /* get rect for the bar, adjusted for the border */
320 GetClientRect (hwnd
, &rect
);
322 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
323 hOldFont
= SelectObject (hdc
, hFont
);
325 /* draw Background */
326 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
327 FillRect(hdc
, &rect
, hbrBk
);
330 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
331 x
= HEADER_DrawItem (hwnd
, hdc
, HEADER_OrderToIndex(hwnd
,i
), FALSE
);
334 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
336 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
)
337 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
339 DrawEdge (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
342 SelectObject (hdc
, hOldFont
);
347 HEADER_RefreshItem (HWND hwnd
, HDC hdc
, INT iItem
)
349 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
350 HFONT hFont
, hOldFont
;
352 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
353 hOldFont
= SelectObject (hdc
, hFont
);
354 HEADER_DrawItem (hwnd
, hdc
, iItem
, FALSE
);
355 SelectObject (hdc
, hOldFont
);
360 HEADER_InternalHitTest (HWND hwnd
, LPPOINT lpPt
, UINT
*pFlags
, INT
*pItem
)
362 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
367 GetClientRect (hwnd
, &rect
);
371 if (PtInRect (&rect
, *lpPt
))
373 if (infoPtr
->uNumItem
== 0) {
374 *pFlags
|= HHT_NOWHERE
;
380 /* somewhere inside */
381 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
382 rect
= infoPtr
->items
[iCount
].rect
;
383 width
= rect
.right
- rect
.left
;
388 if (PtInRect (&rect
, *lpPt
)) {
389 if (width
<= 2 * DIVIDER_WIDTH
) {
390 *pFlags
|= HHT_ONHEADER
;
392 TRACE("ON HEADER %d\n", iCount
);
397 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
398 if (PtInRect (&rcTest
, *lpPt
)) {
400 *pFlags
|= HHT_ONDIVOPEN
;
402 TRACE("ON DIVOPEN %d\n", *pItem
);
406 *pFlags
|= HHT_ONDIVIDER
;
408 TRACE("ON DIVIDER %d\n", *pItem
);
414 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
415 if (PtInRect (&rcTest
, *lpPt
)) {
416 *pFlags
|= HHT_ONDIVIDER
;
418 TRACE("ON DIVIDER %d\n", *pItem
);
422 *pFlags
|= HHT_ONHEADER
;
424 TRACE("ON HEADER %d\n", iCount
);
429 /* check for last divider part (on nowhere) */
430 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
431 rect
.left
= rect
.right
;
432 rect
.right
+= DIVIDER_WIDTH
;
433 if (PtInRect (&rect
, *lpPt
)) {
435 *pFlags
|= HHT_ONDIVOPEN
;
436 *pItem
= infoPtr
->uNumItem
- 1;
437 TRACE("ON DIVOPEN %d\n", *pItem
);
441 *pFlags
|= HHT_ONDIVIDER
;
442 *pItem
= infoPtr
->uNumItem
-1;
443 TRACE("ON DIVIDER %d\n", *pItem
);
448 *pFlags
|= HHT_NOWHERE
;
455 if (lpPt
->x
< rect
.left
) {
457 *pFlags
|= HHT_TOLEFT
;
459 else if (lpPt
->x
> rect
.right
) {
461 *pFlags
|= HHT_TORIGHT
;
464 if (lpPt
->y
< rect
.top
) {
466 *pFlags
|= HHT_ABOVE
;
468 else if (lpPt
->y
> rect
.bottom
) {
470 *pFlags
|= HHT_BELOW
;
475 TRACE("flags=0x%X\n", *pFlags
);
481 HEADER_DrawTrackLine (HWND hwnd
, HDC hdc
, INT x
)
487 GetClientRect (hwnd
, &rect
);
489 hOldPen
= SelectObject (hdc
, GetStockObject (BLACK_PEN
));
490 oldRop
= SetROP2 (hdc
, R2_XORPEN
);
491 MoveToEx (hdc
, x
, rect
.top
, NULL
);
492 LineTo (hdc
, x
, rect
.bottom
);
493 SetROP2 (hdc
, oldRop
);
494 SelectObject (hdc
, hOldPen
);
499 HEADER_SendSimpleNotify (HWND hwnd
, UINT code
)
501 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
504 nmhdr
.hwndFrom
= hwnd
;
505 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
508 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
509 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
513 HEADER_SendHeaderNotify (HWND hwnd
, UINT code
, INT iItem
, INT mask
)
515 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
519 nmhdr
.hdr
.hwndFrom
= hwnd
;
520 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
521 nmhdr
.hdr
.code
= code
;
524 nmhdr
.pitem
= &nmitem
;
526 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
527 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
528 nmitem
.pszText
= NULL
;
529 nmitem
.cchTextMax
= 0;
530 /* nmitem.pszText = infoPtr->items[iItem].pszText; */
531 /* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
532 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
533 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
534 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
535 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
537 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
538 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
543 HEADER_SendClickNotify (HWND hwnd
, UINT code
, INT iItem
)
545 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
548 nmhdr
.hdr
.hwndFrom
= hwnd
;
549 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
550 nmhdr
.hdr
.code
= code
;
555 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
556 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
561 HEADER_CreateDragImage (HWND hwnd
, WPARAM wParam
)
563 FIXME("empty stub!\n");
569 HEADER_DeleteItem (HWND hwnd
, WPARAM wParam
)
571 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
572 INT iItem
= (INT
)wParam
;
574 TRACE("[iItem=%d]\n", iItem
);
576 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
579 if (infoPtr
->uNumItem
== 1) {
580 TRACE("Simple delete!\n");
581 if (infoPtr
->items
[0].pszText
)
582 COMCTL32_Free (infoPtr
->items
[0].pszText
);
583 COMCTL32_Free (infoPtr
->items
);
585 infoPtr
->uNumItem
= 0;
588 HEADER_ITEM
*oldItems
= infoPtr
->items
;
589 TRACE("Complex delete! [iItem=%d]\n", iItem
);
591 if (infoPtr
->items
[iItem
].pszText
)
592 COMCTL32_Free (infoPtr
->items
[iItem
].pszText
);
595 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
596 /* pre delete copy */
598 memcpy (&infoPtr
->items
[0], &oldItems
[0],
599 iItem
* sizeof(HEADER_ITEM
));
602 /* post delete copy */
603 if (iItem
< infoPtr
->uNumItem
) {
604 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
605 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
608 COMCTL32_Free (oldItems
);
611 HEADER_SetItemBounds (hwnd
);
613 InvalidateRect(hwnd
, NULL
, FALSE
);
620 HEADER_GetImageList (HWND hwnd
)
622 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
624 return (LRESULT
)infoPtr
->himl
;
629 HEADER_GetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
631 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
632 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
633 INT nItem
= (INT
)wParam
;
638 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
641 TRACE("[nItem=%d]\n", nItem
);
646 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
647 if (phdi
->mask
& HDI_BITMAP
)
648 phdi
->hbm
= lpItem
->hbm
;
650 if (phdi
->mask
& HDI_FORMAT
)
651 phdi
->fmt
= lpItem
->fmt
;
653 if (phdi
->mask
& HDI_WIDTH
)
654 phdi
->cxy
= lpItem
->cxy
;
656 if (phdi
->mask
& HDI_LPARAM
)
657 phdi
->lParam
= lpItem
->lParam
;
659 if (phdi
->mask
& HDI_TEXT
) {
660 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
662 WideCharToMultiByte (CP_ACP
, 0, lpItem
->pszText
, -1,
663 phdi
->pszText
, phdi
->cchTextMax
, NULL
, NULL
);
668 phdi
->pszText
= LPSTR_TEXTCALLBACKA
;
671 if (phdi
->mask
& HDI_IMAGE
)
672 phdi
->iImage
= lpItem
->iImage
;
674 if (phdi
->mask
& HDI_ORDER
)
675 phdi
->iOrder
= lpItem
->iOrder
;
682 HEADER_GetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
684 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
685 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
686 INT nItem
= (INT
)wParam
;
691 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
694 TRACE("[nItem=%d]\n", nItem
);
699 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
700 if (phdi
->mask
& HDI_BITMAP
)
701 phdi
->hbm
= lpItem
->hbm
;
703 if (phdi
->mask
& HDI_FORMAT
)
704 phdi
->fmt
= lpItem
->fmt
;
706 if (phdi
->mask
& HDI_WIDTH
)
707 phdi
->cxy
= lpItem
->cxy
;
709 if (phdi
->mask
& HDI_LPARAM
)
710 phdi
->lParam
= lpItem
->lParam
;
712 if (phdi
->mask
& HDI_TEXT
) {
713 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
715 lstrcpynW (phdi
->pszText
, lpItem
->pszText
, phdi
->cchTextMax
);
720 phdi
->pszText
= LPSTR_TEXTCALLBACKW
;
723 if (phdi
->mask
& HDI_IMAGE
)
724 phdi
->iImage
= lpItem
->iImage
;
726 if (phdi
->mask
& HDI_ORDER
)
727 phdi
->iOrder
= lpItem
->iOrder
;
733 inline static LRESULT
734 HEADER_GetItemCount (HWND hwnd
)
736 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
737 return infoPtr
->uNumItem
;
742 HEADER_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
744 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
745 INT iItem
= (INT
)wParam
;
746 LPRECT lpRect
= (LPRECT
)lParam
;
748 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
751 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
752 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
753 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
754 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
761 HEADER_GetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
764 LPINT order
= (LPINT
) lParam
;
765 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
767 if ((int)wParam
<infoPtr
->uNumItem
)
769 for (i
=0; i
<(int)wParam
; i
++)
770 *order
++=HEADER_OrderToIndex(hwnd
,i
);
775 HEADER_SetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
778 LPINT order
= (LPINT
) lParam
;
779 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
782 if ((int)wParam
<infoPtr
->uNumItem
)
784 for (i
=0; i
<(int)wParam
; i
++)
786 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[*order
++];
789 infoPtr
->bRectsValid
=0;
790 InvalidateRect(hwnd
, NULL
, FALSE
);
794 inline static LRESULT
795 HEADER_GetUnicodeFormat (HWND hwnd
)
797 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
798 return infoPtr
->bUnicode
;
803 HEADER_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
805 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
807 HEADER_InternalHitTest (hwnd
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
809 if (phti
->flags
== HHT_ONHEADER
)
817 HEADER_InsertItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
819 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
820 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
821 INT nItem
= (INT
)wParam
;
825 if ((phdi
== NULL
) || (nItem
< 0))
828 if (nItem
> infoPtr
->uNumItem
)
829 nItem
= infoPtr
->uNumItem
;
831 if (infoPtr
->uNumItem
== 0) {
832 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
));
836 HEADER_ITEM
*oldItems
= infoPtr
->items
;
839 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
841 memcpy (&infoPtr
->items
[1], &oldItems
[0],
842 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
846 /* pre insert copy */
848 memcpy (&infoPtr
->items
[0], &oldItems
[0],
849 nItem
* sizeof(HEADER_ITEM
));
852 /* post insert copy */
853 if (nItem
< infoPtr
->uNumItem
- 1) {
854 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
855 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
859 COMCTL32_Free (oldItems
);
862 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
863 lpItem
->bDown
= FALSE
;
865 if (phdi
->mask
& HDI_WIDTH
)
866 lpItem
->cxy
= phdi
->cxy
;
868 if (phdi
->mask
& HDI_TEXT
) {
869 if (!phdi
->pszText
) /* null pointer check */
871 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
872 len
= MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, NULL
, 0);
873 lpItem
->pszText
= COMCTL32_Alloc( len
*sizeof(WCHAR
) );
874 MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, lpItem
->pszText
, len
);
877 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
880 if (phdi
->mask
& HDI_FORMAT
)
881 lpItem
->fmt
= phdi
->fmt
;
883 if (lpItem
->fmt
== 0)
884 lpItem
->fmt
= HDF_LEFT
;
886 if (!(lpItem
->fmt
&HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
888 lpItem
->fmt
|= HDF_STRING
;
890 if (phdi
->mask
& HDI_BITMAP
)
891 lpItem
->hbm
= phdi
->hbm
;
893 if (phdi
->mask
& HDI_LPARAM
)
894 lpItem
->lParam
= phdi
->lParam
;
896 if (phdi
->mask
& HDI_IMAGE
)
897 lpItem
->iImage
= phdi
->iImage
;
899 if (phdi
->mask
& HDI_ORDER
)
901 lpItem
->iOrder
= phdi
->iOrder
;
904 lpItem
->iOrder
=nItem
;
907 HEADER_SetItemBounds (hwnd
);
909 InvalidateRect(hwnd
, NULL
, FALSE
);
916 HEADER_InsertItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
918 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
919 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
920 INT nItem
= (INT
)wParam
;
924 if ((phdi
== NULL
) || (nItem
< 0))
927 if (nItem
> infoPtr
->uNumItem
)
928 nItem
= infoPtr
->uNumItem
;
930 if (infoPtr
->uNumItem
== 0) {
931 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
));
935 HEADER_ITEM
*oldItems
= infoPtr
->items
;
938 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
939 /* pre insert copy */
941 memcpy (&infoPtr
->items
[0], &oldItems
[0],
942 nItem
* sizeof(HEADER_ITEM
));
945 /* post insert copy */
946 if (nItem
< infoPtr
->uNumItem
- 1) {
947 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
948 (infoPtr
->uNumItem
- nItem
) * sizeof(HEADER_ITEM
));
951 COMCTL32_Free (oldItems
);
954 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
955 lpItem
->bDown
= FALSE
;
957 if (phdi
->mask
& HDI_WIDTH
)
958 lpItem
->cxy
= phdi
->cxy
;
960 if (phdi
->mask
& HDI_TEXT
) {
961 WCHAR wide_null_char
= 0;
962 if (!phdi
->pszText
) /* null pointer check */
963 phdi
->pszText
= &wide_null_char
;
964 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
965 len
= strlenW (phdi
->pszText
);
966 lpItem
->pszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
967 strcpyW (lpItem
->pszText
, phdi
->pszText
);
970 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
973 if (phdi
->mask
& HDI_FORMAT
)
974 lpItem
->fmt
= phdi
->fmt
;
976 if (lpItem
->fmt
== 0)
977 lpItem
->fmt
= HDF_LEFT
;
979 if (phdi
->mask
& HDI_BITMAP
)
980 lpItem
->hbm
= phdi
->hbm
;
982 if (phdi
->mask
& HDI_LPARAM
)
983 lpItem
->lParam
= phdi
->lParam
;
985 if (phdi
->mask
& HDI_IMAGE
)
986 lpItem
->iImage
= phdi
->iImage
;
988 if (phdi
->mask
& HDI_ORDER
)
990 lpItem
->iOrder
= phdi
->iOrder
;
993 lpItem
->iOrder
= nItem
;
995 HEADER_SetItemBounds (hwnd
);
997 InvalidateRect(hwnd
, NULL
, FALSE
);
1004 HEADER_Layout (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1006 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1007 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
1009 lpLayout
->pwpos
->hwnd
= hwnd
;
1010 lpLayout
->pwpos
->hwndInsertAfter
= 0;
1011 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
1012 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
1013 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
1014 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_HIDDEN
)
1015 lpLayout
->pwpos
->cy
= 0;
1017 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
1018 lpLayout
->prc
->top
+= infoPtr
->nHeight
;
1020 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
1022 TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
1023 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
1024 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
1026 infoPtr
->bRectsValid
= FALSE
;
1033 HEADER_SetImageList (HWND hwnd
, HIMAGELIST himl
)
1035 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1038 TRACE("(himl 0x%x)\n", (int)himl
);
1039 himlOld
= infoPtr
->himl
;
1040 infoPtr
->himl
= himl
;
1042 /* FIXME: Refresh needed??? */
1044 return (LRESULT
)himlOld
;
1049 HEADER_SetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1051 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1052 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
1053 INT nItem
= (INT
)wParam
;
1054 HEADER_ITEM
*lpItem
;
1058 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1061 TRACE("[nItem=%d]\n", nItem
);
1063 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, nItem
, phdi
->mask
))
1066 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
1067 if (phdi
->mask
& HDI_BITMAP
)
1068 lpItem
->hbm
= phdi
->hbm
;
1070 if (phdi
->mask
& HDI_FORMAT
)
1071 lpItem
->fmt
= phdi
->fmt
;
1073 if (phdi
->mask
& HDI_LPARAM
)
1074 lpItem
->lParam
= phdi
->lParam
;
1076 if (phdi
->mask
& HDI_TEXT
) {
1077 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
1078 if (lpItem
->pszText
) {
1079 COMCTL32_Free (lpItem
->pszText
);
1080 lpItem
->pszText
= NULL
;
1082 if (phdi
->pszText
) {
1083 INT len
= MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,NULL
,0);
1084 lpItem
->pszText
= COMCTL32_Alloc( len
*sizeof(WCHAR
) );
1085 MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,lpItem
->pszText
,len
);
1089 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1092 if (phdi
->mask
& HDI_WIDTH
)
1093 lpItem
->cxy
= phdi
->cxy
;
1095 if (phdi
->mask
& HDI_IMAGE
)
1096 lpItem
->iImage
= phdi
->iImage
;
1098 if (phdi
->mask
& HDI_ORDER
)
1100 lpItem
->iOrder
= phdi
->iOrder
;
1103 lpItem
->iOrder
= nItem
;
1105 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGEDA
, nItem
, phdi
->mask
);
1107 HEADER_SetItemBounds (hwnd
);
1109 InvalidateRect(hwnd
, NULL
, FALSE
);
1116 HEADER_SetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1118 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1119 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
1120 INT nItem
= (INT
)wParam
;
1121 HEADER_ITEM
*lpItem
;
1125 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1128 TRACE("[nItem=%d]\n", nItem
);
1130 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
))
1133 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
1134 if (phdi
->mask
& HDI_BITMAP
)
1135 lpItem
->hbm
= phdi
->hbm
;
1137 if (phdi
->mask
& HDI_FORMAT
)
1138 lpItem
->fmt
= phdi
->fmt
;
1140 if (phdi
->mask
& HDI_LPARAM
)
1141 lpItem
->lParam
= phdi
->lParam
;
1143 if (phdi
->mask
& HDI_TEXT
) {
1144 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1145 if (lpItem
->pszText
) {
1146 COMCTL32_Free (lpItem
->pszText
);
1147 lpItem
->pszText
= NULL
;
1149 if (phdi
->pszText
) {
1150 INT len
= strlenW (phdi
->pszText
);
1151 lpItem
->pszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1152 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1156 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1159 if (phdi
->mask
& HDI_WIDTH
)
1160 lpItem
->cxy
= phdi
->cxy
;
1162 if (phdi
->mask
& HDI_IMAGE
)
1163 lpItem
->iImage
= phdi
->iImage
;
1165 if (phdi
->mask
& HDI_ORDER
)
1167 lpItem
->iOrder
= phdi
->iOrder
;
1170 lpItem
->iOrder
= nItem
;
1172 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
);
1174 HEADER_SetItemBounds (hwnd
);
1176 InvalidateRect(hwnd
, NULL
, FALSE
);
1181 inline static LRESULT
1182 HEADER_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
)
1184 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1185 BOOL bTemp
= infoPtr
->bUnicode
;
1187 infoPtr
->bUnicode
= (BOOL
)wParam
;
1194 HEADER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1196 HEADER_INFO
*infoPtr
;
1201 infoPtr
= (HEADER_INFO
*)COMCTL32_Alloc (sizeof(HEADER_INFO
));
1202 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1204 infoPtr
->hwndNotify
= GetParent(hwnd
);
1205 infoPtr
->uNumItem
= 0;
1206 infoPtr
->nHeight
= 20;
1209 infoPtr
->bRectsValid
= FALSE
;
1210 infoPtr
->hcurArrow
= LoadCursorA (0, IDC_ARROWA
);
1211 infoPtr
->hcurDivider
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDER
));
1212 infoPtr
->hcurDivopen
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDEROPEN
));
1213 infoPtr
->bPressed
= FALSE
;
1214 infoPtr
->bTracking
= FALSE
;
1215 infoPtr
->iMoveItem
= 0;
1217 infoPtr
->iHotItem
= -1;
1218 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
1219 infoPtr
->nNotifyFormat
=
1220 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
1223 hOldFont
= SelectObject (hdc
, GetStockObject (SYSTEM_FONT
));
1224 GetTextMetricsA (hdc
, &tm
);
1225 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1226 SelectObject (hdc
, hOldFont
);
1234 HEADER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1236 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1237 HEADER_ITEM
*lpItem
;
1240 if (infoPtr
->items
) {
1241 lpItem
= (HEADER_ITEM
*)infoPtr
->items
;
1242 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
1243 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
))
1244 COMCTL32_Free (lpItem
->pszText
);
1246 COMCTL32_Free (infoPtr
->items
);
1250 ImageList_Destroy (infoPtr
->himl
);
1252 COMCTL32_Free (infoPtr
);
1253 SetWindowLongA (hwnd
, 0, 0);
1258 static inline LRESULT
1259 HEADER_GetFont (HWND hwnd
)
1261 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1263 return (LRESULT
)infoPtr
->hFont
;
1268 HEADER_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1274 pt
.x
= (INT
)LOWORD(lParam
);
1275 pt
.y
= (INT
)HIWORD(lParam
);
1276 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1278 if ((GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
1279 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMDBLCLICKA
, nItem
,0);
1280 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
1281 HEADER_SendHeaderNotify (hwnd
, HDN_DIVIDERDBLCLICKA
, nItem
,0);
1288 HEADER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1290 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1291 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1297 pt
.x
= (INT
)LOWORD(lParam
);
1298 pt
.y
= (INT
)HIWORD(lParam
);
1299 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1301 if ((dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
1303 infoPtr
->bCaptured
= TRUE
;
1304 infoPtr
->bPressed
= TRUE
;
1305 infoPtr
->iMoveItem
= nItem
;
1307 infoPtr
->items
[nItem
].bDown
= TRUE
;
1309 /* Send WM_CUSTOMDRAW */
1311 HEADER_RefreshItem (hwnd
, hdc
, nItem
);
1312 ReleaseDC (hwnd
, hdc
);
1314 TRACE("Pressed item %d!\n", nItem
);
1316 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
1317 if (!(HEADER_SendHeaderNotify (hwnd
, HDN_BEGINTRACKA
, nItem
,0))) {
1319 infoPtr
->bCaptured
= TRUE
;
1320 infoPtr
->bTracking
= TRUE
;
1321 infoPtr
->iMoveItem
= nItem
;
1322 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
1323 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
1325 if (!(dwStyle
& HDS_FULLDRAG
)) {
1326 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
1328 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1329 ReleaseDC (hwnd
, hdc
);
1332 TRACE("Begin tracking item %d!\n", nItem
);
1341 HEADER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1343 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1345 *DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1352 pt
.x
= (INT
)SLOWORD(lParam
);
1353 pt
.y
= (INT
)SHIWORD(lParam
);
1354 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1356 if (infoPtr
->bPressed
) {
1357 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1358 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1360 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1361 ReleaseDC (hwnd
, hdc
);
1363 HEADER_SendClickNotify (hwnd
, HDN_ITEMCLICKA
, infoPtr
->iMoveItem
);
1365 else if (flags
== HHT_ONHEADER
)
1367 HEADER_ITEM
*lpItem
;
1368 INT newindex
= HEADER_IndexToOrder(hwnd
,nItem
);
1369 INT oldindex
= HEADER_IndexToOrder(hwnd
,infoPtr
->iMoveItem
);
1371 TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
1372 infoPtr
->iMoveItem
,oldindex
,nItem
,newindex
);
1373 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
1374 lpItem
->iOrder
=oldindex
;
1376 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[infoPtr
->iMoveItem
];
1377 lpItem
->iOrder
= newindex
;
1379 infoPtr
->bRectsValid
= FALSE
;
1380 InvalidateRect(hwnd
, NULL
, FALSE
);
1381 /* FIXME: Should some WM_NOTIFY be sent */
1384 TRACE("Released item %d!\n", infoPtr
->iMoveItem
);
1385 infoPtr
->bPressed
= FALSE
;
1387 else if (infoPtr
->bTracking
) {
1388 TRACE("End tracking item %d!\n", infoPtr
->iMoveItem
);
1389 infoPtr
->bTracking
= FALSE
;
1391 HEADER_SendHeaderNotify (hwnd
, HDN_ENDTRACKA
, infoPtr
->iMoveItem
,HDI_WIDTH
);
1394 * we want to do this even for HDS_FULLDRAG because this is where
1395 * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications
1397 * if (!(dwStyle & HDS_FULLDRAG)) {
1401 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1402 ReleaseDC (hwnd
, hdc
);
1403 if (HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1405 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1408 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1411 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1414 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1415 HEADER_SetItemBounds (hwnd
);
1416 InvalidateRect(hwnd
, NULL
, FALSE
);
1422 if (infoPtr
->bCaptured
) {
1423 infoPtr
->bCaptured
= FALSE
;
1425 HEADER_SendSimpleNotify (hwnd
, NM_RELEASEDCAPTURE
);
1433 HEADER_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1435 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1440 return infoPtr
->nNotifyFormat
;
1443 infoPtr
->nNotifyFormat
=
1444 SendMessageA ((HWND
)wParam
, WM_NOTIFYFORMAT
,
1445 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1446 return infoPtr
->nNotifyFormat
;
1454 HEADER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1456 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1457 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1463 pt
.x
= (INT
)SLOWORD(lParam
);
1464 pt
.y
= (INT
)SHIWORD(lParam
);
1465 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1467 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1468 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1469 infoPtr
->iHotItem
= nItem
;
1471 infoPtr
->iHotItem
= -1;
1472 InvalidateRect(hwnd
, NULL
, FALSE
);
1475 if (infoPtr
->bCaptured
) {
1476 if (infoPtr
->bPressed
) {
1477 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1478 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1480 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1482 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1483 ReleaseDC (hwnd
, hdc
);
1485 TRACE("Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1487 else if (infoPtr
->bTracking
) {
1488 if (dwStyle
& HDS_FULLDRAG
) {
1489 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1491 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1494 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1495 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1497 HEADER_SetItemBounds (hwnd
);
1498 InvalidateRect(hwnd
, NULL
, FALSE
);
1502 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1503 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1504 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1505 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1506 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1507 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1508 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1509 ReleaseDC (hwnd
, hdc
);
1510 HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1513 TRACE("Tracking item %d!\n", infoPtr
->iMoveItem
);
1517 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1518 FIXME("hot track support!\n");
1526 HEADER_Paint (HWND hwnd
, WPARAM wParam
)
1531 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1532 HEADER_Refresh (hwnd
, hdc
);
1534 EndPaint (hwnd
, &ps
);
1540 HEADER_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1545 pt
.x
= LOWORD(lParam
);
1546 pt
.y
= HIWORD(lParam
);
1548 /* Send a Notify message */
1549 bRet
= HEADER_SendSimpleNotify (hwnd
, NM_RCLICK
);
1551 /* Change to screen coordinate for WM_CONTEXTMENU */
1552 ClientToScreen(hwnd
, &pt
);
1554 /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */
1555 SendMessageA( hwnd
, WM_CONTEXTMENU
, (WPARAM
) hwnd
, MAKELPARAM(pt
.x
, pt
.y
));
1562 HEADER_SetCursor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1564 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1569 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1572 ScreenToClient (hwnd
, &pt
);
1574 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1576 if (flags
== HHT_ONDIVIDER
)
1577 SetCursor (infoPtr
->hcurDivider
);
1578 else if (flags
== HHT_ONDIVOPEN
)
1579 SetCursor (infoPtr
->hcurDivopen
);
1581 SetCursor (infoPtr
->hcurArrow
);
1588 HEADER_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1590 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1592 HFONT hFont
, hOldFont
;
1595 infoPtr
->hFont
= (HFONT
)wParam
;
1597 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
1600 hOldFont
= SelectObject (hdc
, hFont
);
1601 GetTextMetricsA (hdc
, &tm
);
1602 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1603 SelectObject (hdc
, hOldFont
);
1606 infoPtr
->bRectsValid
= FALSE
;
1609 InvalidateRect(hwnd
, NULL
, FALSE
);
1616 static LRESULT WINAPI
1617 HEADER_WindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1619 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1620 if (!HEADER_GetInfoPtr (hwnd
) && (msg
!= WM_CREATE
))
1621 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1623 /* case HDM_CLEARFILTER: */
1625 case HDM_CREATEDRAGIMAGE
:
1626 return HEADER_CreateDragImage (hwnd
, wParam
);
1628 case HDM_DELETEITEM
:
1629 return HEADER_DeleteItem (hwnd
, wParam
);
1631 /* case HDM_EDITFILTER: */
1633 /* case HDM_GETBITMAPMARGIN: */
1635 case HDM_GETIMAGELIST
:
1636 return HEADER_GetImageList (hwnd
);
1639 return HEADER_GetItemA (hwnd
, wParam
, lParam
);
1642 return HEADER_GetItemW (hwnd
, wParam
, lParam
);
1644 case HDM_GETITEMCOUNT
:
1645 return HEADER_GetItemCount (hwnd
);
1647 case HDM_GETITEMRECT
:
1648 return HEADER_GetItemRect (hwnd
, wParam
, lParam
);
1650 case HDM_GETORDERARRAY
:
1651 return HEADER_GetOrderArray(hwnd
, wParam
, lParam
);
1653 case HDM_GETUNICODEFORMAT
:
1654 return HEADER_GetUnicodeFormat (hwnd
);
1657 return HEADER_HitTest (hwnd
, wParam
, lParam
);
1659 case HDM_INSERTITEMA
:
1660 return HEADER_InsertItemA (hwnd
, wParam
, lParam
);
1662 case HDM_INSERTITEMW
:
1663 return HEADER_InsertItemW (hwnd
, wParam
, lParam
);
1666 return HEADER_Layout (hwnd
, wParam
, lParam
);
1668 case HDM_ORDERTOINDEX
:
1669 return HEADER_OrderToIndex(hwnd
, wParam
);
1671 /* case HDM_SETBITMAPMARGIN: */
1673 /* case HDM_SETFILTERCHANGETIMEOUT: */
1675 /* case HDM_SETHOTDIVIDER: */
1677 case HDM_SETIMAGELIST
:
1678 return HEADER_SetImageList (hwnd
, (HIMAGELIST
)lParam
);
1681 return HEADER_SetItemA (hwnd
, wParam
, lParam
);
1684 return HEADER_SetItemW (hwnd
, wParam
, lParam
);
1686 case HDM_SETORDERARRAY
:
1687 return HEADER_SetOrderArray(hwnd
, wParam
, lParam
);
1689 case HDM_SETUNICODEFORMAT
:
1690 return HEADER_SetUnicodeFormat (hwnd
, wParam
);
1693 return HEADER_Create (hwnd
, wParam
, lParam
);
1696 return HEADER_Destroy (hwnd
, wParam
, lParam
);
1702 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1705 return HEADER_GetFont (hwnd
);
1707 case WM_LBUTTONDBLCLK
:
1708 return HEADER_LButtonDblClk (hwnd
, wParam
, lParam
);
1710 case WM_LBUTTONDOWN
:
1711 return HEADER_LButtonDown (hwnd
, wParam
, lParam
);
1714 return HEADER_LButtonUp (hwnd
, wParam
, lParam
);
1717 return HEADER_MouseMove (hwnd
, wParam
, lParam
);
1719 case WM_NOTIFYFORMAT
:
1720 return HEADER_NotifyFormat (hwnd
, wParam
, lParam
);
1723 return HEADER_Size (hwnd
, wParam
);
1726 return HEADER_Paint (hwnd
, wParam
);
1729 return HEADER_RButtonUp (hwnd
, wParam
, lParam
);
1732 return HEADER_SetCursor (hwnd
, wParam
, lParam
);
1735 return HEADER_SetFont (hwnd
, wParam
, lParam
);
1739 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1740 msg
, wParam
, lParam
);
1741 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1748 HEADER_Register (void)
1752 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1753 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1754 wndClass
.lpfnWndProc
= (WNDPROC
)HEADER_WindowProc
;
1755 wndClass
.cbClsExtra
= 0;
1756 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1757 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
1758 wndClass
.lpszClassName
= WC_HEADERA
;
1760 RegisterClassA (&wndClass
);
1765 HEADER_Unregister (void)
1767 UnregisterClassA (WC_HEADERA
, (HINSTANCE
)NULL
);