4 * Copyright 1998 Eric Kohl
7 * - Imagelist support (partially).
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.
30 #define __HDM_LAYOUT_HACK__
34 #define DIVIDER_WIDTH 10
36 #define HEADER_GetInfoPtr(wndPtr) ((HEADER_INFO *)wndPtr->wExtra[0])
40 HEADER_DrawItem (WND
*wndPtr
, HDC32 hdc
, INT32 iItem
, BOOL32 bHotTrack
)
42 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
43 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
48 if (r
.right
- r
.left
== 0)
49 return phdi
->rect
.right
;
51 if (wndPtr
->dwStyle
& HDS_BUTTONS
) {
53 DrawEdge32 (hdc
, &r
, BDR_RAISEDOUTER
,
54 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
59 DrawEdge32 (hdc
, &r
, EDGE_RAISED
,
60 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
63 DrawEdge32 (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
65 if (phdi
->fmt
& HDF_OWNERDRAW
) {
67 dis
.CtlType
= ODT_HEADER
;
68 dis
.CtlID
= wndPtr
->wIDmenu
;
70 dis
.itemAction
= ODA_DRAWENTIRE
;
71 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
72 dis
.hwndItem
= wndPtr
->hwndSelf
;
75 dis
.itemData
= phdi
->lParam
;
76 SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_DRAWITEM
,
77 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&dis
);
80 UINT32 uTextJustify
= DT_LEFT
;
82 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
83 uTextJustify
= DT_CENTER
;
84 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
85 uTextJustify
= DT_RIGHT
;
87 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->hbm
)) {
90 INT32 yD
, yS
, cx
, cy
, rx
, ry
;
92 GetObject32A (phdi
->hbm
, sizeof(BITMAP32
), (LPVOID
)&bmp
);
94 ry
= r
.bottom
- r
.top
;
95 rx
= r
.right
- r
.left
;
97 if (ry
>= bmp
.bmHeight
) {
99 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
105 yS
= (bmp
.bmHeight
- ry
) / 2;
109 if (rx
>= bmp
.bmWidth
+ 6) {
116 hdcBitmap
= CreateCompatibleDC32 (hdc
);
117 SelectObject32 (hdcBitmap
, phdi
->hbm
);
118 BitBlt32 (hdc
, r
.left
+ 3, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
119 DeleteDC32 (hdcBitmap
);
121 r
.left
+= (bmp
.bmWidth
+ 3);
125 if ((phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
128 INT32 xD
, yD
, yS
, cx
, cy
, rx
, ry
, tx
;
131 GetObject32A (phdi
->hbm
, sizeof(BITMAP32
), (LPVOID
)&bmp
);
134 DrawText32A(hdc
, phdi
->pszText
, lstrlen32A(phdi
->pszText
),
135 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
136 tx
= textRect
.right
- textRect
.left
;
137 ry
= r
.bottom
- r
.top
;
138 rx
= r
.right
- r
.left
;
140 if (ry
>= bmp
.bmHeight
) {
142 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
148 yS
= (bmp
.bmHeight
- ry
) / 2;
152 if (r
.left
+ tx
+ bmp
.bmWidth
+ 9 <= r
.right
) {
154 xD
= r
.left
+ tx
+ 6;
157 if (rx
>= bmp
.bmWidth
+ 6) {
159 xD
= r
.right
- bmp
.bmWidth
- 3;
169 hdcBitmap
= CreateCompatibleDC32 (hdc
);
170 SelectObject32 (hdcBitmap
, phdi
->hbm
);
171 BitBlt32 (hdc
, xD
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
172 DeleteDC32 (hdcBitmap
);
175 if (phdi
->fmt
& HDF_IMAGE
) {
178 // ImageList_Draw (infoPtr->himl, phdi->iImage,...);
181 if ((phdi
->fmt
& HDF_STRING
) && (phdi
->pszText
)) {
182 oldBkMode
= SetBkMode32(hdc
, TRANSPARENT
);
185 SetTextColor32 (hdc
, bHotTrack
? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
186 DrawText32A(hdc
, phdi
->pszText
, lstrlen32A(phdi
->pszText
),
187 &r
, uTextJustify
|DT_VCENTER
|DT_SINGLELINE
);
188 if (oldBkMode
!= TRANSPARENT
)
189 SetBkMode32(hdc
, oldBkMode
);
192 return phdi
->rect
.right
;
197 HEADER_Refresh (WND
*wndPtr
, HDC32 hdc
)
199 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
200 HFONT32 hFont
, hOldFont
;
205 /* get rect for the bar, adjusted for the border */
206 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
208 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (SYSTEM_FONT
);
209 hOldFont
= SelectObject32 (hdc
, hFont
);
211 /* draw Background */
212 hbrBk
= GetSysColorBrush32(COLOR_3DFACE
);
213 FillRect32(hdc
, &rect
, hbrBk
);
216 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
217 x
= HEADER_DrawItem (wndPtr
, hdc
, i
, FALSE
);
220 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
222 if (wndPtr
->dwStyle
& HDS_BUTTONS
)
223 DrawEdge32 (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
225 DrawEdge32 (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
228 SelectObject32 (hdc
, hOldFont
);
233 HEADER_RefreshItem (WND
*wndPtr
, HDC32 hdc
, INT32 iItem
)
235 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
236 HFONT32 hFont
, hOldFont
;
238 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (SYSTEM_FONT
);
239 hOldFont
= SelectObject32 (hdc
, hFont
);
240 HEADER_DrawItem (wndPtr
, hdc
, iItem
, FALSE
);
241 SelectObject32 (hdc
, hOldFont
);
246 HEADER_SetItemBounds (WND
*wndPtr
)
248 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
253 if (infoPtr
->uNumItem
== 0)
256 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
259 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
260 phdi
= &infoPtr
->items
[i
];
261 phdi
->rect
.top
= rect
.top
;
262 phdi
->rect
.bottom
= rect
.bottom
;
264 phdi
->rect
.right
= phdi
->rect
.left
+ phdi
->cxy
;
265 x
= phdi
->rect
.right
;
271 HEADER_ForceItemBounds (WND
*wndPtr
, INT32 cy
)
273 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
277 if (infoPtr
->uNumItem
== 0)
281 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
282 phdi
= &infoPtr
->items
[i
];
284 phdi
->rect
.bottom
= cy
;
286 phdi
->rect
.right
= phdi
->rect
.left
+ phdi
->cxy
;
287 x
= phdi
->rect
.right
;
293 HEADER_InternalHitTest (WND
*wndPtr
, LPPOINT32 lpPt
, UINT32
*pFlags
, INT32
*pItem
)
295 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
300 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
304 if (PtInRect32 (&rect
, *lpPt
))
306 if (infoPtr
->uNumItem
== 0) {
307 *pFlags
|= HHT_NOWHERE
;
309 TRACE (header
, "NOWHERE\n");
313 /* somewhere inside */
314 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
315 rect
= infoPtr
->items
[iCount
].rect
;
316 width
= rect
.right
- rect
.left
;
321 if (PtInRect32 (&rect
, *lpPt
)) {
322 if (width
<= 2 * DIVIDER_WIDTH
) {
323 *pFlags
|= HHT_ONHEADER
;
325 TRACE (header
, "ON HEADER %d\n", iCount
);
330 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
331 if (PtInRect32 (&rcTest
, *lpPt
)) {
333 *pFlags
|= HHT_ONDIVOPEN
;
335 TRACE (header
, "ON DIVOPEN %d\n", *pItem
);
339 *pFlags
|= HHT_ONDIVIDER
;
341 TRACE (header
, "ON DIVIDER %d\n", *pItem
);
347 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
348 if (PtInRect32 (&rcTest
, *lpPt
)) {
349 *pFlags
|= HHT_ONDIVIDER
;
351 TRACE (header
, "ON DIVIDER %d\n", *pItem
);
355 *pFlags
|= HHT_ONHEADER
;
357 TRACE (header
, "ON HEADER %d\n", iCount
);
362 /* check for last divider part (on nowhere) */
363 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
364 rect
.left
= rect
.right
;
365 rect
.right
+= DIVIDER_WIDTH
;
366 if (PtInRect32 (&rect
, *lpPt
)) {
368 *pFlags
|= HHT_ONDIVOPEN
;
369 *pItem
= infoPtr
->uNumItem
- 1;
370 TRACE (header
, "ON DIVOPEN %d\n", *pItem
);
374 *pFlags
|= HHT_ONDIVIDER
;
375 *pItem
= infoPtr
->uNumItem
-1;
376 TRACE (header
, "ON DIVIDER %d\n", *pItem
);
381 *pFlags
|= HHT_NOWHERE
;
383 TRACE (header
, "NOWHERE\n");
388 if (lpPt
->x
< rect
.left
) {
389 TRACE (header
, "TO LEFT\n");
390 *pFlags
|= HHT_TOLEFT
;
392 else if (lpPt
->x
> rect
.right
) {
393 TRACE (header
, "TO LEFT\n");
394 *pFlags
|= HHT_TORIGHT
;
397 if (lpPt
->y
< rect
.top
) {
398 TRACE (header
, "ABOVE\n");
399 *pFlags
|= HHT_ABOVE
;
401 else if (lpPt
->y
> rect
.bottom
) {
402 TRACE (header
, "BELOW\n");
403 *pFlags
|= HHT_BELOW
;
408 TRACE (header
, "flags=0x%X\n", *pFlags
);
414 HEADER_DrawTrackLine (WND
*wndPtr
, HDC32 hdc
, INT32 x
)
420 GetClientRect32 (wndPtr
->hwndSelf
, &rect
);
422 hOldPen
= SelectObject32 (hdc
, GetStockObject32 (BLACK_PEN
));
423 oldRop
= SetROP232 (hdc
, R2_XORPEN
);
424 MoveToEx32 (hdc
, x
, rect
.top
, NULL
);
425 LineTo32 (hdc
, x
, rect
.bottom
);
426 SetROP232 (hdc
, oldRop
);
427 SelectObject32 (hdc
, hOldPen
);
432 HEADER_SendSimpleNotify (WND
*wndPtr
, UINT32 code
)
436 nmhdr
.hwndFrom
= wndPtr
->hwndSelf
;
437 nmhdr
.idFrom
= wndPtr
->wIDmenu
;
440 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
441 (WPARAM32
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
446 HEADER_SendHeaderNotify (WND
*wndPtr
, UINT32 code
, INT32 iItem
)
448 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
452 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
453 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
454 nmhdr
.hdr
.code
= code
;
457 nmhdr
.pitem
= &nmitem
;
458 nmitem
.mask
= infoPtr
->items
[iItem
].mask
;
459 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
460 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
461 nmitem
.pszText
= infoPtr
->items
[iItem
].pszText
;
462 nmitem
.cchTextMax
= infoPtr
->items
[iItem
].cchTextMax
;
463 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
464 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
465 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
466 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
468 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
469 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
474 HEADER_SendClickNotify (WND
*wndPtr
, UINT32 code
, INT32 iItem
)
478 nmhdr
.hdr
.hwndFrom
= wndPtr
->hwndSelf
;
479 nmhdr
.hdr
.idFrom
= wndPtr
->wIDmenu
;
480 nmhdr
.hdr
.code
= code
;
485 return (BOOL32
)SendMessage32A (GetParent32 (wndPtr
->hwndSelf
), WM_NOTIFY
,
486 (WPARAM32
)wndPtr
->wIDmenu
, (LPARAM
)&nmhdr
);
491 HEADER_CreateDragImage (WND
*wndPtr
, WPARAM32 wParam
)
493 FIXME (header
, "empty stub!\n");
499 HEADER_DeleteItem (WND
*wndPtr
, WPARAM32 wParam
)
501 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
505 iItem
= (INT32
)wParam
;
507 TRACE(header
, "[iItem=%d]\n", iItem
);
509 if ((iItem
< 0) || (iItem
> infoPtr
->uNumItem
- 1))
512 if (infoPtr
->uNumItem
== 1) {
513 TRACE(header
, "Simple delete!\n");
514 if (infoPtr
->items
[0].pszText
)
515 HeapFree (GetProcessHeap (), 0, infoPtr
->items
[0].pszText
);
516 HeapFree (GetProcessHeap (), 0, infoPtr
->items
);
518 infoPtr
->uNumItem
= 0;
521 HEADER_ITEM
*oldItems
= infoPtr
->items
;
522 TRACE(header
, "Complex delete! [iItem=%d]\n", iItem
);
524 if (infoPtr
->items
[iItem
].pszText
)
525 HeapFree (GetProcessHeap (), 0, infoPtr
->items
[iItem
].pszText
);
528 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
529 sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
530 /* pre delete copy */
532 memcpy (&infoPtr
->items
[0], &oldItems
[0],
533 iItem
* sizeof(HEADER_ITEM
));
536 /* post delete copy */
537 if (iItem
< infoPtr
->uNumItem
) {
538 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
539 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
542 HeapFree (GetProcessHeap (), 0, oldItems
);
545 HEADER_SetItemBounds (wndPtr
);
547 hdc
= GetDC32 (wndPtr
->hwndSelf
);
548 HEADER_Refresh (wndPtr
, hdc
);
549 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
556 HEADER_GetImageList (WND
*wndPtr
)
558 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
560 return (LRESULT
)infoPtr
->himl
;
565 HEADER_GetItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
567 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
572 phdi
= (HD_ITEMA
*)lParam
;
573 iItem
= (INT32
)wParam
;
575 if ((iItem
< 0) || (iItem
> infoPtr
->uNumItem
- 1))
578 TRACE (header
, "[iItem=%d]\n", iItem
);
585 if (uMask
& infoPtr
->items
[iItem
].mask
& HDI_BITMAP
) {
586 phdi
->hbm
= infoPtr
->items
[iItem
].hbm
;
587 phdi
->mask
|= HDI_BITMAP
;
590 if (uMask
& infoPtr
->items
[iItem
].mask
& HDI_FORMAT
) {
591 phdi
->fmt
= infoPtr
->items
[iItem
].fmt
;
592 phdi
->mask
|= HDI_FORMAT
;
595 if (uMask
& infoPtr
->items
[iItem
].mask
& HDI_WIDTH
) {
596 phdi
->cxy
= infoPtr
->items
[iItem
].cxy
;
597 phdi
->mask
|= HDI_WIDTH
;
600 if (uMask
& infoPtr
->items
[iItem
].mask
& HDI_LPARAM
) {
601 phdi
->lParam
= infoPtr
->items
[iItem
].lParam
;
602 phdi
->mask
|= HDI_LPARAM
;
605 if (uMask
& infoPtr
->items
[iItem
].mask
& HDI_TEXT
) {
606 phdi
->pszText
= infoPtr
->items
[iItem
].pszText
;
607 phdi
->cchTextMax
= infoPtr
->items
[iItem
].cchTextMax
;
608 phdi
->mask
|= HDI_TEXT
;
611 if (uMask
& infoPtr
->items
[iItem
].mask
& HDI_IMAGE
) {
612 phdi
->iImage
= infoPtr
->items
[iItem
].iImage
;
613 phdi
->mask
|= HDI_IMAGE
;
616 if (uMask
& infoPtr
->items
[iItem
].mask
& HDI_ORDER
) {
617 phdi
->iOrder
= infoPtr
->items
[iItem
].iOrder
;
618 phdi
->mask
|= HDI_ORDER
;
626 HEADER_GetItemCount (WND
*wndPtr
)
628 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
630 return (infoPtr
->uNumItem
);
635 HEADER_GetItemRect (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
637 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
641 iItem
= (INT32
)wParam
;
642 lpRect
= (LPRECT32
)lParam
;
644 if ((iItem
< 0) || (iItem
> infoPtr
->uNumItem
- 1))
647 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
648 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
649 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
650 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
657 HEADER_HitTest (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
659 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
661 HEADER_InternalHitTest (wndPtr
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
668 HEADER_InsertItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
670 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
675 phdi
= (HD_ITEMA
*)lParam
;
676 iItem
= (INT32
)wParam
;
678 if (iItem
< 0) return -1;
679 if (iItem
> infoPtr
->uNumItem
)
680 iItem
= infoPtr
->uNumItem
;
682 if (infoPtr
->uNumItem
== 0) {
683 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
684 sizeof (HEADER_ITEM
));
688 HEADER_ITEM
*oldItems
= infoPtr
->items
;
691 infoPtr
->items
= HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
692 sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
693 /* pre insert copy */
695 memcpy (&infoPtr
->items
[0], &oldItems
[0],
696 iItem
* sizeof(HEADER_ITEM
));
699 /* post insert copy */
700 if (iItem
< infoPtr
->uNumItem
- 1) {
701 memcpy (&infoPtr
->items
[iItem
+1], &oldItems
[iItem
],
702 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
705 HeapFree (GetProcessHeap (), 0, oldItems
);
708 infoPtr
->items
[iItem
].bDown
= FALSE
;
710 infoPtr
->items
[iItem
].mask
= phdi
->mask
;
711 if (phdi
->mask
& HDI_WIDTH
)
712 infoPtr
->items
[iItem
].cxy
= phdi
->cxy
;
714 if (phdi
->mask
& HDI_TEXT
) {
715 len
= lstrlen32A (phdi
->pszText
);
716 infoPtr
->items
[iItem
].pszText
=
717 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, len
+1);
718 lstrcpy32A (infoPtr
->items
[iItem
].pszText
, phdi
->pszText
);
719 infoPtr
->items
[iItem
].cchTextMax
= phdi
->cchTextMax
;
722 if (phdi
->mask
& HDI_FORMAT
)
723 infoPtr
->items
[iItem
].fmt
= phdi
->fmt
;
725 if (phdi
->mask
& HDI_BITMAP
)
726 infoPtr
->items
[iItem
].hbm
= phdi
->hbm
;
728 if (phdi
->mask
& HDI_LPARAM
)
729 infoPtr
->items
[iItem
].lParam
= phdi
->lParam
;
731 if (phdi
->mask
& HDI_IMAGE
)
732 infoPtr
->items
[iItem
].iImage
= phdi
->iImage
;
734 if (phdi
->mask
& HDI_ORDER
)
735 infoPtr
->items
[iItem
].iOrder
= phdi
->iOrder
;
737 HEADER_SetItemBounds (wndPtr
);
739 hdc
= GetDC32 (wndPtr
->hwndSelf
);
740 HEADER_Refresh (wndPtr
, hdc
);
741 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
748 HEADER_Layout (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
750 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
751 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
753 lpLayout
->pwpos
->hwnd
= wndPtr
->hwndSelf
;
754 lpLayout
->pwpos
->hwndInsertAfter
= 0;
755 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
756 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
757 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
758 if (wndPtr
->dwStyle
& HDS_HIDDEN
)
759 lpLayout
->pwpos
->cy
= 0;
761 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
762 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
764 TRACE (header
, "Layout x=%d y=%d cx=%d cy=%d\n",
765 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
766 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
768 HEADER_ForceItemBounds (wndPtr
, lpLayout
->pwpos
->cy
);
771 #ifdef __HDM_LAYOUT_HACK__
772 MoveWindow32 (lpLayout
->pwpos
->hwnd
, lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
773 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
, TRUE
);
781 HEADER_SetImageList (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
783 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
786 himlOld
= infoPtr
->himl
;
787 infoPtr
->himl
= (HIMAGELIST
)lParam
;
789 /* FIXME: Refresh needed??? */
791 return (LRESULT
)himlOld
;
796 HEADER_SetItem32A (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
798 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
803 phdi
= (HD_ITEMA
*)lParam
;
804 iItem
= (INT32
)wParam
;
806 if ((iItem
< 0) || (iItem
> infoPtr
->uNumItem
- 1))
809 TRACE (header
, "[iItem=%d]\n", iItem
);
811 if (HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGING32A
, iItem
))
814 if (phdi
->mask
& HDI_BITMAP
) {
815 infoPtr
->items
[iItem
].hbm
= phdi
->hbm
;
816 infoPtr
->items
[iItem
].mask
|= HDI_BITMAP
;
819 if (phdi
->mask
& HDI_FORMAT
) {
820 infoPtr
->items
[iItem
].fmt
= phdi
->fmt
;
821 infoPtr
->items
[iItem
].mask
|= HDI_FORMAT
;
824 if (phdi
->mask
& HDI_LPARAM
) {
825 infoPtr
->items
[iItem
].lParam
= phdi
->lParam
;
826 infoPtr
->items
[iItem
].mask
|= HDI_LPARAM
;
829 if (phdi
->mask
& HDI_TEXT
) {
830 INT32 len
= lstrlen32A (phdi
->pszText
);
831 if (infoPtr
->items
[iItem
].pszText
)
832 HeapFree (GetProcessHeap (), 0, infoPtr
->items
[iItem
].pszText
);
833 infoPtr
->items
[iItem
].pszText
=
834 HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
, len
+1);
835 lstrcpy32A (infoPtr
->items
[iItem
].pszText
, phdi
->pszText
);
836 infoPtr
->items
[iItem
].cchTextMax
= phdi
->cchTextMax
;
839 if (phdi
->mask
& HDI_WIDTH
) {
840 infoPtr
->items
[iItem
].cxy
= phdi
->cxy
;
841 infoPtr
->items
[iItem
].mask
|= HDI_WIDTH
;
844 if (phdi
->mask
& HDI_IMAGE
) {
845 infoPtr
->items
[iItem
].iImage
= phdi
->iImage
;
846 infoPtr
->items
[iItem
].mask
|= HDI_IMAGE
;
849 if (phdi
->mask
& HDI_ORDER
) {
850 infoPtr
->items
[iItem
].iOrder
= phdi
->iOrder
;
851 infoPtr
->items
[iItem
].mask
|= HDI_ORDER
;
854 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGED32A
, iItem
);
856 HEADER_SetItemBounds (wndPtr
);
857 hdc
= GetDC32 (wndPtr
->hwndSelf
);
858 HEADER_Refresh (wndPtr
, hdc
);
859 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
866 HEADER_Create (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
868 HEADER_INFO
*infoPtr
;
873 infoPtr
= (HEADER_INFO
*)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY
,
874 sizeof(HEADER_INFO
));
875 wndPtr
->wExtra
[0] = (DWORD
)infoPtr
;
877 infoPtr
->uNumItem
= 0;
878 infoPtr
->nHeight
= 20;
881 infoPtr
->hcurArrow
= LoadCursor32A (0, IDC_ARROW32A
);
882 infoPtr
->hcurDivider
= LoadCursor32A (0, IDC_SIZEWE32A
);
883 infoPtr
->hcurDivopen
= LoadCursor32A (0, IDC_SIZENS32A
);
884 infoPtr
->bPressed
= FALSE
;
885 infoPtr
->bTracking
= FALSE
;
886 infoPtr
->iMoveItem
= 0;
888 infoPtr
->iHotItem
= -1;
891 hOldFont
= SelectObject32 (hdc
, GetStockObject32 (SYSTEM_FONT
));
892 GetTextMetrics32A (hdc
, &tm
);
893 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
894 SelectObject32 (hdc
, hOldFont
);
895 ReleaseDC32 (0, hdc
);
902 HEADER_Destroy (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
904 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
907 if (infoPtr
->items
) {
908 for (iItem
= 0; iItem
< infoPtr
->uNumItem
; iItem
++) {
909 if (infoPtr
->items
[iItem
].pszText
)
910 HeapFree (GetProcessHeap (), 0, infoPtr
->items
[iItem
].pszText
);
912 HeapFree (GetProcessHeap (), 0, infoPtr
->items
);
916 ImageList_Destroy (infoPtr
->himl
);
918 HeapFree (GetProcessHeap (), 0, infoPtr
);
925 HEADER_GetFont (WND
*wndPtr
)
927 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
929 return (LRESULT
)infoPtr
->hFont
;
934 HEADER_LButtonDblClk (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
940 pt
.x
= (INT32
)LOWORD(lParam
);
941 pt
.y
= (INT32
)HIWORD(lParam
);
942 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &iItem
);
944 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
945 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMDBLCLICK32A
, iItem
);
946 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
947 HEADER_SendHeaderNotify (wndPtr
, HDN_DIVIDERDBLCLICK32A
, iItem
);
954 HEADER_LButtonDown (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
956 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
962 pt
.x
= (INT32
)LOWORD(lParam
);
963 pt
.y
= (INT32
)HIWORD(lParam
);
964 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &iItem
);
966 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
967 SetCapture32 (wndPtr
->hwndSelf
);
968 infoPtr
->bCaptured
= TRUE
;
969 infoPtr
->bPressed
= TRUE
;
970 infoPtr
->iMoveItem
= iItem
;
972 infoPtr
->items
[iItem
].bDown
= TRUE
;
974 /* Send WM_CUSTOMDRAW */
975 hdc
= GetDC32 (wndPtr
->hwndSelf
);
976 HEADER_RefreshItem (wndPtr
, hdc
, iItem
);
977 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
979 TRACE (header
, "Pressed item %d!\n", iItem
);
981 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
982 if (!(HEADER_SendHeaderNotify (wndPtr
, HDN_BEGINTRACK32A
, iItem
))) {
983 SetCapture32 (wndPtr
->hwndSelf
);
984 infoPtr
->bCaptured
= TRUE
;
985 infoPtr
->bTracking
= TRUE
;
986 infoPtr
->iMoveItem
= iItem
;
987 infoPtr
->nOldWidth
= infoPtr
->items
[iItem
].cxy
;
988 infoPtr
->xTrackOffset
= infoPtr
->items
[iItem
].rect
.right
- pt
.x
;
990 if (!(wndPtr
->dwStyle
& HDS_FULLDRAG
)) {
991 infoPtr
->xOldTrack
= infoPtr
->items
[iItem
].rect
.right
;
992 hdc
= GetDC32 (wndPtr
->hwndSelf
);
993 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
994 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
997 TRACE (header
, "Begin tracking item %d!\n", iItem
);
1006 HEADER_LButtonUp (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1008 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
1011 INT32 iItem
, nWidth
;
1014 pt
.x
= (INT32
)LOWORD(lParam
);
1015 pt
.y
= (INT32
)HIWORD(lParam
);
1016 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &iItem
);
1018 if (infoPtr
->bPressed
) {
1019 if ((iItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1020 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1021 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1022 HEADER_RefreshItem (wndPtr
, hdc
, infoPtr
->iMoveItem
);
1023 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1025 HEADER_SendClickNotify (wndPtr
, HDN_ITEMCLICK32A
, infoPtr
->iMoveItem
);
1027 TRACE (header
, "Released item %d!\n", infoPtr
->iMoveItem
);
1028 infoPtr
->bPressed
= FALSE
;
1030 else if (infoPtr
->bTracking
) {
1031 TRACE (header
, "End tracking item %d!\n", infoPtr
->iMoveItem
);
1032 infoPtr
->bTracking
= FALSE
;
1034 HEADER_SendHeaderNotify (wndPtr
, HDN_ENDTRACK32A
, infoPtr
->iMoveItem
);
1036 if (!(wndPtr
->dwStyle
& HDS_FULLDRAG
)) {
1037 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1038 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
1039 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1040 if (HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGING32A
, infoPtr
->iMoveItem
))
1041 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1043 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+
1044 infoPtr
->xTrackOffset
;
1047 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1048 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGED32A
, infoPtr
->iMoveItem
);
1051 HEADER_SetItemBounds (wndPtr
);
1052 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1053 HEADER_Refresh (wndPtr
, hdc
);
1054 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1058 if (infoPtr
->bCaptured
) {
1059 infoPtr
->bCaptured
= FALSE
;
1061 HEADER_SendSimpleNotify (wndPtr
, NM_RELEASEDCAPTURE
);
1069 HEADER_MouseMove (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1071 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
1074 INT32 iItem
, nWidth
;
1077 pt
.x
= (INT32
)LOWORD(lParam
);
1078 pt
.y
= (INT32
)HIWORD(lParam
);
1079 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &iItem
);
1081 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (wndPtr
->dwStyle
& HDS_HOTTRACK
)) {
1082 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1083 infoPtr
->iHotItem
= iItem
;
1085 infoPtr
->iHotItem
= -1;
1086 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1087 HEADER_Refresh (wndPtr
, hdc
);
1088 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1091 if (infoPtr
->bCaptured
) {
1092 if (infoPtr
->bPressed
) {
1093 if ((iItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1094 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1096 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1097 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1098 HEADER_RefreshItem (wndPtr
, hdc
, infoPtr
->iMoveItem
);
1099 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1101 TRACE (header
, "Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1103 else if (infoPtr
->bTracking
) {
1104 if (wndPtr
->dwStyle
& HDS_FULLDRAG
) {
1105 if (HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGING32A
, infoPtr
->iMoveItem
))
1106 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1108 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+
1109 infoPtr
->xTrackOffset
;
1112 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1113 HEADER_SendHeaderNotify (wndPtr
, HDN_ITEMCHANGED32A
,
1114 infoPtr
->iMoveItem
);
1116 HEADER_SetItemBounds (wndPtr
);
1117 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1118 HEADER_Refresh (wndPtr
, hdc
);
1119 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1122 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1123 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
1124 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1125 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1126 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1127 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1128 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1129 HEADER_DrawTrackLine (wndPtr
, hdc
, infoPtr
->xOldTrack
);
1130 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1133 HEADER_SendHeaderNotify (wndPtr
, HDN_TRACK32A
, infoPtr
->iMoveItem
);
1134 TRACE (header
, "Tracking item %d!\n", infoPtr
->iMoveItem
);
1138 if ((wndPtr
->dwStyle
& HDS_BUTTONS
) && (wndPtr
->dwStyle
& HDS_HOTTRACK
)) {
1139 FIXME (header
, "hot track support!\n");
1147 HEADER_Paint (WND
*wndPtr
, WPARAM32 wParam
)
1152 hdc
= wParam
==0 ? BeginPaint32 (wndPtr
->hwndSelf
, &ps
) : (HDC32
)wParam
;
1153 HEADER_Refresh (wndPtr
, hdc
);
1155 EndPaint32 (wndPtr
->hwndSelf
, &ps
);
1161 HEADER_RButtonUp (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1163 return HEADER_SendSimpleNotify (wndPtr
, NM_RCLICK
);
1168 HEADER_SetCursor (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1170 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
1175 TRACE (header
, "code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1177 GetCursorPos32 (&pt
);
1178 ScreenToClient32 (wndPtr
->hwndSelf
, &pt
);
1180 HEADER_InternalHitTest (wndPtr
, &pt
, &flags
, &iItem
);
1182 if (flags
== HHT_ONDIVIDER
)
1183 SetCursor32 (infoPtr
->hcurDivider
);
1184 else if (flags
== HHT_ONDIVOPEN
)
1185 SetCursor32 (infoPtr
->hcurDivopen
);
1187 SetCursor32 (infoPtr
->hcurArrow
);
1194 HEADER_SetFont (WND
*wndPtr
, WPARAM32 wParam
, LPARAM lParam
)
1196 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(wndPtr
);
1198 HFONT32 hFont
, hOldFont
;
1201 infoPtr
->hFont
= (HFONT32
)wParam
;
1203 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject32 (SYSTEM_FONT
);
1206 hOldFont
= SelectObject32 (hdc
, hFont
);
1207 GetTextMetrics32A (hdc
, &tm
);
1208 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1209 SelectObject32 (hdc
, hOldFont
);
1210 ReleaseDC32 (0, hdc
);
1213 HEADER_ForceItemBounds (wndPtr
, infoPtr
->nHeight
);
1214 hdc
= GetDC32 (wndPtr
->hwndSelf
);
1215 HEADER_Refresh (wndPtr
, hdc
);
1216 ReleaseDC32 (wndPtr
->hwndSelf
, hdc
);
1224 HeaderWindowProc (HWND32 hwnd
, UINT32 msg
, WPARAM32 wParam
, LPARAM lParam
)
1226 WND
*wndPtr
= WIN_FindWndPtr(hwnd
);
1229 case HDM_CREATEDRAGIMAGE
:
1230 return HEADER_CreateDragImage (wndPtr
, wParam
);
1232 case HDM_DELETEITEM
:
1233 return HEADER_DeleteItem (wndPtr
, wParam
);
1235 case HDM_GETIMAGELIST
:
1236 return HEADER_GetImageList (wndPtr
);
1238 case HDM_GETITEM32A
:
1239 return HEADER_GetItem32A (wndPtr
, wParam
, lParam
);
1241 case HDM_GETITEMCOUNT
:
1242 return HEADER_GetItemCount (wndPtr
);
1244 case HDM_GETITEMRECT
:
1245 return HEADER_GetItemRect (wndPtr
, wParam
, lParam
);
1248 return HEADER_HitTest (wndPtr
, wParam
, lParam
);
1250 case HDM_INSERTITEM32A
:
1251 return HEADER_InsertItem32A (wndPtr
, wParam
, lParam
);
1254 return HEADER_Layout (wndPtr
, wParam
, lParam
);
1256 case HDM_SETIMAGELIST
:
1257 return HEADER_SetImageList (wndPtr
, wParam
, lParam
);
1259 case HDM_SETITEM32A
:
1260 return HEADER_SetItem32A (wndPtr
, wParam
, lParam
);
1264 return HEADER_Create (wndPtr
, wParam
, lParam
);
1267 return HEADER_Destroy (wndPtr
, wParam
, lParam
);
1273 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1276 return HEADER_GetFont (wndPtr
);
1278 case WM_LBUTTONDBLCLK
:
1279 return HEADER_LButtonDblClk (wndPtr
, wParam
, lParam
);
1281 case WM_LBUTTONDOWN
:
1282 return HEADER_LButtonDown (wndPtr
, wParam
, lParam
);
1285 return HEADER_LButtonUp (wndPtr
, wParam
, lParam
);
1288 return HEADER_MouseMove (wndPtr
, wParam
, lParam
);
1291 return HEADER_Paint (wndPtr
, wParam
);
1294 return HEADER_RButtonUp (wndPtr
, wParam
, lParam
);
1297 return HEADER_SetCursor (wndPtr
, wParam
, lParam
);
1300 return HEADER_SetFont (wndPtr
, wParam
, lParam
);
1304 ERR (header
, "unknown msg %04x wp=%04x lp=%08lx\n",
1305 msg
, wParam
, lParam
);
1306 return DefWindowProc32A (hwnd
, msg
, wParam
, lParam
);
1312 void HEADER_Register( void )
1314 WNDCLASS32A wndClass
;
1316 if (GlobalFindAtom32A (WC_HEADER32A
)) return;
1318 ZeroMemory (&wndClass
, sizeof(WNDCLASS32A
));
1319 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1320 wndClass
.lpfnWndProc
= (WNDPROC32
)HeaderWindowProc
;
1321 wndClass
.cbClsExtra
= 0;
1322 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1323 wndClass
.hCursor
= LoadCursor32A (0, IDC_ARROW32A
);
1324 wndClass
.lpszClassName
= WC_HEADER32A
;
1326 RegisterClass32A (&wndClass
);