4 * Copyright 1998 Eric Kohl
7 * - Imagelist support (partially).
8 * - Callback items (under construction).
9 * - Order list support.
10 * - Control specific cursors (over dividers).
11 * - Hottrack support (partially).
12 * - Custom draw support (including Notifications).
13 * - Drag and Drop support (including Notifications).
17 * - Replace DrawText32A by DrawTextEx32A(...|DT_ENDELLIPSIS) in
19 * - Little flaw when drawing a bitmap on the right side of the text.
29 #define __HDM_LAYOUT_HACK__
33 #define DIVIDER_WIDTH 10
35 #define HEADER_GetInfoPtr(wndPtr) ((HEADER_INFO *)wndPtr->wExtra[0])
39 HEADER_DrawItem (WND
*wndPtr
, HDC32 hdc
, INT32 iItem
, BOOL32 bHotTrack
)
41 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
42 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
47 if (r
.right
- r
.left
== 0)
48 return phdi
->rect
.right
;
50 if (wndPtr
->dwStyle
& HDS_BUTTONS
) {
52 DrawEdge32 (hdc
, &r
, BDR_RAISEDOUTER
,
53 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
58 DrawEdge32 (hdc
, &r
, EDGE_RAISED
,
59 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
62 DrawEdge32 (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
64 if (phdi
->fmt
& HDF_OWNERDRAW
) {
66 dis
.CtlType
= ODT_HEADER
;
67 dis
.CtlID
= wndPtr
->wIDmenu
;
69 dis
.itemAction
= ODA_DRAWENTIRE
;
70 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
71 dis
.hwndItem
= wndPtr
->hwndSelf
;
74 dis
.itemData
= phdi
->lParam
;
75 SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_DRAWITEM
,
76 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&dis
);
79 UINT32 uTextJustify
= DT_LEFT
;
81 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
82 uTextJustify
= DT_CENTER
;
83 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
84 uTextJustify
= DT_RIGHT
;
86 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->hbm
)) {
89 INT32 yD
, yS
, cx
, cy
, rx
, ry
;
91 GetObject32A (phdi
->hbm
, sizeof(BITMAP32
), (LPVOID
)&bmp
);
93 ry
= r
.bottom
- r
.top
;
94 rx
= r
.right
- r
.left
;
96 if (ry
>= bmp
.bmHeight
) {
98 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
104 yS
= (bmp
.bmHeight
- ry
) / 2;
108 if (rx
>= bmp
.bmWidth
+ 6) {
115 hdcBitmap
= CreateCompatibleDC32 (hdc
);
116 SelectObject32 (hdcBitmap
, phdi
->hbm
);
117 BitBlt32 (hdc
, r
.left
+ 3, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
118 DeleteDC32 (hdcBitmap
);
120 r
.left
+= (bmp
.bmWidth
+ 3);
124 if ((phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
127 INT32 xD
, yD
, yS
, cx
, cy
, rx
, ry
, tx
;
130 GetObject32A (phdi
->hbm
, sizeof(BITMAP32
), (LPVOID
)&bmp
);
133 DrawText32A(hdc
, phdi
->pszText
, lstrlen32A(phdi
->pszText
),
134 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
135 tx
= textRect
.right
- textRect
.left
;
136 ry
= r
.bottom
- r
.top
;
137 rx
= r
.right
- r
.left
;
139 if (ry
>= bmp
.bmHeight
) {
141 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
147 yS
= (bmp
.bmHeight
- ry
) / 2;
151 if (r
.left
+ tx
+ bmp
.bmWidth
+ 9 <= r
.right
) {
153 xD
= r
.left
+ tx
+ 6;
156 if (rx
>= bmp
.bmWidth
+ 6) {
158 xD
= r
.right
- bmp
.bmWidth
- 3;
168 hdcBitmap
= CreateCompatibleDC32 (hdc
);
169 SelectObject32 (hdcBitmap
, phdi
->hbm
);
170 BitBlt32 (hdc
, xD
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
171 DeleteDC32 (hdcBitmap
);
174 if (phdi
->fmt
& HDF_IMAGE
) {
177 // ImageList_Draw (infoPtr->himl, phdi->iImage,...);
180 if ((phdi
->fmt
& HDF_STRING
) && (phdi
->pszText
)) {
181 oldBkMode
= SetBkMode32(hdc
, TRANSPARENT
);
184 SetTextColor32 (hdc
, bHotTrack
? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
185 DrawText32A(hdc
, phdi
->pszText
, lstrlen32A(phdi
->pszText
),
186 &r
, uTextJustify
|DT_VCENTER
|DT_SINGLELINE
);
187 if (oldBkMode
!= TRANSPARENT
)
188 SetBkMode32(hdc
, oldBkMode
);
191 return phdi
->rect
.right
;
196 HEADER_Refresh (WND
*wndPtr
, HDC32 hdc
)
198 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
199 HFONT32 hFont
, hOldFont
;
204 /* get rect for the bar, adjusted for the border */
205 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
207 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (SYSTEM_FONT
);
208 hOldFont
= SelectObject32 (hdc
, hFont
);
210 /* draw Background */
211 hbrBk
= GetSysColorBrush32(COLOR_3DFACE
);
212 FillRect32(hdc
, &rect
, hbrBk
);
215 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
216 x
= HEADER_DrawItem (wndPtr
, hdc
, i
, FALSE
);
219 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
221 if (wndPtr
->dwStyle
& HDS_BUTTONS
)
222 DrawEdge32 (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
224 DrawEdge32 (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
227 SelectObject32 (hdc
, hOldFont
);
232 HEADER_RefreshItem (WND
*wndPtr
, HDC32 hdc
, INT32 iItem
)
234 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
235 HFONT32 hFont
, hOldFont
;
237 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (SYSTEM_FONT
);
238 hOldFont
= SelectObject32 (hdc
, hFont
);
239 HEADER_DrawItem (wndPtr
, hdc
, iItem
, FALSE
);
240 SelectObject32 (hdc
, hOldFont
);
245 HEADER_SetItemBounds (WND
*wndPtr
)
247 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
252 if (infoPtr
->uNumItem
== 0)
255 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
258 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
259 phdi
= &infoPtr
->items
[i
];
260 phdi
->rect
.top
= rect
.top
;
261 phdi
->rect
.bottom
= rect
.bottom
;
263 phdi
->rect
.right
= phdi
->rect
.left
+ phdi
->cxy
;
264 x
= phdi
->rect
.right
;
270 HEADER_ForceItemBounds (WND
*wndPtr
, INT32 cy
)
272 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
276 if (infoPtr
->uNumItem
== 0)
280 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
281 phdi
= &infoPtr
->items
[i
];
283 phdi
->rect
.bottom
= cy
;
285 phdi
->rect
.right
= phdi
->rect
.left
+ phdi
->cxy
;
286 x
= phdi
->rect
.right
;
292 HEADER_InternalHitTest (WND
*wndPtr
, LPPOINT32 lpPt
, UINT32
*pFlags
, INT32
*pItem
)
294 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
299 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
303 if (PtInRect32 (&rect
, *lpPt
))
305 if (infoPtr
->uNumItem
== 0) {
306 *pFlags
|= HHT_NOWHERE
;
308 TRACE (header
, "NOWHERE\n");
312 /* somewhere inside */
313 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
314 rect
= infoPtr
->items
[iCount
].rect
;
315 width
= rect
.right
- rect
.left
;
320 if (PtInRect32 (&rect
, *lpPt
)) {
321 if (width
<= 2 * DIVIDER_WIDTH
) {
322 *pFlags
|= HHT_ONHEADER
;
324 TRACE (header
, "ON HEADER %d\n", iCount
);
329 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
330 if (PtInRect32 (&rcTest
, *lpPt
)) {
332 *pFlags
|= HHT_ONDIVOPEN
;
334 TRACE (header
, "ON DIVOPEN %d\n", *pItem
);
338 *pFlags
|= HHT_ONDIVIDER
;
340 TRACE (header
, "ON DIVIDER %d\n", *pItem
);
346 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
347 if (PtInRect32 (&rcTest
, *lpPt
)) {
348 *pFlags
|= HHT_ONDIVIDER
;
350 TRACE (header
, "ON DIVIDER %d\n", *pItem
);
354 *pFlags
|= HHT_ONHEADER
;
356 TRACE (header
, "ON HEADER %d\n", iCount
);
361 /* check for last divider part (on nowhere) */
362 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
363 rect
.left
= rect
.right
;
364 rect
.right
+= DIVIDER_WIDTH
;
365 if (PtInRect32 (&rect
, *lpPt
)) {
367 *pFlags
|= HHT_ONDIVOPEN
;
368 *pItem
= infoPtr
->uNumItem
- 1;
369 TRACE (header
, "ON DIVOPEN %d\n", *pItem
);
373 *pFlags
|= HHT_ONDIVIDER
;
374 *pItem
= infoPtr
->uNumItem
-1;
375 TRACE (header
, "ON DIVIDER %d\n", *pItem
);
380 *pFlags
|= HHT_NOWHERE
;
382 TRACE (header
, "NOWHERE\n");
387 if (lpPt
->x
< rect
.left
) {
388 TRACE (header
, "TO LEFT\n");
389 *pFlags
|= HHT_TOLEFT
;
391 else if (lpPt
->x
> rect
.right
) {
392 TRACE (header
, "TO LEFT\n");
393 *pFlags
|= HHT_TORIGHT
;
396 if (lpPt
->y
< rect
.top
) {
397 TRACE (header
, "ABOVE\n");
398 *pFlags
|= HHT_ABOVE
;
400 else if (lpPt
->y
> rect
.bottom
) {
401 TRACE (header
, "BELOW\n");
402 *pFlags
|= HHT_BELOW
;
407 TRACE (header
, "flags=0x%X\n", *pFlags
);
413 HEADER_DrawTrackLine (WND
*wndPtr
, HDC32 hdc
, INT32 x
)
419 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
421 hOldPen
= SelectObject32 (hdc
, GetStockObject32 (BLACK_PEN
));
422 oldRop
= SetROP232 (hdc
, R2_XORPEN
);
423 MoveToEx32 (hdc
, x
, rect
.top
, NULL
);
424 LineTo32 (hdc
, x
, rect
.bottom
);
425 SetROP232 (hdc
, oldRop
);
426 SelectObject32 (hdc
, hOldPen
);
431 HEADER_SendSimpleNotify (WND
*wndPtr
, UINT32 code
)
435 nmhdr
.hwndFrom
= wndPtr
->hwndSelf
;
436 nmhdr
.idFrom
= wndPtr
->wIDmenu
;
439 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
440 (WPARAM32
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
445 HEADER_SendHeaderNotify (WND
*wndPtr
, UINT32 code
, INT32 iItem
)
447 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
451 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
452 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
453 nmhdr
.hdr
.code
= code
;
456 nmhdr
.pitem
= &nmitem
;
458 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
459 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
460 nmitem
.pszText
= NULL
;
461 nmitem
.cchTextMax
= 0;
462 // nmitem.pszText = infoPtr->items[iItem].pszText;
463 // nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax;
464 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
465 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
466 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
467 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
469 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
470 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
475 HEADER_SendClickNotify (WND
*wndPtr
, UINT32 code
, INT32 iItem
)
479 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
480 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
481 nmhdr
.hdr
.code
= code
;
486 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
487 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
492 HEADER_CreateDragImage (WND
*wndPtr
, WPARAM32 wParam
)
494 FIXME (header
, "empty stub!\n");
500 HEADER_DeleteItem (WND
*wndPtr
, WPARAM32 wParam
)
502 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
503 INT32 iItem
= (INT32
)wParam
;
506 TRACE(header
, "[iItem=%d]\n", iItem
);
508 if ((iItem
< 0) || (iItem
>= (INT32
)infoPtr
->uNumItem
))
511 if (infoPtr
->uNumItem
== 1) {
512 TRACE(header
, "Simple delete!\n");
513 if (infoPtr
->items
[0].pszText
)
514 COMCTL32_Free (infoPtr
->items
[0].pszText
);
515 COMCTL32_Free (infoPtr
->items
);
517 infoPtr
->uNumItem
= 0;
520 HEADER_ITEM
*oldItems
= infoPtr
->items
;
521 TRACE(header
, "Complex delete! [iItem=%d]\n", iItem
);
523 if (infoPtr
->items
[iItem
].pszText
)
524 COMCTL32_Free (infoPtr
->items
[iItem
].pszText
);
527 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
528 /* pre delete copy */
530 memcpy (&infoPtr
->items
[0], &oldItems
[0],
531 iItem
* sizeof(HEADER_ITEM
));
534 /* post delete copy */
535 if (iItem
< infoPtr
->uNumItem
) {
536 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
537 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
540 COMCTL32_Free (oldItems
);
543 HEADER_SetItemBounds (wndPtr
);
545 hdc
= GetDC32 (wndPtr
->hwndSelf
);
546 HEADER_Refresh (wndPtr
, hdc
);
547 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
554 HEADER_GetImageList (WND
*wndPtr
)
556 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
558 return (LRESULT
)infoPtr
->himl
;
563 HEADER_GetItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
565 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
566 HDITEM32A
*phdi
= (HDITEM32A
*)lParam
;
567 INT32 nItem
= (INT32
)wParam
;
572 if ((nItem
< 0) || (nItem
>= (INT32
)infoPtr
->uNumItem
))
575 TRACE (header
, "[nItem=%d]\n", nItem
);
580 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
581 if (phdi
->mask
& HDI_BITMAP
)
582 phdi
->hbm
= lpItem
->hbm
;
584 if (phdi
->mask
& HDI_FORMAT
)
585 phdi
->fmt
= lpItem
->fmt
;
587 if (phdi
->mask
& HDI_WIDTH
)
588 phdi
->cxy
= lpItem
->cxy
;
590 if (phdi
->mask
& HDI_LPARAM
)
591 phdi
->lParam
= lpItem
->lParam
;
593 if (phdi
->mask
& HDI_TEXT
) {
594 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACK32A
)
595 lstrcpyn32A (phdi
->pszText
, lpItem
->pszText
, phdi
->cchTextMax
);
597 phdi
->pszText
= LPSTR_TEXTCALLBACK32A
;
600 if (phdi
->mask
& HDI_IMAGE
)
601 phdi
->iImage
= lpItem
->iImage
;
603 if (phdi
->mask
& HDI_ORDER
)
604 phdi
->iOrder
= lpItem
->iOrder
;
611 HEADER_GetItemCount (WND
*wndPtr
)
613 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
615 return (infoPtr
->uNumItem
);
620 HEADER_GetItemRect (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
622 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
623 INT32 iItem
= (INT32
)wParam
;
624 LPRECT32 lpRect
= (LPRECT32
)lParam
;
626 if ((iItem
< 0) || (iItem
>= (INT32
)infoPtr
->uNumItem
))
629 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
630 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
631 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
632 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
639 HEADER_HitTest (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
641 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
643 HEADER_InternalHitTest (wndPtr
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
650 HEADER_InsertItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
652 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
653 HDITEM32A
*phdi
= (HDITEM32A
*)lParam
;
654 INT32 nItem
= (INT32
)wParam
;
659 if ((phdi
== NULL
) || (nItem
< 0))
662 if (nItem
> infoPtr
->uNumItem
)
663 nItem
= infoPtr
->uNumItem
;
665 if (infoPtr
->uNumItem
== 0) {
666 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
));
670 HEADER_ITEM
*oldItems
= infoPtr
->items
;
673 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
674 /* pre insert copy */
676 memcpy (&infoPtr
->items
[0], &oldItems
[0],
677 nItem
* sizeof(HEADER_ITEM
));
680 /* post insert copy */
681 if (nItem
< infoPtr
->uNumItem
- 1) {
682 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
683 (infoPtr
->uNumItem
- nItem
) * sizeof(HEADER_ITEM
));
686 COMCTL32_Free (oldItems
);
689 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
690 lpItem
->bDown
= FALSE
;
692 if (phdi
->mask
& HDI_WIDTH
)
693 lpItem
->cxy
= phdi
->cxy
;
695 if (phdi
->mask
& HDI_TEXT
) {
696 if (phdi
->pszText
!= LPSTR_TEXTCALLBACK32A
) {
697 len
= lstrlen32A (phdi
->pszText
);
698 lpItem
->pszText
= COMCTL32_Alloc (len
+1);
699 lstrcpy32A (lpItem
->pszText
, phdi
->pszText
);
702 lpItem
->pszText
= LPSTR_TEXTCALLBACK32A
;
705 if (phdi
->mask
& HDI_FORMAT
)
706 lpItem
->fmt
= phdi
->fmt
;
708 if (phdi
->mask
& HDI_BITMAP
)
709 lpItem
->hbm
= phdi
->hbm
;
711 if (phdi
->mask
& HDI_LPARAM
)
712 lpItem
->lParam
= phdi
->lParam
;
714 if (phdi
->mask
& HDI_IMAGE
)
715 lpItem
->iImage
= phdi
->iImage
;
717 if (phdi
->mask
& HDI_ORDER
)
718 lpItem
->iOrder
= phdi
->iOrder
;
720 HEADER_SetItemBounds (wndPtr
);
722 hdc
= GetDC32 (wndPtr
->hwndSelf
);
723 HEADER_Refresh (wndPtr
, hdc
);
724 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
731 HEADER_Layout (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
733 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
734 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
736 lpLayout
->pwpos
->hwnd
= wndPtr
->hwndSelf
;
737 lpLayout
->pwpos
->hwndInsertAfter
= 0;
738 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
739 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
740 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
741 if (wndPtr
->dwStyle
& HDS_HIDDEN
)
742 lpLayout
->pwpos
->cy
= 0;
744 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
745 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
747 TRACE (header
, "Layout x=%d y=%d cx=%d cy=%d\n",
748 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
749 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
751 HEADER_ForceItemBounds (wndPtr
, lpLayout
->pwpos
->cy
);
754 #ifdef __HDM_LAYOUT_HACK__
755 MoveWindow32 (lpLayout
->pwpos
->hwnd
, lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
756 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
, TRUE
);
764 HEADER_SetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
766 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
769 himlOld
= infoPtr
->himl
;
770 infoPtr
->himl
= (HIMAGELIST
)lParam
;
772 /* FIXME: Refresh needed??? */
774 return (LRESULT
)himlOld
;
779 HEADER_SetItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
781 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
782 HDITEM32A
*phdi
= (HDITEM32A
*)lParam
;
783 INT32 nItem
= (INT32
)wParam
;
789 if ((nItem
< 0) || (nItem
>= (INT32
)infoPtr
->uNumItem
))
792 TRACE (header
, "[nItem=%d]\n", nItem
);
794 if (HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGING32A
, nItem
))
797 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
798 if (phdi
->mask
& HDI_BITMAP
)
799 lpItem
->hbm
= phdi
->hbm
;
801 if (phdi
->mask
& HDI_FORMAT
)
802 lpItem
->fmt
= phdi
->fmt
;
804 if (phdi
->mask
& HDI_LPARAM
)
805 lpItem
->lParam
= phdi
->lParam
;
807 if (phdi
->mask
& HDI_TEXT
) {
808 if (phdi
->pszText
!= LPSTR_TEXTCALLBACK32A
) {
809 INT32 len
= lstrlen32A (phdi
->pszText
);
811 COMCTL32_Free (lpItem
->pszText
);
812 lpItem
->pszText
= COMCTL32_Alloc (len
+1);
813 lstrcpy32A (lpItem
->pszText
, phdi
->pszText
);
816 lpItem
->pszText
= LPSTR_TEXTCALLBACK32A
;
819 if (phdi
->mask
& HDI_WIDTH
)
820 lpItem
->cxy
= phdi
->cxy
;
822 if (phdi
->mask
& HDI_IMAGE
)
823 lpItem
->iImage
= phdi
->iImage
;
825 if (phdi
->mask
& HDI_ORDER
)
826 lpItem
->iOrder
= phdi
->iOrder
;
828 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGED32A
, nItem
);
830 HEADER_SetItemBounds (wndPtr
);
831 hdc
= GetDC32 (wndPtr
->hwndSelf
);
832 HEADER_Refresh (wndPtr
, hdc
);
833 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
840 HEADER_Create (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
842 HEADER_INFO
*infoPtr
;
847 infoPtr
= (HEADER_INFO
*)COMCTL32_Alloc (sizeof(HEADER_INFO
));
848 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
850 infoPtr
->uNumItem
= 0;
851 infoPtr
->nHeight
= 20;
854 infoPtr
->hcurArrow
= LoadCursor32A (0, IDC_ARROW32A
);
855 infoPtr
->hcurDivider
= LoadCursor32A (0, IDC_SIZEWE32A
);
856 infoPtr
->hcurDivopen
= LoadCursor32A (0, IDC_SIZENS32A
);
857 infoPtr
->bPressed
= FALSE
;
858 infoPtr
->bTracking
= FALSE
;
859 infoPtr
->iMoveItem
= 0;
861 infoPtr
->iHotItem
= -1;
864 hOldFont
= SelectObject32 (hdc
, GetStockObject32 (SYSTEM_FONT
));
865 GetTextMetrics32A (hdc
, &tm
);
866 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
867 SelectObject32 (hdc
, hOldFont
);
868 ReleaseDC32 (0, hdc
);
875 HEADER_Destroy (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
877 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
881 if (infoPtr
->items
) {
882 lpItem
= (HEADER_ITEM
*)infoPtr
->items
;
883 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
884 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACK32A
))
885 COMCTL32_Free (lpItem
->pszText
);
887 COMCTL32_Free (infoPtr
->items
);
891 ImageList_Destroy (infoPtr
->himl
);
893 COMCTL32_Free (infoPtr
);
899 static __inline__ LRESULT
900 HEADER_GetFont (WND
*wndPtr
)
902 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
904 return (LRESULT
)infoPtr
->hFont
;
909 HEADER_LButtonDblClk (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
915 pt
.x
= (INT32
)LOWORD(lParam
);
916 pt
.y
= (INT32
)HIWORD(lParam
);
917 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &nItem
);
919 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
920 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMDBLCLICK32A
, nItem
);
921 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
922 HEADER_SendHeaderNotify (wndPtr
, HDN_DIVIDERDBLCLICK32A
, nItem
);
929 HEADER_LButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
931 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
937 pt
.x
= (INT32
)LOWORD(lParam
);
938 pt
.y
= (INT32
)HIWORD(lParam
);
939 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &nItem
);
941 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
942 SetCapture32 (wndPtr
->hwndSelf
);
943 infoPtr
->bCaptured
= TRUE
;
944 infoPtr
->bPressed
= TRUE
;
945 infoPtr
->iMoveItem
= nItem
;
947 infoPtr
->items
[nItem
].bDown
= TRUE
;
949 /* Send WM_CUSTOMDRAW */
950 hdc
= GetDC32 (wndPtr
->hwndSelf
);
951 HEADER_RefreshItem (wndPtr
, hdc
, nItem
);
952 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
954 TRACE (header
, "Pressed item %d!\n", nItem
);
956 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
957 if (!(HEADER_SendHeaderNotify (wndPtr
, HDN_BEGINTRACK32A
, nItem
))) {
958 SetCapture32 (wndPtr
->hwndSelf
);
959 infoPtr
->bCaptured
= TRUE
;
960 infoPtr
->bTracking
= TRUE
;
961 infoPtr
->iMoveItem
= nItem
;
962 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
963 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
965 if (!(wndPtr
->dwStyle
& HDS_FULLDRAG
)) {
966 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
967 hdc
= GetDC32 (wndPtr
->hwndSelf
);
968 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
969 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
972 TRACE (header
, "Begin tracking item %d!\n", nItem
);
981 HEADER_LButtonUp (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
983 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
989 pt
.x
= (INT32
)LOWORD(lParam
);
990 pt
.y
= (INT32
)HIWORD(lParam
);
991 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &nItem
);
993 if (infoPtr
->bPressed
) {
994 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
995 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
996 hdc
= GetDC32 (wndPtr
->hwndSelf
);
997 HEADER_RefreshItem (wndPtr
, hdc
, infoPtr
->iMoveItem
);
998 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1000 HEADER_SendClickNotify (wndPtr
, HDN_ITEMCLICK32A
, infoPtr
->iMoveItem
);
1002 TRACE (header
, "Released item %d!\n", infoPtr
->iMoveItem
);
1003 infoPtr
->bPressed
= FALSE
;
1005 else if (infoPtr
->bTracking
) {
1006 TRACE (header
, "End tracking item %d!\n", infoPtr
->iMoveItem
);
1007 infoPtr
->bTracking
= FALSE
;
1009 HEADER_SendHeaderNotify (wndPtr
, HDN_ENDTRACK32A
, infoPtr
->iMoveItem
);
1011 if (!(wndPtr
->dwStyle
& HDS_FULLDRAG
)) {
1012 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1013 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
1014 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1015 if (HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGING32A
, infoPtr
->iMoveItem
))
1016 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1018 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1021 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1022 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGED32A
, infoPtr
->iMoveItem
);
1025 HEADER_SetItemBounds (wndPtr
);
1026 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1027 HEADER_Refresh (wndPtr
, hdc
);
1028 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1032 if (infoPtr
->bCaptured
) {
1033 infoPtr
->bCaptured
= FALSE
;
1035 HEADER_SendSimpleNotify (wndPtr
, NM_RELEASEDCAPTURE
);
1043 HEADER_MouseMove (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1045 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
1048 INT32 nItem
, nWidth
;
1051 pt
.x
= (INT32
)LOWORD(lParam
);
1052 pt
.y
= (INT32
)HIWORD(lParam
);
1053 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &nItem
);
1055 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (wndPtr
->dwStyle
& HDS_HOTTRACK
)) {
1056 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1057 infoPtr
->iHotItem
= nItem
;
1059 infoPtr
->iHotItem
= -1;
1060 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1061 HEADER_Refresh (wndPtr
, hdc
);
1062 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1065 if (infoPtr
->bCaptured
) {
1066 if (infoPtr
->bPressed
) {
1067 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1068 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1070 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1071 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1072 HEADER_RefreshItem (wndPtr
, hdc
, infoPtr
->iMoveItem
);
1073 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1075 TRACE (header
, "Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1077 else if (infoPtr
->bTracking
) {
1078 if (wndPtr
->dwStyle
& HDS_FULLDRAG
) {
1079 if (HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGING32A
, infoPtr
->iMoveItem
))
1080 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1082 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1085 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1086 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGED32A
,
1087 infoPtr
->iMoveItem
);
1089 HEADER_SetItemBounds (wndPtr
);
1090 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1091 HEADER_Refresh (wndPtr
, hdc
);
1092 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1095 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1096 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
1097 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1098 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1099 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1100 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1101 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1102 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
1103 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1106 HEADER_SendHeaderNotify (wndPtr
, HDN_TRACK32A
, infoPtr
->iMoveItem
);
1107 TRACE (header
, "Tracking item %d!\n", infoPtr
->iMoveItem
);
1111 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (wndPtr
->dwStyle
& HDS_HOTTRACK
)) {
1112 FIXME (header
, "hot track support!\n");
1120 HEADER_Paint (WND
*wndPtr
, WPARAM32 wParam
)
1125 hdc
= wParam
==0 ? BeginPaint32 (wndPtr
->hwndSelf
, &ps
) : (HDC32
)wParam
;
1126 HEADER_Refresh (wndPtr
, hdc
);
1128 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
1134 HEADER_RButtonUp (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1136 return HEADER_SendSimpleNotify (wndPtr
, NM_RCLICK
);
1141 HEADER_SetCursor (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1143 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
1148 TRACE (header
, "code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1150 GetCursorPos32 (&pt
);
1151 ScreenToClient32 (wndPtr
->hwndSelf
, &pt
);
1153 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &nItem
);
1155 if (flags
== HHT_ONDIVIDER
)
1156 SetCursor32 (infoPtr
->hcurDivider
);
1157 else if (flags
== HHT_ONDIVOPEN
)
1158 SetCursor32 (infoPtr
->hcurDivopen
);
1160 SetCursor32 (infoPtr
->hcurArrow
);
1167 HEADER_SetFont (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1169 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
1171 HFONT32 hFont
, hOldFont
;
1174 infoPtr
->hFont
= (HFONT32
)wParam
;
1176 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (SYSTEM_FONT
);
1179 hOldFont
= SelectObject32 (hdc
, hFont
);
1180 GetTextMetrics32A (hdc
, &tm
);
1181 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1182 SelectObject32 (hdc
, hOldFont
);
1183 ReleaseDC32 (0, hdc
);
1186 HEADER_ForceItemBounds (wndPtr
, infoPtr
->nHeight
);
1187 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1188 HEADER_Refresh (wndPtr
, hdc
);
1189 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1197 HEADER_WindowProc (HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
1199 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1202 case HDM_CREATEDRAGIMAGE
:
1203 return HEADER_CreateDragImage (wndPtr
, wParam
);
1205 case HDM_DELETEITEM
:
1206 return HEADER_DeleteItem (wndPtr
, wParam
);
1208 case HDM_GETIMAGELIST
:
1209 return HEADER_GetImageList (wndPtr
);
1211 case HDM_GETITEM32A
:
1212 return HEADER_GetItem32A (wndPtr
, wParam
, lParam
);
1214 // case HDM_GETITEM32W:
1216 case HDM_GETITEMCOUNT
:
1217 return HEADER_GetItemCount (wndPtr
);
1219 case HDM_GETITEMRECT
:
1220 return HEADER_GetItemRect (wndPtr
, wParam
, lParam
);
1222 // case HDM_GETORDERARRAY:
1223 // case HDM_GETUNICODEFORMAT:
1226 return HEADER_HitTest (wndPtr
, wParam
, lParam
);
1228 case HDM_INSERTITEM32A
:
1229 return HEADER_InsertItem32A (wndPtr
, wParam
, lParam
);
1231 // case HDM_INSERTITEM32W:
1234 return HEADER_Layout (wndPtr
, wParam
, lParam
);
1236 case HDM_SETIMAGELIST
:
1237 return HEADER_SetImageList (wndPtr
, wParam
, lParam
);
1239 case HDM_SETITEM32A
:
1240 return HEADER_SetItem32A (wndPtr
, wParam
, lParam
);
1242 // case HDM_SETITEM32W:
1243 // case HDM_SETORDERARRAY:
1244 // case HDM_SETUNICODEFORMAT:
1248 return HEADER_Create (wndPtr
, wParam
, lParam
);
1251 return HEADER_Destroy (wndPtr
, wParam
, lParam
);
1257 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1260 return HEADER_GetFont (wndPtr
);
1262 case WM_LBUTTONDBLCLK
:
1263 return HEADER_LButtonDblClk (wndPtr
, wParam
, lParam
);
1265 case WM_LBUTTONDOWN
:
1266 return HEADER_LButtonDown (wndPtr
, wParam
, lParam
);
1269 return HEADER_LButtonUp (wndPtr
, wParam
, lParam
);
1272 return HEADER_MouseMove (wndPtr
, wParam
, lParam
);
1275 return HEADER_Paint (wndPtr
, wParam
);
1278 return HEADER_RButtonUp (wndPtr
, wParam
, lParam
);
1281 return HEADER_SetCursor (wndPtr
, wParam
, lParam
);
1284 return HEADER_SetFont (wndPtr
, wParam
, lParam
);
1288 ERR (header
, "unknown msg %04x wp=%04x lp=%08lx\n",
1289 msg
, wParam
, lParam
);
1290 return DefWindowProc32A (hwnd
, msg
, wParam
, lParam
);
1296 void HEADER_Register( void )
1298 WNDCLASS32A wndClass
;
1300 if (GlobalFindAtom32A (WC_HEADER32A
)) return;
1302 ZeroMemory (&wndClass
, sizeof(WNDCLASS32A
));
1303 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1304 wndClass
.lpfnWndProc
= (WNDPROC32
)HEADER_WindowProc
;
1305 wndClass
.cbClsExtra
= 0;
1306 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1307 wndClass
.hCursor
= LoadCursor32A (0, IDC_ARROW32A
);
1308 wndClass
.lpszClassName
= WC_HEADER32A
;
1310 RegisterClass32A (&wndClass
);