4 * Copyright 1998 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * - Imagelist support (partially).
23 * - Callback items (under construction).
24 * - Hottrack support (partially).
25 * - Custom draw support (including Notifications).
26 * - Drag and Drop support (including Notifications).
28 * - Use notification format
29 * - Correct the order maintenance code to preserve valid order
32 * - Little flaw when drawing a bitmap on the right side of the text.
40 #include "wine/unicode.h"
46 #include "imagelist.h"
47 #include "wine/debug.h"
49 WINE_DEFAULT_DEBUG_CHANNEL(header
);
59 INT iOrder
; /* see documentation of HD_ITEM */
61 BOOL bDown
; /* is item pressed? (used for drawing) */
62 RECT rect
; /* bounding rectangle of the item */
68 HWND hwndNotify
; /* Owner window to send notifications to */
69 INT nNotifyFormat
; /* format used for WM_NOTIFY messages */
70 UINT uNumItem
; /* number of items (columns) */
71 INT nHeight
; /* height of the header (pixels) */
72 HFONT hFont
; /* handle to the current font */
73 HCURSOR hcurArrow
; /* handle to the arrow cursor */
74 HCURSOR hcurDivider
; /* handle to a cursor (used over dividers) <-|-> */
75 HCURSOR hcurDivopen
; /* handle to a cursor (used over dividers) <-||-> */
76 BOOL bCaptured
; /* Is the mouse captured? */
77 BOOL bPressed
; /* Is a header item pressed (down)? */
78 BOOL bTracking
; /* Is in tracking mode? */
79 BOOL bUnicode
; /* Unicode flag */
80 INT iMoveItem
; /* index of tracked item. (Tracking mode) */
81 INT xTrackOffset
; /* distance between the right side of the tracked item and the cursor */
82 INT xOldTrack
; /* track offset (see above) after the last WM_MOUSEMOVE */
83 INT nOldWidth
; /* width of a sizing item after the last WM_MOUSEMOVE */
84 INT iHotItem
; /* index of hot item (cursor is over this item) */
86 HIMAGELIST himl
; /* handle to a image list (may be 0) */
87 HEADER_ITEM
*items
; /* pointer to array of HEADER_ITEM's */
88 BOOL bRectsValid
; /* validity flag for bounding rectangles */
93 #define DIVIDER_WIDTH 10
95 #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongA(hwnd,0))
99 HEADER_IndexToOrder (HWND hwnd
, INT iItem
)
101 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
102 HEADER_ITEM
*lpItem
= &infoPtr
->items
[iItem
];
103 return lpItem
->iOrder
;
108 HEADER_OrderToIndex(HWND hwnd
, WPARAM wParam
)
110 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
111 INT i
,iorder
= (INT
)wParam
;
114 if ((iorder
<0) || iorder
>infoPtr
->uNumItem
)
116 for (i
=0; i
<infoPtr
->uNumItem
; i
++)
117 if (HEADER_IndexToOrder(hwnd
,i
) == iorder
)
123 HEADER_SetItemBounds (HWND hwnd
)
125 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
130 infoPtr
->bRectsValid
= TRUE
;
132 if (infoPtr
->uNumItem
== 0)
135 GetClientRect (hwnd
, &rect
);
138 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
139 phdi
= &infoPtr
->items
[HEADER_OrderToIndex(hwnd
,i
)];
140 phdi
->rect
.top
= rect
.top
;
141 phdi
->rect
.bottom
= rect
.bottom
;
143 phdi
->rect
.right
= phdi
->rect
.left
+ ((phdi
->cxy
>0)?phdi
->cxy
:0);
144 x
= phdi
->rect
.right
;
149 HEADER_Size (HWND hwnd
, WPARAM wParam
)
151 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
153 infoPtr
->bRectsValid
= FALSE
;
160 HEADER_DrawItem (HWND hwnd
, HDC hdc
, INT iItem
, BOOL bHotTrack
)
162 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
163 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
167 TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem
, bHotTrack
, infoPtr
->bUnicode
);
169 if (!infoPtr
->bRectsValid
)
170 HEADER_SetItemBounds(hwnd
);
173 if (r
.right
- r
.left
== 0)
174 return phdi
->rect
.right
;
176 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) {
178 DrawEdge (hdc
, &r
, BDR_RAISEDOUTER
,
179 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
184 DrawEdge (hdc
, &r
, EDGE_RAISED
,
185 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
188 DrawEdge (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
190 if (phdi
->fmt
& HDF_OWNERDRAW
) {
192 dis
.CtlType
= ODT_HEADER
;
193 dis
.CtlID
= GetWindowLongA (hwnd
, GWL_ID
);
195 dis
.itemAction
= ODA_DRAWENTIRE
;
196 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
200 dis
.itemData
= phdi
->lParam
;
201 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
202 SendMessageA (GetParent (hwnd
), WM_DRAWITEM
,
203 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
204 if (oldBkMode
!= TRANSPARENT
)
205 SetBkMode(hdc
, oldBkMode
);
208 UINT uTextJustify
= DT_LEFT
;
210 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
211 uTextJustify
= DT_CENTER
;
212 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
213 uTextJustify
= DT_RIGHT
;
215 if ((phdi
->fmt
& HDF_BITMAP
) && !(phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
218 INT yD
, yS
, cx
, cy
, rx
, ry
;
220 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
222 ry
= r
.bottom
- r
.top
;
223 rx
= r
.right
- r
.left
;
225 if (ry
>= bmp
.bmHeight
) {
227 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
233 yS
= (bmp
.bmHeight
- ry
) / 2;
237 if (rx
>= bmp
.bmWidth
+ 6) {
244 hdcBitmap
= CreateCompatibleDC (hdc
);
245 SelectObject (hdcBitmap
, phdi
->hbm
);
246 BitBlt (hdc
, r
.left
+ 3, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
247 DeleteDC (hdcBitmap
);
249 r
.left
+= (bmp
.bmWidth
+ 3);
253 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
256 INT xD
, yD
, yS
, cx
, cy
, rx
, ry
, tx
;
259 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
262 DrawTextW (hdc
, phdi
->pszText
, -1,
263 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
264 tx
= textRect
.right
- textRect
.left
;
265 ry
= r
.bottom
- r
.top
;
266 rx
= r
.right
- r
.left
;
268 if (ry
>= bmp
.bmHeight
) {
270 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
276 yS
= (bmp
.bmHeight
- ry
) / 2;
280 if (r
.left
+ tx
+ bmp
.bmWidth
+ 9 <= r
.right
) {
282 xD
= r
.left
+ tx
+ 6;
285 if (rx
>= bmp
.bmWidth
+ 6) {
287 xD
= r
.right
- bmp
.bmWidth
- 3;
297 hdcBitmap
= CreateCompatibleDC (hdc
);
298 SelectObject (hdcBitmap
, phdi
->hbm
);
299 BitBlt (hdc
, xD
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
300 DeleteDC (hdcBitmap
);
303 if ((phdi
->fmt
& HDF_IMAGE
) && (infoPtr
->himl
)) {
305 /* FIXME: (r.bottom- (infoPtr->himl->cy))/2 should horicontal center the image
306 It looks like it doesn't work as expected*/
307 ImageList_Draw (infoPtr
->himl
, phdi
->iImage
,hdc
,r
.left
, (r
.bottom
- (infoPtr
->himl
->cy
))/2,0);
308 r
.left
+= infoPtr
->himl
->cx
;
311 if (((phdi
->fmt
& HDF_STRING
)
312 || (!(phdi
->fmt
& (HDF_OWNERDRAW
|HDF_STRING
|HDF_BITMAP
|
313 HDF_BITMAP_ON_RIGHT
|HDF_IMAGE
)))) /* no explicit format specified? */
314 && (phdi
->pszText
)) {
315 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
318 SetTextColor (hdc
, (bHotTrack
) ? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
319 DrawTextW (hdc
, phdi
->pszText
, -1,
320 &r
, uTextJustify
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
321 if (oldBkMode
!= TRANSPARENT
)
322 SetBkMode(hdc
, oldBkMode
);
326 return phdi
->rect
.right
;
331 HEADER_Refresh (HWND hwnd
, HDC hdc
)
333 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
334 HFONT hFont
, hOldFont
;
339 /* get rect for the bar, adjusted for the border */
340 GetClientRect (hwnd
, &rect
);
342 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
343 hOldFont
= SelectObject (hdc
, hFont
);
345 /* draw Background */
346 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
347 FillRect(hdc
, &rect
, hbrBk
);
350 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
351 x
= HEADER_DrawItem (hwnd
, hdc
, HEADER_OrderToIndex(hwnd
,i
), FALSE
);
354 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
356 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
)
357 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
359 DrawEdge (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
362 SelectObject (hdc
, hOldFont
);
367 HEADER_RefreshItem (HWND hwnd
, HDC hdc
, INT iItem
)
369 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
370 HFONT hFont
, hOldFont
;
372 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
373 hOldFont
= SelectObject (hdc
, hFont
);
374 HEADER_DrawItem (hwnd
, hdc
, iItem
, FALSE
);
375 SelectObject (hdc
, hOldFont
);
380 HEADER_InternalHitTest (HWND hwnd
, LPPOINT lpPt
, UINT
*pFlags
, INT
*pItem
)
382 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
387 GetClientRect (hwnd
, &rect
);
391 if (PtInRect (&rect
, *lpPt
))
393 if (infoPtr
->uNumItem
== 0) {
394 *pFlags
|= HHT_NOWHERE
;
400 /* somewhere inside */
401 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
402 rect
= infoPtr
->items
[iCount
].rect
;
403 width
= rect
.right
- rect
.left
;
408 if (PtInRect (&rect
, *lpPt
)) {
409 if (width
<= 2 * DIVIDER_WIDTH
) {
410 *pFlags
|= HHT_ONHEADER
;
412 TRACE("ON HEADER %d\n", iCount
);
417 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
418 if (PtInRect (&rcTest
, *lpPt
)) {
420 *pFlags
|= HHT_ONDIVOPEN
;
422 TRACE("ON DIVOPEN %d\n", *pItem
);
426 *pFlags
|= HHT_ONDIVIDER
;
428 TRACE("ON DIVIDER %d\n", *pItem
);
434 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
435 if (PtInRect (&rcTest
, *lpPt
)) {
436 *pFlags
|= HHT_ONDIVIDER
;
438 TRACE("ON DIVIDER %d\n", *pItem
);
442 *pFlags
|= HHT_ONHEADER
;
444 TRACE("ON HEADER %d\n", iCount
);
449 /* check for last divider part (on nowhere) */
450 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
451 rect
.left
= rect
.right
;
452 rect
.right
+= DIVIDER_WIDTH
;
453 if (PtInRect (&rect
, *lpPt
)) {
455 *pFlags
|= HHT_ONDIVOPEN
;
456 *pItem
= infoPtr
->uNumItem
- 1;
457 TRACE("ON DIVOPEN %d\n", *pItem
);
461 *pFlags
|= HHT_ONDIVIDER
;
462 *pItem
= infoPtr
->uNumItem
-1;
463 TRACE("ON DIVIDER %d\n", *pItem
);
468 *pFlags
|= HHT_NOWHERE
;
475 if (lpPt
->x
< rect
.left
) {
477 *pFlags
|= HHT_TOLEFT
;
479 else if (lpPt
->x
> rect
.right
) {
481 *pFlags
|= HHT_TORIGHT
;
484 if (lpPt
->y
< rect
.top
) {
486 *pFlags
|= HHT_ABOVE
;
488 else if (lpPt
->y
> rect
.bottom
) {
490 *pFlags
|= HHT_BELOW
;
495 TRACE("flags=0x%X\n", *pFlags
);
501 HEADER_DrawTrackLine (HWND hwnd
, HDC hdc
, INT x
)
507 GetClientRect (hwnd
, &rect
);
509 hOldPen
= SelectObject (hdc
, GetStockObject (BLACK_PEN
));
510 oldRop
= SetROP2 (hdc
, R2_XORPEN
);
511 MoveToEx (hdc
, x
, rect
.top
, NULL
);
512 LineTo (hdc
, x
, rect
.bottom
);
513 SetROP2 (hdc
, oldRop
);
514 SelectObject (hdc
, hOldPen
);
519 HEADER_SendSimpleNotify (HWND hwnd
, UINT code
)
521 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
524 nmhdr
.hwndFrom
= hwnd
;
525 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
528 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
529 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
533 HEADER_SendHeaderNotify (HWND hwnd
, UINT code
, INT iItem
, INT mask
)
535 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
539 nmhdr
.hdr
.hwndFrom
= hwnd
;
540 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
541 nmhdr
.hdr
.code
= code
;
544 nmhdr
.pitem
= &nmitem
;
546 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
547 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
548 nmitem
.pszText
= NULL
;
549 nmitem
.cchTextMax
= 0;
550 /* nmitem.pszText = infoPtr->items[iItem].pszText; */
551 /* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
552 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
553 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
554 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
555 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
557 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
558 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
563 HEADER_SendClickNotify (HWND hwnd
, UINT code
, INT iItem
)
565 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
568 nmhdr
.hdr
.hwndFrom
= hwnd
;
569 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
570 nmhdr
.hdr
.code
= code
;
575 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
576 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
581 HEADER_CreateDragImage (HWND hwnd
, WPARAM wParam
)
583 FIXME("empty stub!\n");
589 HEADER_DeleteItem (HWND hwnd
, WPARAM wParam
)
591 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
592 INT iItem
= (INT
)wParam
;
594 TRACE("[iItem=%d]\n", iItem
);
596 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
599 if (infoPtr
->uNumItem
== 1) {
600 TRACE("Simple delete!\n");
601 if (infoPtr
->items
[0].pszText
)
602 Free (infoPtr
->items
[0].pszText
);
603 Free (infoPtr
->items
);
605 infoPtr
->uNumItem
= 0;
608 HEADER_ITEM
*oldItems
= infoPtr
->items
;
612 TRACE("Complex delete! [iItem=%d]\n", iItem
);
614 if (infoPtr
->items
[iItem
].pszText
)
615 Free (infoPtr
->items
[iItem
].pszText
);
616 iOrder
= infoPtr
->items
[iItem
].iOrder
;
619 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
620 /* pre delete copy */
622 memcpy (&infoPtr
->items
[0], &oldItems
[0],
623 iItem
* sizeof(HEADER_ITEM
));
626 /* post delete copy */
627 if (iItem
< infoPtr
->uNumItem
) {
628 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
629 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
632 /* Correct the orders */
633 for (i
=infoPtr
->uNumItem
, pItem
= infoPtr
->items
; i
; i
--, pItem
++)
635 if (pItem
->iOrder
> iOrder
)
641 HEADER_SetItemBounds (hwnd
);
643 InvalidateRect(hwnd
, NULL
, FALSE
);
650 HEADER_GetImageList (HWND hwnd
)
652 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
654 return (LRESULT
)infoPtr
->himl
;
659 HEADER_GetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
661 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
662 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
663 INT nItem
= (INT
)wParam
;
668 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
671 TRACE("[nItem=%d]\n", nItem
);
676 lpItem
= &infoPtr
->items
[nItem
];
677 if (phdi
->mask
& HDI_BITMAP
)
678 phdi
->hbm
= lpItem
->hbm
;
680 if (phdi
->mask
& HDI_FORMAT
)
681 phdi
->fmt
= lpItem
->fmt
;
683 if (phdi
->mask
& HDI_WIDTH
)
684 phdi
->cxy
= lpItem
->cxy
;
686 if (phdi
->mask
& HDI_LPARAM
)
687 phdi
->lParam
= lpItem
->lParam
;
689 if (phdi
->mask
& HDI_TEXT
) {
690 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
692 WideCharToMultiByte (CP_ACP
, 0, lpItem
->pszText
, -1,
693 phdi
->pszText
, phdi
->cchTextMax
, NULL
, NULL
);
698 phdi
->pszText
= LPSTR_TEXTCALLBACKA
;
701 if (phdi
->mask
& HDI_IMAGE
)
702 phdi
->iImage
= lpItem
->iImage
;
704 if (phdi
->mask
& HDI_ORDER
)
705 phdi
->iOrder
= lpItem
->iOrder
;
712 HEADER_GetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
714 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
715 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
716 INT nItem
= (INT
)wParam
;
721 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
724 TRACE("[nItem=%d]\n", nItem
);
729 lpItem
= &infoPtr
->items
[nItem
];
730 if (phdi
->mask
& HDI_BITMAP
)
731 phdi
->hbm
= lpItem
->hbm
;
733 if (phdi
->mask
& HDI_FORMAT
)
734 phdi
->fmt
= lpItem
->fmt
;
736 if (phdi
->mask
& HDI_WIDTH
)
737 phdi
->cxy
= lpItem
->cxy
;
739 if (phdi
->mask
& HDI_LPARAM
)
740 phdi
->lParam
= lpItem
->lParam
;
742 if (phdi
->mask
& HDI_TEXT
) {
743 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
745 lstrcpynW (phdi
->pszText
, lpItem
->pszText
, phdi
->cchTextMax
);
750 phdi
->pszText
= LPSTR_TEXTCALLBACKW
;
753 if (phdi
->mask
& HDI_IMAGE
)
754 phdi
->iImage
= lpItem
->iImage
;
756 if (phdi
->mask
& HDI_ORDER
)
757 phdi
->iOrder
= lpItem
->iOrder
;
763 inline static LRESULT
764 HEADER_GetItemCount (HWND hwnd
)
766 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
767 return infoPtr
->uNumItem
;
772 HEADER_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
774 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
775 INT iItem
= (INT
)wParam
;
776 LPRECT lpRect
= (LPRECT
)lParam
;
778 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
781 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
782 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
783 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
784 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
791 HEADER_GetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
794 LPINT order
= (LPINT
) lParam
;
795 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
797 if ((int)wParam
<infoPtr
->uNumItem
)
799 for (i
=0; i
<(int)wParam
; i
++)
800 *order
++=HEADER_OrderToIndex(hwnd
,i
);
805 HEADER_SetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
808 LPINT order
= (LPINT
) lParam
;
809 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
812 if ((int)wParam
<infoPtr
->uNumItem
)
814 for (i
=0; i
<(int)wParam
; i
++)
816 lpItem
= &infoPtr
->items
[*order
++];
819 infoPtr
->bRectsValid
=0;
820 InvalidateRect(hwnd
, NULL
, FALSE
);
824 inline static LRESULT
825 HEADER_GetUnicodeFormat (HWND hwnd
)
827 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
828 return infoPtr
->bUnicode
;
833 HEADER_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
835 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
837 HEADER_InternalHitTest (hwnd
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
839 if (phti
->flags
== HHT_ONHEADER
)
847 HEADER_InsertItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
849 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
850 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
851 INT nItem
= (INT
)wParam
;
855 if ((phdi
== NULL
) || (nItem
< 0))
858 if (nItem
> infoPtr
->uNumItem
)
859 nItem
= infoPtr
->uNumItem
;
861 iOrder
= (phdi
->mask
& HDI_ORDER
) ? phdi
->iOrder
: nItem
;
863 if (infoPtr
->uNumItem
== 0) {
864 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
));
868 HEADER_ITEM
*oldItems
= infoPtr
->items
;
871 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
873 memcpy (&infoPtr
->items
[1], &oldItems
[0],
874 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
878 /* pre insert copy */
880 memcpy (&infoPtr
->items
[0], &oldItems
[0],
881 nItem
* sizeof(HEADER_ITEM
));
884 /* post insert copy */
885 if (nItem
< infoPtr
->uNumItem
- 1) {
886 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
887 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
894 for (i
=0; i
< infoPtr
->uNumItem
; i
++)
896 if (infoPtr
->items
[i
].iOrder
>= iOrder
)
897 infoPtr
->items
[i
].iOrder
++;
900 lpItem
= &infoPtr
->items
[nItem
];
901 lpItem
->bDown
= FALSE
;
903 if (phdi
->mask
& HDI_WIDTH
)
904 lpItem
->cxy
= phdi
->cxy
;
906 if (phdi
->mask
& HDI_TEXT
) {
907 if (!phdi
->pszText
) /* null pointer check */
909 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
910 len
= MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, NULL
, 0);
911 lpItem
->pszText
= Alloc( len
*sizeof(WCHAR
) );
912 MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, lpItem
->pszText
, len
);
915 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
918 if (phdi
->mask
& HDI_FORMAT
)
919 lpItem
->fmt
= phdi
->fmt
;
921 if (lpItem
->fmt
== 0)
922 lpItem
->fmt
= HDF_LEFT
;
924 if (!(lpItem
->fmt
& HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
926 lpItem
->fmt
|= HDF_STRING
;
928 if (phdi
->mask
& HDI_BITMAP
)
929 lpItem
->hbm
= phdi
->hbm
;
931 if (phdi
->mask
& HDI_LPARAM
)
932 lpItem
->lParam
= phdi
->lParam
;
934 if (phdi
->mask
& HDI_IMAGE
)
935 lpItem
->iImage
= phdi
->iImage
;
937 lpItem
->iOrder
= iOrder
;
939 HEADER_SetItemBounds (hwnd
);
941 InvalidateRect(hwnd
, NULL
, FALSE
);
948 HEADER_InsertItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
950 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
951 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
952 INT nItem
= (INT
)wParam
;
956 if ((phdi
== NULL
) || (nItem
< 0))
959 if (nItem
> infoPtr
->uNumItem
)
960 nItem
= infoPtr
->uNumItem
;
962 iOrder
= (phdi
->mask
& HDI_ORDER
) ? phdi
->iOrder
: nItem
;
964 if (infoPtr
->uNumItem
== 0) {
965 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
));
969 HEADER_ITEM
*oldItems
= infoPtr
->items
;
972 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
974 memcpy (&infoPtr
->items
[1], &oldItems
[0],
975 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
979 /* pre insert copy */
981 memcpy (&infoPtr
->items
[0], &oldItems
[0],
982 nItem
* sizeof(HEADER_ITEM
));
985 /* post insert copy */
986 if (nItem
< infoPtr
->uNumItem
- 1) {
987 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
988 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
995 for (i
=0; i
< infoPtr
->uNumItem
; i
++)
997 if (infoPtr
->items
[i
].iOrder
>= iOrder
)
998 infoPtr
->items
[i
].iOrder
++;
1001 lpItem
= &infoPtr
->items
[nItem
];
1002 lpItem
->bDown
= FALSE
;
1004 if (phdi
->mask
& HDI_WIDTH
)
1005 lpItem
->cxy
= phdi
->cxy
;
1007 if (phdi
->mask
& HDI_TEXT
) {
1008 WCHAR wide_null_char
= 0;
1009 if (!phdi
->pszText
) /* null pointer check */
1010 phdi
->pszText
= &wide_null_char
;
1011 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1012 len
= strlenW (phdi
->pszText
);
1013 lpItem
->pszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1014 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1017 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1020 if (phdi
->mask
& HDI_FORMAT
)
1021 lpItem
->fmt
= phdi
->fmt
;
1023 if (lpItem
->fmt
== 0)
1024 lpItem
->fmt
= HDF_LEFT
;
1026 if (!(lpItem
->fmt
&HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
1028 lpItem
->fmt
|= HDF_STRING
;
1030 if (phdi
->mask
& HDI_BITMAP
)
1031 lpItem
->hbm
= phdi
->hbm
;
1033 if (phdi
->mask
& HDI_LPARAM
)
1034 lpItem
->lParam
= phdi
->lParam
;
1036 if (phdi
->mask
& HDI_IMAGE
)
1037 lpItem
->iImage
= phdi
->iImage
;
1039 lpItem
->iOrder
= iOrder
;
1041 HEADER_SetItemBounds (hwnd
);
1043 InvalidateRect(hwnd
, NULL
, FALSE
);
1050 HEADER_Layout (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1052 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1053 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
1055 lpLayout
->pwpos
->hwnd
= hwnd
;
1056 lpLayout
->pwpos
->hwndInsertAfter
= 0;
1057 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
1058 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
1059 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
1060 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_HIDDEN
)
1061 lpLayout
->pwpos
->cy
= 0;
1063 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
1064 lpLayout
->prc
->top
+= infoPtr
->nHeight
;
1066 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
1068 TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
1069 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
1070 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
1072 infoPtr
->bRectsValid
= FALSE
;
1079 HEADER_SetImageList (HWND hwnd
, HIMAGELIST himl
)
1081 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1084 TRACE("(himl 0x%x)\n", (int)himl
);
1085 himlOld
= infoPtr
->himl
;
1086 infoPtr
->himl
= himl
;
1088 /* FIXME: Refresh needed??? */
1090 return (LRESULT
)himlOld
;
1095 HEADER_SetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1097 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1098 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
1099 INT nItem
= (INT
)wParam
;
1100 HEADER_ITEM
*lpItem
;
1104 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1107 TRACE("[nItem=%d]\n", nItem
);
1109 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, nItem
, phdi
->mask
))
1112 lpItem
= &infoPtr
->items
[nItem
];
1113 if (phdi
->mask
& HDI_BITMAP
)
1114 lpItem
->hbm
= phdi
->hbm
;
1116 if (phdi
->mask
& HDI_FORMAT
)
1117 lpItem
->fmt
= phdi
->fmt
;
1119 if (phdi
->mask
& HDI_LPARAM
)
1120 lpItem
->lParam
= phdi
->lParam
;
1122 if (phdi
->mask
& HDI_TEXT
) {
1123 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
1124 if (lpItem
->pszText
) {
1125 Free (lpItem
->pszText
);
1126 lpItem
->pszText
= NULL
;
1128 if (phdi
->pszText
) {
1129 INT len
= MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,NULL
,0);
1130 lpItem
->pszText
= Alloc( len
*sizeof(WCHAR
) );
1131 MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,lpItem
->pszText
,len
);
1135 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1138 if (phdi
->mask
& HDI_WIDTH
)
1139 lpItem
->cxy
= phdi
->cxy
;
1141 if (phdi
->mask
& HDI_IMAGE
)
1142 lpItem
->iImage
= phdi
->iImage
;
1144 if (phdi
->mask
& HDI_ORDER
)
1146 lpItem
->iOrder
= phdi
->iOrder
;
1149 lpItem
->iOrder
= nItem
;
1151 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGEDA
, nItem
, phdi
->mask
);
1153 HEADER_SetItemBounds (hwnd
);
1155 InvalidateRect(hwnd
, NULL
, FALSE
);
1162 HEADER_SetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1164 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1165 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
1166 INT nItem
= (INT
)wParam
;
1167 HEADER_ITEM
*lpItem
;
1171 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1174 TRACE("[nItem=%d]\n", nItem
);
1176 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
))
1179 lpItem
= &infoPtr
->items
[nItem
];
1180 if (phdi
->mask
& HDI_BITMAP
)
1181 lpItem
->hbm
= phdi
->hbm
;
1183 if (phdi
->mask
& HDI_FORMAT
)
1184 lpItem
->fmt
= phdi
->fmt
;
1186 if (phdi
->mask
& HDI_LPARAM
)
1187 lpItem
->lParam
= phdi
->lParam
;
1189 if (phdi
->mask
& HDI_TEXT
) {
1190 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1191 if (lpItem
->pszText
) {
1192 Free (lpItem
->pszText
);
1193 lpItem
->pszText
= NULL
;
1195 if (phdi
->pszText
) {
1196 INT len
= strlenW (phdi
->pszText
);
1197 lpItem
->pszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1198 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1202 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1205 if (phdi
->mask
& HDI_WIDTH
)
1206 lpItem
->cxy
= phdi
->cxy
;
1208 if (phdi
->mask
& HDI_IMAGE
)
1209 lpItem
->iImage
= phdi
->iImage
;
1211 if (phdi
->mask
& HDI_ORDER
)
1213 lpItem
->iOrder
= phdi
->iOrder
;
1216 lpItem
->iOrder
= nItem
;
1218 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDW
, nItem
, phdi
->mask
);
1220 HEADER_SetItemBounds (hwnd
);
1222 InvalidateRect(hwnd
, NULL
, FALSE
);
1227 inline static LRESULT
1228 HEADER_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
)
1230 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1231 BOOL bTemp
= infoPtr
->bUnicode
;
1233 infoPtr
->bUnicode
= (BOOL
)wParam
;
1240 HEADER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1242 HEADER_INFO
*infoPtr
;
1247 infoPtr
= (HEADER_INFO
*)Alloc (sizeof(HEADER_INFO
));
1248 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1250 infoPtr
->hwndNotify
= GetParent(hwnd
);
1251 infoPtr
->uNumItem
= 0;
1254 infoPtr
->bRectsValid
= FALSE
;
1255 infoPtr
->hcurArrow
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
1256 infoPtr
->hcurDivider
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDER
));
1257 infoPtr
->hcurDivopen
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDEROPEN
));
1258 infoPtr
->bPressed
= FALSE
;
1259 infoPtr
->bTracking
= FALSE
;
1260 infoPtr
->iMoveItem
= 0;
1262 infoPtr
->iHotItem
= -1;
1263 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
1264 infoPtr
->nNotifyFormat
=
1265 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
1268 hOldFont
= SelectObject (hdc
, GetStockObject (SYSTEM_FONT
));
1269 GetTextMetricsA (hdc
, &tm
);
1270 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1271 SelectObject (hdc
, hOldFont
);
1279 HEADER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1281 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1282 HEADER_ITEM
*lpItem
;
1285 if (infoPtr
->items
) {
1286 lpItem
= infoPtr
->items
;
1287 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
1288 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
))
1289 Free (lpItem
->pszText
);
1291 Free (infoPtr
->items
);
1295 ImageList_Destroy (infoPtr
->himl
);
1298 SetWindowLongA (hwnd
, 0, 0);
1303 static inline LRESULT
1304 HEADER_GetFont (HWND hwnd
)
1306 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1308 return (LRESULT
)infoPtr
->hFont
;
1313 HEADER_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1319 pt
.x
= (INT
)LOWORD(lParam
);
1320 pt
.y
= (INT
)HIWORD(lParam
);
1321 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1323 if ((GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
1324 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMDBLCLICKA
, nItem
,0);
1325 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
1326 HEADER_SendHeaderNotify (hwnd
, HDN_DIVIDERDBLCLICKA
, nItem
,0);
1333 HEADER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1335 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1336 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1342 pt
.x
= (INT
)LOWORD(lParam
);
1343 pt
.y
= (INT
)HIWORD(lParam
);
1344 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1346 if ((dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
1348 infoPtr
->bCaptured
= TRUE
;
1349 infoPtr
->bPressed
= TRUE
;
1350 infoPtr
->iMoveItem
= nItem
;
1352 infoPtr
->items
[nItem
].bDown
= TRUE
;
1354 /* Send WM_CUSTOMDRAW */
1356 HEADER_RefreshItem (hwnd
, hdc
, nItem
);
1357 ReleaseDC (hwnd
, hdc
);
1359 TRACE("Pressed item %d!\n", nItem
);
1361 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
1362 if (!(HEADER_SendHeaderNotify (hwnd
, HDN_BEGINTRACKA
, nItem
,0))) {
1364 infoPtr
->bCaptured
= TRUE
;
1365 infoPtr
->bTracking
= TRUE
;
1366 infoPtr
->iMoveItem
= nItem
;
1367 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
1368 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
1370 if (!(dwStyle
& HDS_FULLDRAG
)) {
1371 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
1373 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1374 ReleaseDC (hwnd
, hdc
);
1377 TRACE("Begin tracking item %d!\n", nItem
);
1386 HEADER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1388 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1390 *DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1397 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1398 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1399 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1401 if (infoPtr
->bPressed
) {
1402 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1403 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1405 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1406 ReleaseDC (hwnd
, hdc
);
1408 HEADER_SendClickNotify (hwnd
, HDN_ITEMCLICKA
, infoPtr
->iMoveItem
);
1410 else if (flags
== HHT_ONHEADER
)
1412 HEADER_ITEM
*lpItem
;
1413 INT newindex
= HEADER_IndexToOrder(hwnd
,nItem
);
1414 INT oldindex
= HEADER_IndexToOrder(hwnd
,infoPtr
->iMoveItem
);
1416 TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
1417 infoPtr
->iMoveItem
,oldindex
,nItem
,newindex
);
1418 lpItem
= &infoPtr
->items
[nItem
];
1419 lpItem
->iOrder
=oldindex
;
1421 lpItem
= &infoPtr
->items
[infoPtr
->iMoveItem
];
1422 lpItem
->iOrder
= newindex
;
1424 infoPtr
->bRectsValid
= FALSE
;
1425 InvalidateRect(hwnd
, NULL
, FALSE
);
1426 /* FIXME: Should some WM_NOTIFY be sent */
1429 TRACE("Released item %d!\n", infoPtr
->iMoveItem
);
1430 infoPtr
->bPressed
= FALSE
;
1432 else if (infoPtr
->bTracking
) {
1433 TRACE("End tracking item %d!\n", infoPtr
->iMoveItem
);
1434 infoPtr
->bTracking
= FALSE
;
1436 HEADER_SendHeaderNotify (hwnd
, HDN_ENDTRACKA
, infoPtr
->iMoveItem
,HDI_WIDTH
);
1439 * we want to do this even for HDS_FULLDRAG because this is where
1440 * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications
1442 * if (!(dwStyle & HDS_FULLDRAG)) {
1446 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1447 ReleaseDC (hwnd
, hdc
);
1448 if (HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1450 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1453 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1456 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1459 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1460 HEADER_SetItemBounds (hwnd
);
1461 InvalidateRect(hwnd
, NULL
, FALSE
);
1467 if (infoPtr
->bCaptured
) {
1468 infoPtr
->bCaptured
= FALSE
;
1470 HEADER_SendSimpleNotify (hwnd
, NM_RELEASEDCAPTURE
);
1478 HEADER_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1480 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1485 return infoPtr
->nNotifyFormat
;
1488 infoPtr
->nNotifyFormat
=
1489 SendMessageA ((HWND
)wParam
, WM_NOTIFYFORMAT
,
1490 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1491 return infoPtr
->nNotifyFormat
;
1499 HEADER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1501 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1502 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1508 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1509 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1510 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1512 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1513 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1514 infoPtr
->iHotItem
= nItem
;
1516 infoPtr
->iHotItem
= -1;
1517 InvalidateRect(hwnd
, NULL
, FALSE
);
1520 if (infoPtr
->bCaptured
) {
1521 if (infoPtr
->bPressed
) {
1522 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1523 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1525 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1527 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1528 ReleaseDC (hwnd
, hdc
);
1530 TRACE("Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1532 else if (infoPtr
->bTracking
) {
1533 if (dwStyle
& HDS_FULLDRAG
) {
1534 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1536 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1539 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1540 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1542 HEADER_SetItemBounds (hwnd
);
1543 InvalidateRect(hwnd
, NULL
, FALSE
);
1547 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1548 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1549 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1550 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1551 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1552 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1553 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1554 ReleaseDC (hwnd
, hdc
);
1555 HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1558 TRACE("Tracking item %d!\n", infoPtr
->iMoveItem
);
1562 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1563 FIXME("hot track support!\n");
1571 HEADER_Paint (HWND hwnd
, WPARAM wParam
)
1576 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1577 HEADER_Refresh (hwnd
, hdc
);
1579 EndPaint (hwnd
, &ps
);
1585 HEADER_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1590 pt
.x
= LOWORD(lParam
);
1591 pt
.y
= HIWORD(lParam
);
1593 /* Send a Notify message */
1594 bRet
= HEADER_SendSimpleNotify (hwnd
, NM_RCLICK
);
1596 /* Change to screen coordinate for WM_CONTEXTMENU */
1597 ClientToScreen(hwnd
, &pt
);
1599 /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */
1600 SendMessageA( hwnd
, WM_CONTEXTMENU
, (WPARAM
) hwnd
, MAKELPARAM(pt
.x
, pt
.y
));
1607 HEADER_SetCursor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1609 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1614 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1617 ScreenToClient (hwnd
, &pt
);
1619 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1621 if (flags
== HHT_ONDIVIDER
)
1622 SetCursor (infoPtr
->hcurDivider
);
1623 else if (flags
== HHT_ONDIVOPEN
)
1624 SetCursor (infoPtr
->hcurDivopen
);
1626 SetCursor (infoPtr
->hcurArrow
);
1633 HEADER_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1635 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1637 HFONT hFont
, hOldFont
;
1640 infoPtr
->hFont
= (HFONT
)wParam
;
1642 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
1645 hOldFont
= SelectObject (hdc
, hFont
);
1646 GetTextMetricsA (hdc
, &tm
);
1647 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1648 SelectObject (hdc
, hOldFont
);
1651 infoPtr
->bRectsValid
= FALSE
;
1654 InvalidateRect(hwnd
, NULL
, FALSE
);
1661 static LRESULT WINAPI
1662 HEADER_WindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1664 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1665 if (!HEADER_GetInfoPtr (hwnd
) && (msg
!= WM_CREATE
))
1666 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1668 /* case HDM_CLEARFILTER: */
1670 case HDM_CREATEDRAGIMAGE
:
1671 return HEADER_CreateDragImage (hwnd
, wParam
);
1673 case HDM_DELETEITEM
:
1674 return HEADER_DeleteItem (hwnd
, wParam
);
1676 /* case HDM_EDITFILTER: */
1678 /* case HDM_GETBITMAPMARGIN: */
1680 case HDM_GETIMAGELIST
:
1681 return HEADER_GetImageList (hwnd
);
1684 return HEADER_GetItemA (hwnd
, wParam
, lParam
);
1687 return HEADER_GetItemW (hwnd
, wParam
, lParam
);
1689 case HDM_GETITEMCOUNT
:
1690 return HEADER_GetItemCount (hwnd
);
1692 case HDM_GETITEMRECT
:
1693 return HEADER_GetItemRect (hwnd
, wParam
, lParam
);
1695 case HDM_GETORDERARRAY
:
1696 return HEADER_GetOrderArray(hwnd
, wParam
, lParam
);
1698 case HDM_GETUNICODEFORMAT
:
1699 return HEADER_GetUnicodeFormat (hwnd
);
1702 return HEADER_HitTest (hwnd
, wParam
, lParam
);
1704 case HDM_INSERTITEMA
:
1705 return HEADER_InsertItemA (hwnd
, wParam
, lParam
);
1707 case HDM_INSERTITEMW
:
1708 return HEADER_InsertItemW (hwnd
, wParam
, lParam
);
1711 return HEADER_Layout (hwnd
, wParam
, lParam
);
1713 case HDM_ORDERTOINDEX
:
1714 return HEADER_OrderToIndex(hwnd
, wParam
);
1716 /* case HDM_SETBITMAPMARGIN: */
1718 /* case HDM_SETFILTERCHANGETIMEOUT: */
1720 /* case HDM_SETHOTDIVIDER: */
1722 case HDM_SETIMAGELIST
:
1723 return HEADER_SetImageList (hwnd
, (HIMAGELIST
)lParam
);
1726 return HEADER_SetItemA (hwnd
, wParam
, lParam
);
1729 return HEADER_SetItemW (hwnd
, wParam
, lParam
);
1731 case HDM_SETORDERARRAY
:
1732 return HEADER_SetOrderArray(hwnd
, wParam
, lParam
);
1734 case HDM_SETUNICODEFORMAT
:
1735 return HEADER_SetUnicodeFormat (hwnd
, wParam
);
1738 return HEADER_Create (hwnd
, wParam
, lParam
);
1741 return HEADER_Destroy (hwnd
, wParam
, lParam
);
1747 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1750 return HEADER_GetFont (hwnd
);
1752 case WM_LBUTTONDBLCLK
:
1753 return HEADER_LButtonDblClk (hwnd
, wParam
, lParam
);
1755 case WM_LBUTTONDOWN
:
1756 return HEADER_LButtonDown (hwnd
, wParam
, lParam
);
1759 return HEADER_LButtonUp (hwnd
, wParam
, lParam
);
1762 return HEADER_MouseMove (hwnd
, wParam
, lParam
);
1764 case WM_NOTIFYFORMAT
:
1765 return HEADER_NotifyFormat (hwnd
, wParam
, lParam
);
1768 return HEADER_Size (hwnd
, wParam
);
1771 return HEADER_Paint (hwnd
, wParam
);
1774 return HEADER_RButtonUp (hwnd
, wParam
, lParam
);
1777 return HEADER_SetCursor (hwnd
, wParam
, lParam
);
1780 return HEADER_SetFont (hwnd
, wParam
, lParam
);
1783 if ((msg
>= WM_USER
) && (msg
< WM_APP
))
1784 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1785 msg
, wParam
, lParam
);
1786 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1793 HEADER_Register (void)
1797 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1798 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1799 wndClass
.lpfnWndProc
= (WNDPROC
)HEADER_WindowProc
;
1800 wndClass
.cbClsExtra
= 0;
1801 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1802 wndClass
.hCursor
= LoadCursorA (0, (LPSTR
)IDC_ARROW
);
1803 wndClass
.lpszClassName
= WC_HEADERA
;
1805 RegisterClassA (&wndClass
);
1810 HEADER_Unregister (void)
1812 UnregisterClassA (WC_HEADERA
, NULL
);