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
31 * - Little flaw when drawing a bitmap on the right side of the text.
37 #include "wine/unicode.h"
40 #include "imagelist.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(header
);
53 INT iOrder
; /* see documentation of HD_ITEM */
55 BOOL bDown
; /* is item pressed? (used for drawing) */
56 RECT rect
; /* bounding rectangle of the item */
62 HWND hwndNotify
; /* Owner window to send notifications to */
63 INT nNotifyFormat
; /* format used for WM_NOTIFY messages */
64 UINT uNumItem
; /* number of items (columns) */
65 INT nHeight
; /* height of the header (pixels) */
66 HFONT hFont
; /* handle to the current font */
67 HCURSOR hcurArrow
; /* handle to the arrow cursor */
68 HCURSOR hcurDivider
; /* handle to a cursor (used over dividers) <-|-> */
69 HCURSOR hcurDivopen
; /* handle to a cursor (used over dividers) <-||-> */
70 BOOL bCaptured
; /* Is the mouse captured? */
71 BOOL bPressed
; /* Is a header item pressed (down)? */
72 BOOL bTracking
; /* Is in tracking mode? */
73 BOOL bUnicode
; /* Unicode flag */
74 INT iMoveItem
; /* index of tracked item. (Tracking mode) */
75 INT xTrackOffset
; /* distance between the right side of the tracked item and the cursor */
76 INT xOldTrack
; /* track offset (see above) after the last WM_MOUSEMOVE */
77 INT nOldWidth
; /* width of a sizing item after the last WM_MOUSEMOVE */
78 INT iHotItem
; /* index of hot item (cursor is over this item) */
80 HIMAGELIST himl
; /* handle to a image list (may be 0) */
81 HEADER_ITEM
*items
; /* pointer to array of HEADER_ITEM's */
82 BOOL bRectsValid
; /* validity flag for bounding rectangles */
87 #define DIVIDER_WIDTH 10
89 #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongA(hwnd,0))
93 HEADER_IndexToOrder (HWND hwnd
, INT iItem
)
95 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
96 HEADER_ITEM
*lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[iItem
];
97 return lpItem
->iOrder
;
102 HEADER_OrderToIndex(HWND hwnd
, WPARAM wParam
)
104 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
105 INT i
,iorder
= (INT
)wParam
;
108 if ((iorder
<0) || iorder
>infoPtr
->uNumItem
)
110 for (i
=0; i
<infoPtr
->uNumItem
; i
++)
111 if (HEADER_IndexToOrder(hwnd
,i
) == iorder
)
117 HEADER_SetItemBounds (HWND hwnd
)
119 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
124 infoPtr
->bRectsValid
= TRUE
;
126 if (infoPtr
->uNumItem
== 0)
129 GetClientRect (hwnd
, &rect
);
132 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
133 phdi
= &infoPtr
->items
[HEADER_OrderToIndex(hwnd
,i
)];
134 phdi
->rect
.top
= rect
.top
;
135 phdi
->rect
.bottom
= rect
.bottom
;
137 phdi
->rect
.right
= phdi
->rect
.left
+ ((phdi
->cxy
>0)?phdi
->cxy
:0);
138 x
= phdi
->rect
.right
;
143 HEADER_Size (HWND hwnd
, WPARAM wParam
)
145 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
147 infoPtr
->bRectsValid
= FALSE
;
154 HEADER_DrawItem (HWND hwnd
, HDC hdc
, INT iItem
, BOOL bHotTrack
)
156 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
157 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
161 TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem
, bHotTrack
, infoPtr
->bUnicode
);
163 if (!infoPtr
->bRectsValid
)
164 HEADER_SetItemBounds(hwnd
);
167 if (r
.right
- r
.left
== 0)
168 return phdi
->rect
.right
;
170 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) {
172 DrawEdge (hdc
, &r
, BDR_RAISEDOUTER
,
173 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
178 DrawEdge (hdc
, &r
, EDGE_RAISED
,
179 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
182 DrawEdge (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
184 if (phdi
->fmt
& HDF_OWNERDRAW
) {
186 dis
.CtlType
= ODT_HEADER
;
187 dis
.CtlID
= GetWindowLongA (hwnd
, GWL_ID
);
189 dis
.itemAction
= ODA_DRAWENTIRE
;
190 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
194 dis
.itemData
= phdi
->lParam
;
195 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
196 SendMessageA (GetParent (hwnd
), WM_DRAWITEM
,
197 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
198 if (oldBkMode
!= TRANSPARENT
)
199 SetBkMode(hdc
, oldBkMode
);
202 UINT uTextJustify
= DT_LEFT
;
204 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
205 uTextJustify
= DT_CENTER
;
206 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
207 uTextJustify
= DT_RIGHT
;
209 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->hbm
)) {
212 INT yD
, yS
, cx
, cy
, rx
, ry
;
214 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
216 ry
= r
.bottom
- r
.top
;
217 rx
= r
.right
- r
.left
;
219 if (ry
>= bmp
.bmHeight
) {
221 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
227 yS
= (bmp
.bmHeight
- ry
) / 2;
231 if (rx
>= bmp
.bmWidth
+ 6) {
238 hdcBitmap
= CreateCompatibleDC (hdc
);
239 SelectObject (hdcBitmap
, phdi
->hbm
);
240 BitBlt (hdc
, r
.left
+ 3, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
241 DeleteDC (hdcBitmap
);
243 r
.left
+= (bmp
.bmWidth
+ 3);
247 if ((phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
250 INT xD
, yD
, yS
, cx
, cy
, rx
, ry
, tx
;
253 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
256 if (infoPtr
->bUnicode
)
257 DrawTextW (hdc
, phdi
->pszText
, -1,
258 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
260 DrawTextA (hdc
, (LPCSTR
)phdi
->pszText
, -1,
261 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
262 tx
= textRect
.right
- textRect
.left
;
263 ry
= r
.bottom
- r
.top
;
264 rx
= r
.right
- r
.left
;
266 if (ry
>= bmp
.bmHeight
) {
268 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
274 yS
= (bmp
.bmHeight
- ry
) / 2;
278 if (r
.left
+ tx
+ bmp
.bmWidth
+ 9 <= r
.right
) {
280 xD
= r
.left
+ tx
+ 6;
283 if (rx
>= bmp
.bmWidth
+ 6) {
285 xD
= r
.right
- bmp
.bmWidth
- 3;
295 hdcBitmap
= CreateCompatibleDC (hdc
);
296 SelectObject (hdcBitmap
, phdi
->hbm
);
297 BitBlt (hdc
, xD
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
298 DeleteDC (hdcBitmap
);
301 if ((phdi
->fmt
& HDF_IMAGE
) && (infoPtr
->himl
)) {
303 /* FIXME: (r.bottom- (infoPtr->himl->cy))/2 should horicontal center the image
304 It looks like it doesn't work as expected*/
305 ImageList_Draw (infoPtr
->himl
, phdi
->iImage
,hdc
,r
.left
, (r
.bottom
- (infoPtr
->himl
->cy
))/2,0);
306 r
.left
+= infoPtr
->himl
->cx
;
309 if (((phdi
->fmt
& HDF_STRING
)
310 || (!(phdi
->fmt
& (HDF_OWNERDRAW
|HDF_STRING
|HDF_BITMAP
|
311 HDF_BITMAP_ON_RIGHT
|HDF_IMAGE
)))) /* no explicit format specified? */
312 && (phdi
->pszText
)) {
313 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
316 SetTextColor (hdc
, (bHotTrack
) ? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
317 if (infoPtr
->bUnicode
)
318 DrawTextW (hdc
, phdi
->pszText
, -1,
319 &r
, uTextJustify
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
321 DrawTextA (hdc
, (LPCSTR
)phdi
->pszText
, -1,
322 &r
, uTextJustify
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
323 if (oldBkMode
!= TRANSPARENT
)
324 SetBkMode(hdc
, oldBkMode
);
328 return phdi
->rect
.right
;
333 HEADER_Refresh (HWND hwnd
, HDC hdc
)
335 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
336 HFONT hFont
, hOldFont
;
341 /* get rect for the bar, adjusted for the border */
342 GetClientRect (hwnd
, &rect
);
344 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
345 hOldFont
= SelectObject (hdc
, hFont
);
347 /* draw Background */
348 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
349 FillRect(hdc
, &rect
, hbrBk
);
352 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
353 x
= HEADER_DrawItem (hwnd
, hdc
, HEADER_OrderToIndex(hwnd
,i
), FALSE
);
356 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
358 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
)
359 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
361 DrawEdge (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
364 SelectObject (hdc
, hOldFont
);
369 HEADER_RefreshItem (HWND hwnd
, HDC hdc
, INT iItem
)
371 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
372 HFONT hFont
, hOldFont
;
374 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
375 hOldFont
= SelectObject (hdc
, hFont
);
376 HEADER_DrawItem (hwnd
, hdc
, iItem
, FALSE
);
377 SelectObject (hdc
, hOldFont
);
382 HEADER_InternalHitTest (HWND hwnd
, LPPOINT lpPt
, UINT
*pFlags
, INT
*pItem
)
384 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
389 GetClientRect (hwnd
, &rect
);
393 if (PtInRect (&rect
, *lpPt
))
395 if (infoPtr
->uNumItem
== 0) {
396 *pFlags
|= HHT_NOWHERE
;
402 /* somewhere inside */
403 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
404 rect
= infoPtr
->items
[iCount
].rect
;
405 width
= rect
.right
- rect
.left
;
410 if (PtInRect (&rect
, *lpPt
)) {
411 if (width
<= 2 * DIVIDER_WIDTH
) {
412 *pFlags
|= HHT_ONHEADER
;
414 TRACE("ON HEADER %d\n", iCount
);
419 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
420 if (PtInRect (&rcTest
, *lpPt
)) {
422 *pFlags
|= HHT_ONDIVOPEN
;
424 TRACE("ON DIVOPEN %d\n", *pItem
);
428 *pFlags
|= HHT_ONDIVIDER
;
430 TRACE("ON DIVIDER %d\n", *pItem
);
436 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
437 if (PtInRect (&rcTest
, *lpPt
)) {
438 *pFlags
|= HHT_ONDIVIDER
;
440 TRACE("ON DIVIDER %d\n", *pItem
);
444 *pFlags
|= HHT_ONHEADER
;
446 TRACE("ON HEADER %d\n", iCount
);
451 /* check for last divider part (on nowhere) */
452 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
453 rect
.left
= rect
.right
;
454 rect
.right
+= DIVIDER_WIDTH
;
455 if (PtInRect (&rect
, *lpPt
)) {
457 *pFlags
|= HHT_ONDIVOPEN
;
458 *pItem
= infoPtr
->uNumItem
- 1;
459 TRACE("ON DIVOPEN %d\n", *pItem
);
463 *pFlags
|= HHT_ONDIVIDER
;
464 *pItem
= infoPtr
->uNumItem
-1;
465 TRACE("ON DIVIDER %d\n", *pItem
);
470 *pFlags
|= HHT_NOWHERE
;
477 if (lpPt
->x
< rect
.left
) {
479 *pFlags
|= HHT_TOLEFT
;
481 else if (lpPt
->x
> rect
.right
) {
483 *pFlags
|= HHT_TORIGHT
;
486 if (lpPt
->y
< rect
.top
) {
488 *pFlags
|= HHT_ABOVE
;
490 else if (lpPt
->y
> rect
.bottom
) {
492 *pFlags
|= HHT_BELOW
;
497 TRACE("flags=0x%X\n", *pFlags
);
503 HEADER_DrawTrackLine (HWND hwnd
, HDC hdc
, INT x
)
509 GetClientRect (hwnd
, &rect
);
511 hOldPen
= SelectObject (hdc
, GetStockObject (BLACK_PEN
));
512 oldRop
= SetROP2 (hdc
, R2_XORPEN
);
513 MoveToEx (hdc
, x
, rect
.top
, NULL
);
514 LineTo (hdc
, x
, rect
.bottom
);
515 SetROP2 (hdc
, oldRop
);
516 SelectObject (hdc
, hOldPen
);
521 HEADER_SendSimpleNotify (HWND hwnd
, UINT code
)
523 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
526 nmhdr
.hwndFrom
= hwnd
;
527 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
530 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
531 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
535 HEADER_SendHeaderNotify (HWND hwnd
, UINT code
, INT iItem
, INT mask
)
537 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
541 nmhdr
.hdr
.hwndFrom
= hwnd
;
542 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
543 nmhdr
.hdr
.code
= code
;
546 nmhdr
.pitem
= &nmitem
;
548 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
549 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
550 nmitem
.pszText
= NULL
;
551 nmitem
.cchTextMax
= 0;
552 /* nmitem.pszText = infoPtr->items[iItem].pszText; */
553 /* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
554 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
555 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
556 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
557 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
559 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
560 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
565 HEADER_SendClickNotify (HWND hwnd
, UINT code
, INT iItem
)
567 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
570 nmhdr
.hdr
.hwndFrom
= hwnd
;
571 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
572 nmhdr
.hdr
.code
= code
;
577 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
578 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
583 HEADER_CreateDragImage (HWND hwnd
, WPARAM wParam
)
585 FIXME("empty stub!\n");
591 HEADER_DeleteItem (HWND hwnd
, WPARAM wParam
)
593 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
594 INT iItem
= (INT
)wParam
;
596 TRACE("[iItem=%d]\n", iItem
);
598 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
601 if (infoPtr
->uNumItem
== 1) {
602 TRACE("Simple delete!\n");
603 if (infoPtr
->items
[0].pszText
)
604 COMCTL32_Free (infoPtr
->items
[0].pszText
);
605 COMCTL32_Free (infoPtr
->items
);
607 infoPtr
->uNumItem
= 0;
610 HEADER_ITEM
*oldItems
= infoPtr
->items
;
611 TRACE("Complex delete! [iItem=%d]\n", iItem
);
613 if (infoPtr
->items
[iItem
].pszText
)
614 COMCTL32_Free (infoPtr
->items
[iItem
].pszText
);
617 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
618 /* pre delete copy */
620 memcpy (&infoPtr
->items
[0], &oldItems
[0],
621 iItem
* sizeof(HEADER_ITEM
));
624 /* post delete copy */
625 if (iItem
< infoPtr
->uNumItem
) {
626 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
627 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
630 COMCTL32_Free (oldItems
);
633 HEADER_SetItemBounds (hwnd
);
635 InvalidateRect(hwnd
, NULL
, FALSE
);
642 HEADER_GetImageList (HWND hwnd
)
644 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
646 return (LRESULT
)infoPtr
->himl
;
651 HEADER_GetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
653 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
654 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
655 INT nItem
= (INT
)wParam
;
660 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
663 TRACE("[nItem=%d]\n", nItem
);
668 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
669 if (phdi
->mask
& HDI_BITMAP
)
670 phdi
->hbm
= lpItem
->hbm
;
672 if (phdi
->mask
& HDI_FORMAT
)
673 phdi
->fmt
= lpItem
->fmt
;
675 if (phdi
->mask
& HDI_WIDTH
)
676 phdi
->cxy
= lpItem
->cxy
;
678 if (phdi
->mask
& HDI_LPARAM
)
679 phdi
->lParam
= lpItem
->lParam
;
681 if (phdi
->mask
& HDI_TEXT
) {
682 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
684 WideCharToMultiByte (CP_ACP
, 0, lpItem
->pszText
, -1,
685 phdi
->pszText
, phdi
->cchTextMax
, NULL
, NULL
);
690 phdi
->pszText
= LPSTR_TEXTCALLBACKA
;
693 if (phdi
->mask
& HDI_IMAGE
)
694 phdi
->iImage
= lpItem
->iImage
;
696 if (phdi
->mask
& HDI_ORDER
)
697 phdi
->iOrder
= lpItem
->iOrder
;
704 HEADER_GetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
706 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
707 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
708 INT nItem
= (INT
)wParam
;
713 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
716 TRACE("[nItem=%d]\n", nItem
);
721 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
722 if (phdi
->mask
& HDI_BITMAP
)
723 phdi
->hbm
= lpItem
->hbm
;
725 if (phdi
->mask
& HDI_FORMAT
)
726 phdi
->fmt
= lpItem
->fmt
;
728 if (phdi
->mask
& HDI_WIDTH
)
729 phdi
->cxy
= lpItem
->cxy
;
731 if (phdi
->mask
& HDI_LPARAM
)
732 phdi
->lParam
= lpItem
->lParam
;
734 if (phdi
->mask
& HDI_TEXT
) {
735 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
737 lstrcpynW (phdi
->pszText
, lpItem
->pszText
, phdi
->cchTextMax
);
742 phdi
->pszText
= LPSTR_TEXTCALLBACKW
;
745 if (phdi
->mask
& HDI_IMAGE
)
746 phdi
->iImage
= lpItem
->iImage
;
748 if (phdi
->mask
& HDI_ORDER
)
749 phdi
->iOrder
= lpItem
->iOrder
;
755 inline static LRESULT
756 HEADER_GetItemCount (HWND hwnd
)
758 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
759 return infoPtr
->uNumItem
;
764 HEADER_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
766 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
767 INT iItem
= (INT
)wParam
;
768 LPRECT lpRect
= (LPRECT
)lParam
;
770 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
773 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
774 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
775 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
776 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
783 HEADER_GetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
786 LPINT order
= (LPINT
) lParam
;
787 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
789 if ((int)wParam
<infoPtr
->uNumItem
)
791 for (i
=0; i
<(int)wParam
; i
++)
792 *order
++=HEADER_OrderToIndex(hwnd
,i
);
797 HEADER_SetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
800 LPINT order
= (LPINT
) lParam
;
801 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
804 if ((int)wParam
<infoPtr
->uNumItem
)
806 for (i
=0; i
<(int)wParam
; i
++)
808 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[*order
++];
811 infoPtr
->bRectsValid
=0;
812 InvalidateRect(hwnd
, NULL
, FALSE
);
816 inline static LRESULT
817 HEADER_GetUnicodeFormat (HWND hwnd
)
819 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
820 return infoPtr
->bUnicode
;
825 HEADER_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
827 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
829 HEADER_InternalHitTest (hwnd
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
831 if (phti
->flags
== HHT_ONHEADER
)
839 HEADER_InsertItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
841 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
842 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
843 INT nItem
= (INT
)wParam
;
847 if ((phdi
== NULL
) || (nItem
< 0))
850 if (nItem
> infoPtr
->uNumItem
)
851 nItem
= infoPtr
->uNumItem
;
853 if (infoPtr
->uNumItem
== 0) {
854 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
));
858 HEADER_ITEM
*oldItems
= infoPtr
->items
;
861 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
863 memcpy (&infoPtr
->items
[1], &oldItems
[0],
864 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
868 /* pre insert copy */
870 memcpy (&infoPtr
->items
[0], &oldItems
[0],
871 nItem
* sizeof(HEADER_ITEM
));
874 /* post insert copy */
875 if (nItem
< infoPtr
->uNumItem
- 1) {
876 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
877 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
881 COMCTL32_Free (oldItems
);
884 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
885 lpItem
->bDown
= FALSE
;
887 if (phdi
->mask
& HDI_WIDTH
)
888 lpItem
->cxy
= phdi
->cxy
;
890 if (phdi
->mask
& HDI_TEXT
) {
891 if (!phdi
->pszText
) /* null pointer check */
893 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
894 len
= MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, NULL
, 0);
895 lpItem
->pszText
= COMCTL32_Alloc( len
*sizeof(WCHAR
) );
896 MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, lpItem
->pszText
, len
);
899 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
902 if (phdi
->mask
& HDI_FORMAT
)
903 lpItem
->fmt
= phdi
->fmt
;
905 if (lpItem
->fmt
== 0)
906 lpItem
->fmt
= HDF_LEFT
;
908 if (!(lpItem
->fmt
& HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
910 lpItem
->fmt
|= HDF_STRING
;
912 if (phdi
->mask
& HDI_BITMAP
)
913 lpItem
->hbm
= phdi
->hbm
;
915 if (phdi
->mask
& HDI_LPARAM
)
916 lpItem
->lParam
= phdi
->lParam
;
918 if (phdi
->mask
& HDI_IMAGE
)
919 lpItem
->iImage
= phdi
->iImage
;
921 if (phdi
->mask
& HDI_ORDER
)
923 lpItem
->iOrder
= phdi
->iOrder
;
926 lpItem
->iOrder
=nItem
;
929 HEADER_SetItemBounds (hwnd
);
931 InvalidateRect(hwnd
, NULL
, FALSE
);
938 HEADER_InsertItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
940 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
941 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
942 INT nItem
= (INT
)wParam
;
946 if ((phdi
== NULL
) || (nItem
< 0))
949 if (nItem
> infoPtr
->uNumItem
)
950 nItem
= infoPtr
->uNumItem
;
952 if (infoPtr
->uNumItem
== 0) {
953 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
));
957 HEADER_ITEM
*oldItems
= infoPtr
->items
;
960 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
962 memcpy (&infoPtr
->items
[1], &oldItems
[0],
963 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
967 /* pre insert copy */
969 memcpy (&infoPtr
->items
[0], &oldItems
[0],
970 nItem
* sizeof(HEADER_ITEM
));
973 /* post insert copy */
974 if (nItem
< infoPtr
->uNumItem
- 1) {
975 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
976 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
980 COMCTL32_Free (oldItems
);
983 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
984 lpItem
->bDown
= FALSE
;
986 if (phdi
->mask
& HDI_WIDTH
)
987 lpItem
->cxy
= phdi
->cxy
;
989 if (phdi
->mask
& HDI_TEXT
) {
990 WCHAR wide_null_char
= 0;
991 if (!phdi
->pszText
) /* null pointer check */
992 phdi
->pszText
= &wide_null_char
;
993 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
994 len
= strlenW (phdi
->pszText
);
995 lpItem
->pszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
996 strcpyW (lpItem
->pszText
, phdi
->pszText
);
999 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1002 if (phdi
->mask
& HDI_FORMAT
)
1003 lpItem
->fmt
= phdi
->fmt
;
1005 if (lpItem
->fmt
== 0)
1006 lpItem
->fmt
= HDF_LEFT
;
1008 if (!(lpItem
->fmt
&HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
1010 lpItem
->fmt
|= HDF_STRING
;
1012 if (phdi
->mask
& HDI_BITMAP
)
1013 lpItem
->hbm
= phdi
->hbm
;
1015 if (phdi
->mask
& HDI_LPARAM
)
1016 lpItem
->lParam
= phdi
->lParam
;
1018 if (phdi
->mask
& HDI_IMAGE
)
1019 lpItem
->iImage
= phdi
->iImage
;
1021 if (phdi
->mask
& HDI_ORDER
)
1023 lpItem
->iOrder
= phdi
->iOrder
;
1026 lpItem
->iOrder
= nItem
;
1028 HEADER_SetItemBounds (hwnd
);
1030 InvalidateRect(hwnd
, NULL
, FALSE
);
1037 HEADER_Layout (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1039 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1040 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
1042 lpLayout
->pwpos
->hwnd
= hwnd
;
1043 lpLayout
->pwpos
->hwndInsertAfter
= 0;
1044 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
1045 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
1046 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
1047 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_HIDDEN
)
1048 lpLayout
->pwpos
->cy
= 0;
1050 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
1051 lpLayout
->prc
->top
+= infoPtr
->nHeight
;
1053 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
1055 TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
1056 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
1057 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
1059 infoPtr
->bRectsValid
= FALSE
;
1066 HEADER_SetImageList (HWND hwnd
, HIMAGELIST himl
)
1068 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1071 TRACE("(himl 0x%x)\n", (int)himl
);
1072 himlOld
= infoPtr
->himl
;
1073 infoPtr
->himl
= himl
;
1075 /* FIXME: Refresh needed??? */
1077 return (LRESULT
)himlOld
;
1082 HEADER_SetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1084 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1085 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
1086 INT nItem
= (INT
)wParam
;
1087 HEADER_ITEM
*lpItem
;
1091 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1094 TRACE("[nItem=%d]\n", nItem
);
1096 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, nItem
, phdi
->mask
))
1099 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
1100 if (phdi
->mask
& HDI_BITMAP
)
1101 lpItem
->hbm
= phdi
->hbm
;
1103 if (phdi
->mask
& HDI_FORMAT
)
1104 lpItem
->fmt
= phdi
->fmt
;
1106 if (phdi
->mask
& HDI_LPARAM
)
1107 lpItem
->lParam
= phdi
->lParam
;
1109 if (phdi
->mask
& HDI_TEXT
) {
1110 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
1111 if (lpItem
->pszText
) {
1112 COMCTL32_Free (lpItem
->pszText
);
1113 lpItem
->pszText
= NULL
;
1115 if (phdi
->pszText
) {
1116 INT len
= MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,NULL
,0);
1117 lpItem
->pszText
= COMCTL32_Alloc( len
*sizeof(WCHAR
) );
1118 MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,lpItem
->pszText
,len
);
1122 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1125 if (phdi
->mask
& HDI_WIDTH
)
1126 lpItem
->cxy
= phdi
->cxy
;
1128 if (phdi
->mask
& HDI_IMAGE
)
1129 lpItem
->iImage
= phdi
->iImage
;
1131 if (phdi
->mask
& HDI_ORDER
)
1133 lpItem
->iOrder
= phdi
->iOrder
;
1136 lpItem
->iOrder
= nItem
;
1138 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGEDA
, nItem
, phdi
->mask
);
1140 HEADER_SetItemBounds (hwnd
);
1142 InvalidateRect(hwnd
, NULL
, FALSE
);
1149 HEADER_SetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1151 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1152 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
1153 INT nItem
= (INT
)wParam
;
1154 HEADER_ITEM
*lpItem
;
1158 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1161 TRACE("[nItem=%d]\n", nItem
);
1163 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
))
1166 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
1167 if (phdi
->mask
& HDI_BITMAP
)
1168 lpItem
->hbm
= phdi
->hbm
;
1170 if (phdi
->mask
& HDI_FORMAT
)
1171 lpItem
->fmt
= phdi
->fmt
;
1173 if (phdi
->mask
& HDI_LPARAM
)
1174 lpItem
->lParam
= phdi
->lParam
;
1176 if (phdi
->mask
& HDI_TEXT
) {
1177 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1178 if (lpItem
->pszText
) {
1179 COMCTL32_Free (lpItem
->pszText
);
1180 lpItem
->pszText
= NULL
;
1182 if (phdi
->pszText
) {
1183 INT len
= strlenW (phdi
->pszText
);
1184 lpItem
->pszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1185 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1189 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1192 if (phdi
->mask
& HDI_WIDTH
)
1193 lpItem
->cxy
= phdi
->cxy
;
1195 if (phdi
->mask
& HDI_IMAGE
)
1196 lpItem
->iImage
= phdi
->iImage
;
1198 if (phdi
->mask
& HDI_ORDER
)
1200 lpItem
->iOrder
= phdi
->iOrder
;
1203 lpItem
->iOrder
= nItem
;
1205 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
);
1207 HEADER_SetItemBounds (hwnd
);
1209 InvalidateRect(hwnd
, NULL
, FALSE
);
1214 inline static LRESULT
1215 HEADER_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
)
1217 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1218 BOOL bTemp
= infoPtr
->bUnicode
;
1220 infoPtr
->bUnicode
= (BOOL
)wParam
;
1227 HEADER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1229 HEADER_INFO
*infoPtr
;
1234 infoPtr
= (HEADER_INFO
*)COMCTL32_Alloc (sizeof(HEADER_INFO
));
1235 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1237 infoPtr
->hwndNotify
= GetParent(hwnd
);
1238 infoPtr
->uNumItem
= 0;
1239 infoPtr
->nHeight
= 20;
1242 infoPtr
->bRectsValid
= FALSE
;
1243 infoPtr
->hcurArrow
= LoadCursorA (0, IDC_ARROWA
);
1244 infoPtr
->hcurDivider
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDER
));
1245 infoPtr
->hcurDivopen
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDEROPEN
));
1246 infoPtr
->bPressed
= FALSE
;
1247 infoPtr
->bTracking
= FALSE
;
1248 infoPtr
->iMoveItem
= 0;
1250 infoPtr
->iHotItem
= -1;
1251 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
1252 infoPtr
->nNotifyFormat
=
1253 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
1256 hOldFont
= SelectObject (hdc
, GetStockObject (SYSTEM_FONT
));
1257 GetTextMetricsA (hdc
, &tm
);
1258 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1259 SelectObject (hdc
, hOldFont
);
1267 HEADER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1269 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1270 HEADER_ITEM
*lpItem
;
1273 if (infoPtr
->items
) {
1274 lpItem
= (HEADER_ITEM
*)infoPtr
->items
;
1275 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
1276 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
))
1277 COMCTL32_Free (lpItem
->pszText
);
1279 COMCTL32_Free (infoPtr
->items
);
1283 ImageList_Destroy (infoPtr
->himl
);
1285 COMCTL32_Free (infoPtr
);
1286 SetWindowLongA (hwnd
, 0, 0);
1291 static inline LRESULT
1292 HEADER_GetFont (HWND hwnd
)
1294 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1296 return (LRESULT
)infoPtr
->hFont
;
1301 HEADER_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1307 pt
.x
= (INT
)LOWORD(lParam
);
1308 pt
.y
= (INT
)HIWORD(lParam
);
1309 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1311 if ((GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
1312 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMDBLCLICKA
, nItem
,0);
1313 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
1314 HEADER_SendHeaderNotify (hwnd
, HDN_DIVIDERDBLCLICKA
, nItem
,0);
1321 HEADER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1323 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1324 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1330 pt
.x
= (INT
)LOWORD(lParam
);
1331 pt
.y
= (INT
)HIWORD(lParam
);
1332 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1334 if ((dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
1336 infoPtr
->bCaptured
= TRUE
;
1337 infoPtr
->bPressed
= TRUE
;
1338 infoPtr
->iMoveItem
= nItem
;
1340 infoPtr
->items
[nItem
].bDown
= TRUE
;
1342 /* Send WM_CUSTOMDRAW */
1344 HEADER_RefreshItem (hwnd
, hdc
, nItem
);
1345 ReleaseDC (hwnd
, hdc
);
1347 TRACE("Pressed item %d!\n", nItem
);
1349 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
1350 if (!(HEADER_SendHeaderNotify (hwnd
, HDN_BEGINTRACKA
, nItem
,0))) {
1352 infoPtr
->bCaptured
= TRUE
;
1353 infoPtr
->bTracking
= TRUE
;
1354 infoPtr
->iMoveItem
= nItem
;
1355 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
1356 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
1358 if (!(dwStyle
& HDS_FULLDRAG
)) {
1359 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
1361 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1362 ReleaseDC (hwnd
, hdc
);
1365 TRACE("Begin tracking item %d!\n", nItem
);
1374 HEADER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1376 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1378 *DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1385 pt
.x
= (INT
)SLOWORD(lParam
);
1386 pt
.y
= (INT
)SHIWORD(lParam
);
1387 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1389 if (infoPtr
->bPressed
) {
1390 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1391 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1393 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1394 ReleaseDC (hwnd
, hdc
);
1396 HEADER_SendClickNotify (hwnd
, HDN_ITEMCLICKA
, infoPtr
->iMoveItem
);
1398 else if (flags
== HHT_ONHEADER
)
1400 HEADER_ITEM
*lpItem
;
1401 INT newindex
= HEADER_IndexToOrder(hwnd
,nItem
);
1402 INT oldindex
= HEADER_IndexToOrder(hwnd
,infoPtr
->iMoveItem
);
1404 TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
1405 infoPtr
->iMoveItem
,oldindex
,nItem
,newindex
);
1406 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[nItem
];
1407 lpItem
->iOrder
=oldindex
;
1409 lpItem
= (HEADER_ITEM
*)&infoPtr
->items
[infoPtr
->iMoveItem
];
1410 lpItem
->iOrder
= newindex
;
1412 infoPtr
->bRectsValid
= FALSE
;
1413 InvalidateRect(hwnd
, NULL
, FALSE
);
1414 /* FIXME: Should some WM_NOTIFY be sent */
1417 TRACE("Released item %d!\n", infoPtr
->iMoveItem
);
1418 infoPtr
->bPressed
= FALSE
;
1420 else if (infoPtr
->bTracking
) {
1421 TRACE("End tracking item %d!\n", infoPtr
->iMoveItem
);
1422 infoPtr
->bTracking
= FALSE
;
1424 HEADER_SendHeaderNotify (hwnd
, HDN_ENDTRACKA
, infoPtr
->iMoveItem
,HDI_WIDTH
);
1427 * we want to do this even for HDS_FULLDRAG because this is where
1428 * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications
1430 * if (!(dwStyle & HDS_FULLDRAG)) {
1434 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1435 ReleaseDC (hwnd
, hdc
);
1436 if (HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1438 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1441 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1444 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1447 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1448 HEADER_SetItemBounds (hwnd
);
1449 InvalidateRect(hwnd
, NULL
, FALSE
);
1455 if (infoPtr
->bCaptured
) {
1456 infoPtr
->bCaptured
= FALSE
;
1458 HEADER_SendSimpleNotify (hwnd
, NM_RELEASEDCAPTURE
);
1466 HEADER_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1468 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1473 return infoPtr
->nNotifyFormat
;
1476 infoPtr
->nNotifyFormat
=
1477 SendMessageA ((HWND
)wParam
, WM_NOTIFYFORMAT
,
1478 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1479 return infoPtr
->nNotifyFormat
;
1487 HEADER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1489 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1490 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1496 pt
.x
= (INT
)SLOWORD(lParam
);
1497 pt
.y
= (INT
)SHIWORD(lParam
);
1498 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1500 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1501 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1502 infoPtr
->iHotItem
= nItem
;
1504 infoPtr
->iHotItem
= -1;
1505 InvalidateRect(hwnd
, NULL
, FALSE
);
1508 if (infoPtr
->bCaptured
) {
1509 if (infoPtr
->bPressed
) {
1510 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1511 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1513 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1515 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1516 ReleaseDC (hwnd
, hdc
);
1518 TRACE("Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1520 else if (infoPtr
->bTracking
) {
1521 if (dwStyle
& HDS_FULLDRAG
) {
1522 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1524 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1527 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1528 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1530 HEADER_SetItemBounds (hwnd
);
1531 InvalidateRect(hwnd
, NULL
, FALSE
);
1535 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1536 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1537 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1538 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1539 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1540 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1541 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1542 ReleaseDC (hwnd
, hdc
);
1543 HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1546 TRACE("Tracking item %d!\n", infoPtr
->iMoveItem
);
1550 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1551 FIXME("hot track support!\n");
1559 HEADER_Paint (HWND hwnd
, WPARAM wParam
)
1564 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1565 HEADER_Refresh (hwnd
, hdc
);
1567 EndPaint (hwnd
, &ps
);
1573 HEADER_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1578 pt
.x
= LOWORD(lParam
);
1579 pt
.y
= HIWORD(lParam
);
1581 /* Send a Notify message */
1582 bRet
= HEADER_SendSimpleNotify (hwnd
, NM_RCLICK
);
1584 /* Change to screen coordinate for WM_CONTEXTMENU */
1585 ClientToScreen(hwnd
, &pt
);
1587 /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */
1588 SendMessageA( hwnd
, WM_CONTEXTMENU
, (WPARAM
) hwnd
, MAKELPARAM(pt
.x
, pt
.y
));
1595 HEADER_SetCursor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1597 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1602 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1605 ScreenToClient (hwnd
, &pt
);
1607 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1609 if (flags
== HHT_ONDIVIDER
)
1610 SetCursor (infoPtr
->hcurDivider
);
1611 else if (flags
== HHT_ONDIVOPEN
)
1612 SetCursor (infoPtr
->hcurDivopen
);
1614 SetCursor (infoPtr
->hcurArrow
);
1621 HEADER_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1623 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1625 HFONT hFont
, hOldFont
;
1628 infoPtr
->hFont
= (HFONT
)wParam
;
1630 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
1633 hOldFont
= SelectObject (hdc
, hFont
);
1634 GetTextMetricsA (hdc
, &tm
);
1635 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1636 SelectObject (hdc
, hOldFont
);
1639 infoPtr
->bRectsValid
= FALSE
;
1642 InvalidateRect(hwnd
, NULL
, FALSE
);
1649 static LRESULT WINAPI
1650 HEADER_WindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1652 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1653 if (!HEADER_GetInfoPtr (hwnd
) && (msg
!= WM_CREATE
))
1654 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1656 /* case HDM_CLEARFILTER: */
1658 case HDM_CREATEDRAGIMAGE
:
1659 return HEADER_CreateDragImage (hwnd
, wParam
);
1661 case HDM_DELETEITEM
:
1662 return HEADER_DeleteItem (hwnd
, wParam
);
1664 /* case HDM_EDITFILTER: */
1666 /* case HDM_GETBITMAPMARGIN: */
1668 case HDM_GETIMAGELIST
:
1669 return HEADER_GetImageList (hwnd
);
1672 return HEADER_GetItemA (hwnd
, wParam
, lParam
);
1675 return HEADER_GetItemW (hwnd
, wParam
, lParam
);
1677 case HDM_GETITEMCOUNT
:
1678 return HEADER_GetItemCount (hwnd
);
1680 case HDM_GETITEMRECT
:
1681 return HEADER_GetItemRect (hwnd
, wParam
, lParam
);
1683 case HDM_GETORDERARRAY
:
1684 return HEADER_GetOrderArray(hwnd
, wParam
, lParam
);
1686 case HDM_GETUNICODEFORMAT
:
1687 return HEADER_GetUnicodeFormat (hwnd
);
1690 return HEADER_HitTest (hwnd
, wParam
, lParam
);
1692 case HDM_INSERTITEMA
:
1693 return HEADER_InsertItemA (hwnd
, wParam
, lParam
);
1695 case HDM_INSERTITEMW
:
1696 return HEADER_InsertItemW (hwnd
, wParam
, lParam
);
1699 return HEADER_Layout (hwnd
, wParam
, lParam
);
1701 case HDM_ORDERTOINDEX
:
1702 return HEADER_OrderToIndex(hwnd
, wParam
);
1704 /* case HDM_SETBITMAPMARGIN: */
1706 /* case HDM_SETFILTERCHANGETIMEOUT: */
1708 /* case HDM_SETHOTDIVIDER: */
1710 case HDM_SETIMAGELIST
:
1711 return HEADER_SetImageList (hwnd
, (HIMAGELIST
)lParam
);
1714 return HEADER_SetItemA (hwnd
, wParam
, lParam
);
1717 return HEADER_SetItemW (hwnd
, wParam
, lParam
);
1719 case HDM_SETORDERARRAY
:
1720 return HEADER_SetOrderArray(hwnd
, wParam
, lParam
);
1722 case HDM_SETUNICODEFORMAT
:
1723 return HEADER_SetUnicodeFormat (hwnd
, wParam
);
1726 return HEADER_Create (hwnd
, wParam
, lParam
);
1729 return HEADER_Destroy (hwnd
, wParam
, lParam
);
1735 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1738 return HEADER_GetFont (hwnd
);
1740 case WM_LBUTTONDBLCLK
:
1741 return HEADER_LButtonDblClk (hwnd
, wParam
, lParam
);
1743 case WM_LBUTTONDOWN
:
1744 return HEADER_LButtonDown (hwnd
, wParam
, lParam
);
1747 return HEADER_LButtonUp (hwnd
, wParam
, lParam
);
1750 return HEADER_MouseMove (hwnd
, wParam
, lParam
);
1752 case WM_NOTIFYFORMAT
:
1753 return HEADER_NotifyFormat (hwnd
, wParam
, lParam
);
1756 return HEADER_Size (hwnd
, wParam
);
1759 return HEADER_Paint (hwnd
, wParam
);
1762 return HEADER_RButtonUp (hwnd
, wParam
, lParam
);
1765 return HEADER_SetCursor (hwnd
, wParam
, lParam
);
1768 return HEADER_SetFont (hwnd
, wParam
, lParam
);
1772 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1773 msg
, wParam
, lParam
);
1774 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1781 HEADER_Register (void)
1785 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1786 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1787 wndClass
.lpfnWndProc
= (WNDPROC
)HEADER_WindowProc
;
1788 wndClass
.cbClsExtra
= 0;
1789 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1790 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
1791 wndClass
.lpszClassName
= WC_HEADERA
;
1793 RegisterClassA (&wndClass
);
1798 HEADER_Unregister (void)
1800 UnregisterClassA (WC_HEADERA
, (HINSTANCE
)NULL
);