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.
38 #include "wine/unicode.h"
41 #include "imagelist.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(header
);
54 INT iOrder
; /* see documentation of HD_ITEM */
56 BOOL bDown
; /* is item pressed? (used for drawing) */
57 RECT rect
; /* bounding rectangle of the item */
63 HWND hwndNotify
; /* Owner window to send notifications to */
64 INT nNotifyFormat
; /* format used for WM_NOTIFY messages */
65 UINT uNumItem
; /* number of items (columns) */
66 INT nHeight
; /* height of the header (pixels) */
67 HFONT hFont
; /* handle to the current font */
68 HCURSOR hcurArrow
; /* handle to the arrow cursor */
69 HCURSOR hcurDivider
; /* handle to a cursor (used over dividers) <-|-> */
70 HCURSOR hcurDivopen
; /* handle to a cursor (used over dividers) <-||-> */
71 BOOL bCaptured
; /* Is the mouse captured? */
72 BOOL bPressed
; /* Is a header item pressed (down)? */
73 BOOL bTracking
; /* Is in tracking mode? */
74 BOOL bUnicode
; /* Unicode flag */
75 INT iMoveItem
; /* index of tracked item. (Tracking mode) */
76 INT xTrackOffset
; /* distance between the right side of the tracked item and the cursor */
77 INT xOldTrack
; /* track offset (see above) after the last WM_MOUSEMOVE */
78 INT nOldWidth
; /* width of a sizing item after the last WM_MOUSEMOVE */
79 INT iHotItem
; /* index of hot item (cursor is over this item) */
81 HIMAGELIST himl
; /* handle to a image list (may be 0) */
82 HEADER_ITEM
*items
; /* pointer to array of HEADER_ITEM's */
83 BOOL bRectsValid
; /* validity flag for bounding rectangles */
88 #define DIVIDER_WIDTH 10
90 #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongA(hwnd,0))
94 HEADER_IndexToOrder (HWND hwnd
, INT iItem
)
96 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
97 HEADER_ITEM
*lpItem
= &infoPtr
->items
[iItem
];
98 return lpItem
->iOrder
;
103 HEADER_OrderToIndex(HWND hwnd
, WPARAM wParam
)
105 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
106 INT i
,iorder
= (INT
)wParam
;
109 if ((iorder
<0) || iorder
>infoPtr
->uNumItem
)
111 for (i
=0; i
<infoPtr
->uNumItem
; i
++)
112 if (HEADER_IndexToOrder(hwnd
,i
) == iorder
)
118 HEADER_SetItemBounds (HWND hwnd
)
120 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
125 infoPtr
->bRectsValid
= TRUE
;
127 if (infoPtr
->uNumItem
== 0)
130 GetClientRect (hwnd
, &rect
);
133 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
134 phdi
= &infoPtr
->items
[HEADER_OrderToIndex(hwnd
,i
)];
135 phdi
->rect
.top
= rect
.top
;
136 phdi
->rect
.bottom
= rect
.bottom
;
138 phdi
->rect
.right
= phdi
->rect
.left
+ ((phdi
->cxy
>0)?phdi
->cxy
:0);
139 x
= phdi
->rect
.right
;
144 HEADER_Size (HWND hwnd
, WPARAM wParam
)
146 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
148 infoPtr
->bRectsValid
= FALSE
;
155 HEADER_DrawItem (HWND hwnd
, HDC hdc
, INT iItem
, BOOL bHotTrack
)
157 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
158 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
162 TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem
, bHotTrack
, infoPtr
->bUnicode
);
164 if (!infoPtr
->bRectsValid
)
165 HEADER_SetItemBounds(hwnd
);
168 if (r
.right
- r
.left
== 0)
169 return phdi
->rect
.right
;
171 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) {
173 DrawEdge (hdc
, &r
, BDR_RAISEDOUTER
,
174 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
179 DrawEdge (hdc
, &r
, EDGE_RAISED
,
180 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
183 DrawEdge (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
185 if (phdi
->fmt
& HDF_OWNERDRAW
) {
187 dis
.CtlType
= ODT_HEADER
;
188 dis
.CtlID
= GetWindowLongA (hwnd
, GWL_ID
);
190 dis
.itemAction
= ODA_DRAWENTIRE
;
191 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
195 dis
.itemData
= phdi
->lParam
;
196 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
197 SendMessageA (GetParent (hwnd
), WM_DRAWITEM
,
198 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
199 if (oldBkMode
!= TRANSPARENT
)
200 SetBkMode(hdc
, oldBkMode
);
203 UINT uTextJustify
= DT_LEFT
;
205 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
206 uTextJustify
= DT_CENTER
;
207 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
208 uTextJustify
= DT_RIGHT
;
210 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->hbm
)) {
213 INT yD
, yS
, cx
, cy
, rx
, ry
;
215 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
217 ry
= r
.bottom
- r
.top
;
218 rx
= r
.right
- r
.left
;
220 if (ry
>= bmp
.bmHeight
) {
222 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
228 yS
= (bmp
.bmHeight
- ry
) / 2;
232 if (rx
>= bmp
.bmWidth
+ 6) {
239 hdcBitmap
= CreateCompatibleDC (hdc
);
240 SelectObject (hdcBitmap
, phdi
->hbm
);
241 BitBlt (hdc
, r
.left
+ 3, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
242 DeleteDC (hdcBitmap
);
244 r
.left
+= (bmp
.bmWidth
+ 3);
248 if ((phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
251 INT xD
, yD
, yS
, cx
, cy
, rx
, ry
, tx
;
254 GetObjectA (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
257 if (infoPtr
->bUnicode
)
258 DrawTextW (hdc
, phdi
->pszText
, -1,
259 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
261 DrawTextA (hdc
, (LPCSTR
)phdi
->pszText
, -1,
262 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
263 tx
= textRect
.right
- textRect
.left
;
264 ry
= r
.bottom
- r
.top
;
265 rx
= r
.right
- r
.left
;
267 if (ry
>= bmp
.bmHeight
) {
269 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
275 yS
= (bmp
.bmHeight
- ry
) / 2;
279 if (r
.left
+ tx
+ bmp
.bmWidth
+ 9 <= r
.right
) {
281 xD
= r
.left
+ tx
+ 6;
284 if (rx
>= bmp
.bmWidth
+ 6) {
286 xD
= r
.right
- bmp
.bmWidth
- 3;
296 hdcBitmap
= CreateCompatibleDC (hdc
);
297 SelectObject (hdcBitmap
, phdi
->hbm
);
298 BitBlt (hdc
, xD
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
299 DeleteDC (hdcBitmap
);
302 if ((phdi
->fmt
& HDF_IMAGE
) && (infoPtr
->himl
)) {
304 /* FIXME: (r.bottom- (infoPtr->himl->cy))/2 should horicontal center the image
305 It looks like it doesn't work as expected*/
306 ImageList_Draw (infoPtr
->himl
, phdi
->iImage
,hdc
,r
.left
, (r
.bottom
- (infoPtr
->himl
->cy
))/2,0);
307 r
.left
+= infoPtr
->himl
->cx
;
310 if (((phdi
->fmt
& HDF_STRING
)
311 || (!(phdi
->fmt
& (HDF_OWNERDRAW
|HDF_STRING
|HDF_BITMAP
|
312 HDF_BITMAP_ON_RIGHT
|HDF_IMAGE
)))) /* no explicit format specified? */
313 && (phdi
->pszText
)) {
314 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
317 SetTextColor (hdc
, (bHotTrack
) ? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
318 if (infoPtr
->bUnicode
)
319 DrawTextW (hdc
, phdi
->pszText
, -1,
320 &r
, uTextJustify
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
322 DrawTextA (hdc
, (LPCSTR
)phdi
->pszText
, -1,
323 &r
, uTextJustify
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
324 if (oldBkMode
!= TRANSPARENT
)
325 SetBkMode(hdc
, oldBkMode
);
329 return phdi
->rect
.right
;
334 HEADER_Refresh (HWND hwnd
, HDC hdc
)
336 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
337 HFONT hFont
, hOldFont
;
342 /* get rect for the bar, adjusted for the border */
343 GetClientRect (hwnd
, &rect
);
345 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
346 hOldFont
= SelectObject (hdc
, hFont
);
348 /* draw Background */
349 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
350 FillRect(hdc
, &rect
, hbrBk
);
353 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
354 x
= HEADER_DrawItem (hwnd
, hdc
, HEADER_OrderToIndex(hwnd
,i
), FALSE
);
357 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
359 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
)
360 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
362 DrawEdge (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
365 SelectObject (hdc
, hOldFont
);
370 HEADER_RefreshItem (HWND hwnd
, HDC hdc
, INT iItem
)
372 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
373 HFONT hFont
, hOldFont
;
375 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
376 hOldFont
= SelectObject (hdc
, hFont
);
377 HEADER_DrawItem (hwnd
, hdc
, iItem
, FALSE
);
378 SelectObject (hdc
, hOldFont
);
383 HEADER_InternalHitTest (HWND hwnd
, LPPOINT lpPt
, UINT
*pFlags
, INT
*pItem
)
385 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
390 GetClientRect (hwnd
, &rect
);
394 if (PtInRect (&rect
, *lpPt
))
396 if (infoPtr
->uNumItem
== 0) {
397 *pFlags
|= HHT_NOWHERE
;
403 /* somewhere inside */
404 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
405 rect
= infoPtr
->items
[iCount
].rect
;
406 width
= rect
.right
- rect
.left
;
411 if (PtInRect (&rect
, *lpPt
)) {
412 if (width
<= 2 * DIVIDER_WIDTH
) {
413 *pFlags
|= HHT_ONHEADER
;
415 TRACE("ON HEADER %d\n", iCount
);
420 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
421 if (PtInRect (&rcTest
, *lpPt
)) {
423 *pFlags
|= HHT_ONDIVOPEN
;
425 TRACE("ON DIVOPEN %d\n", *pItem
);
429 *pFlags
|= HHT_ONDIVIDER
;
431 TRACE("ON DIVIDER %d\n", *pItem
);
437 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
438 if (PtInRect (&rcTest
, *lpPt
)) {
439 *pFlags
|= HHT_ONDIVIDER
;
441 TRACE("ON DIVIDER %d\n", *pItem
);
445 *pFlags
|= HHT_ONHEADER
;
447 TRACE("ON HEADER %d\n", iCount
);
452 /* check for last divider part (on nowhere) */
453 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
454 rect
.left
= rect
.right
;
455 rect
.right
+= DIVIDER_WIDTH
;
456 if (PtInRect (&rect
, *lpPt
)) {
458 *pFlags
|= HHT_ONDIVOPEN
;
459 *pItem
= infoPtr
->uNumItem
- 1;
460 TRACE("ON DIVOPEN %d\n", *pItem
);
464 *pFlags
|= HHT_ONDIVIDER
;
465 *pItem
= infoPtr
->uNumItem
-1;
466 TRACE("ON DIVIDER %d\n", *pItem
);
471 *pFlags
|= HHT_NOWHERE
;
478 if (lpPt
->x
< rect
.left
) {
480 *pFlags
|= HHT_TOLEFT
;
482 else if (lpPt
->x
> rect
.right
) {
484 *pFlags
|= HHT_TORIGHT
;
487 if (lpPt
->y
< rect
.top
) {
489 *pFlags
|= HHT_ABOVE
;
491 else if (lpPt
->y
> rect
.bottom
) {
493 *pFlags
|= HHT_BELOW
;
498 TRACE("flags=0x%X\n", *pFlags
);
504 HEADER_DrawTrackLine (HWND hwnd
, HDC hdc
, INT x
)
510 GetClientRect (hwnd
, &rect
);
512 hOldPen
= SelectObject (hdc
, GetStockObject (BLACK_PEN
));
513 oldRop
= SetROP2 (hdc
, R2_XORPEN
);
514 MoveToEx (hdc
, x
, rect
.top
, NULL
);
515 LineTo (hdc
, x
, rect
.bottom
);
516 SetROP2 (hdc
, oldRop
);
517 SelectObject (hdc
, hOldPen
);
522 HEADER_SendSimpleNotify (HWND hwnd
, UINT code
)
524 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
527 nmhdr
.hwndFrom
= hwnd
;
528 nmhdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
531 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
532 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
536 HEADER_SendHeaderNotify (HWND hwnd
, UINT code
, INT iItem
, INT mask
)
538 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
542 nmhdr
.hdr
.hwndFrom
= hwnd
;
543 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
544 nmhdr
.hdr
.code
= code
;
547 nmhdr
.pitem
= &nmitem
;
549 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
550 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
551 nmitem
.pszText
= NULL
;
552 nmitem
.cchTextMax
= 0;
553 /* nmitem.pszText = infoPtr->items[iItem].pszText; */
554 /* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
555 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
556 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
557 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
558 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
560 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
561 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
566 HEADER_SendClickNotify (HWND hwnd
, UINT code
, INT iItem
)
568 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
571 nmhdr
.hdr
.hwndFrom
= hwnd
;
572 nmhdr
.hdr
.idFrom
= GetWindowLongA (hwnd
, GWL_ID
);
573 nmhdr
.hdr
.code
= code
;
578 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
579 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
584 HEADER_CreateDragImage (HWND hwnd
, WPARAM wParam
)
586 FIXME("empty stub!\n");
592 HEADER_DeleteItem (HWND hwnd
, WPARAM wParam
)
594 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
595 INT iItem
= (INT
)wParam
;
597 TRACE("[iItem=%d]\n", iItem
);
599 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
602 if (infoPtr
->uNumItem
== 1) {
603 TRACE("Simple delete!\n");
604 if (infoPtr
->items
[0].pszText
)
605 COMCTL32_Free (infoPtr
->items
[0].pszText
);
606 COMCTL32_Free (infoPtr
->items
);
608 infoPtr
->uNumItem
= 0;
611 HEADER_ITEM
*oldItems
= infoPtr
->items
;
615 TRACE("Complex delete! [iItem=%d]\n", iItem
);
617 if (infoPtr
->items
[iItem
].pszText
)
618 COMCTL32_Free (infoPtr
->items
[iItem
].pszText
);
619 iOrder
= infoPtr
->items
[iItem
].iOrder
;
622 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
623 /* pre delete copy */
625 memcpy (&infoPtr
->items
[0], &oldItems
[0],
626 iItem
* sizeof(HEADER_ITEM
));
629 /* post delete copy */
630 if (iItem
< infoPtr
->uNumItem
) {
631 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
632 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
635 /* Correct the orders */
636 for (i
=infoPtr
->uNumItem
, pItem
= infoPtr
->items
; i
; i
--, pItem
++)
638 if (pItem
->iOrder
> iOrder
)
641 COMCTL32_Free (oldItems
);
644 HEADER_SetItemBounds (hwnd
);
646 InvalidateRect(hwnd
, NULL
, FALSE
);
653 HEADER_GetImageList (HWND hwnd
)
655 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
657 return (LRESULT
)infoPtr
->himl
;
662 HEADER_GetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
664 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
665 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
666 INT nItem
= (INT
)wParam
;
671 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
674 TRACE("[nItem=%d]\n", nItem
);
679 lpItem
= &infoPtr
->items
[nItem
];
680 if (phdi
->mask
& HDI_BITMAP
)
681 phdi
->hbm
= lpItem
->hbm
;
683 if (phdi
->mask
& HDI_FORMAT
)
684 phdi
->fmt
= lpItem
->fmt
;
686 if (phdi
->mask
& HDI_WIDTH
)
687 phdi
->cxy
= lpItem
->cxy
;
689 if (phdi
->mask
& HDI_LPARAM
)
690 phdi
->lParam
= lpItem
->lParam
;
692 if (phdi
->mask
& HDI_TEXT
) {
693 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
695 WideCharToMultiByte (CP_ACP
, 0, lpItem
->pszText
, -1,
696 phdi
->pszText
, phdi
->cchTextMax
, NULL
, NULL
);
701 phdi
->pszText
= LPSTR_TEXTCALLBACKA
;
704 if (phdi
->mask
& HDI_IMAGE
)
705 phdi
->iImage
= lpItem
->iImage
;
707 if (phdi
->mask
& HDI_ORDER
)
708 phdi
->iOrder
= lpItem
->iOrder
;
715 HEADER_GetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
717 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
718 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
719 INT nItem
= (INT
)wParam
;
724 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
727 TRACE("[nItem=%d]\n", nItem
);
732 lpItem
= &infoPtr
->items
[nItem
];
733 if (phdi
->mask
& HDI_BITMAP
)
734 phdi
->hbm
= lpItem
->hbm
;
736 if (phdi
->mask
& HDI_FORMAT
)
737 phdi
->fmt
= lpItem
->fmt
;
739 if (phdi
->mask
& HDI_WIDTH
)
740 phdi
->cxy
= lpItem
->cxy
;
742 if (phdi
->mask
& HDI_LPARAM
)
743 phdi
->lParam
= lpItem
->lParam
;
745 if (phdi
->mask
& HDI_TEXT
) {
746 if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
748 lstrcpynW (phdi
->pszText
, lpItem
->pszText
, phdi
->cchTextMax
);
753 phdi
->pszText
= LPSTR_TEXTCALLBACKW
;
756 if (phdi
->mask
& HDI_IMAGE
)
757 phdi
->iImage
= lpItem
->iImage
;
759 if (phdi
->mask
& HDI_ORDER
)
760 phdi
->iOrder
= lpItem
->iOrder
;
766 inline static LRESULT
767 HEADER_GetItemCount (HWND hwnd
)
769 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
770 return infoPtr
->uNumItem
;
775 HEADER_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
777 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
778 INT iItem
= (INT
)wParam
;
779 LPRECT lpRect
= (LPRECT
)lParam
;
781 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
784 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
785 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
786 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
787 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
794 HEADER_GetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
797 LPINT order
= (LPINT
) lParam
;
798 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
800 if ((int)wParam
<infoPtr
->uNumItem
)
802 for (i
=0; i
<(int)wParam
; i
++)
803 *order
++=HEADER_OrderToIndex(hwnd
,i
);
808 HEADER_SetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
811 LPINT order
= (LPINT
) lParam
;
812 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
815 if ((int)wParam
<infoPtr
->uNumItem
)
817 for (i
=0; i
<(int)wParam
; i
++)
819 lpItem
= &infoPtr
->items
[*order
++];
822 infoPtr
->bRectsValid
=0;
823 InvalidateRect(hwnd
, NULL
, FALSE
);
827 inline static LRESULT
828 HEADER_GetUnicodeFormat (HWND hwnd
)
830 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
831 return infoPtr
->bUnicode
;
836 HEADER_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
838 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
840 HEADER_InternalHitTest (hwnd
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
842 if (phti
->flags
== HHT_ONHEADER
)
850 HEADER_InsertItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
852 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
853 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
854 INT nItem
= (INT
)wParam
;
858 if ((phdi
== NULL
) || (nItem
< 0))
861 if (nItem
> infoPtr
->uNumItem
)
862 nItem
= infoPtr
->uNumItem
;
864 if (infoPtr
->uNumItem
== 0) {
865 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
));
869 HEADER_ITEM
*oldItems
= infoPtr
->items
;
872 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
874 memcpy (&infoPtr
->items
[1], &oldItems
[0],
875 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
879 /* pre insert copy */
881 memcpy (&infoPtr
->items
[0], &oldItems
[0],
882 nItem
* sizeof(HEADER_ITEM
));
885 /* post insert copy */
886 if (nItem
< infoPtr
->uNumItem
- 1) {
887 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
888 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
892 COMCTL32_Free (oldItems
);
895 lpItem
= &infoPtr
->items
[nItem
];
896 lpItem
->bDown
= FALSE
;
898 if (phdi
->mask
& HDI_WIDTH
)
899 lpItem
->cxy
= phdi
->cxy
;
901 if (phdi
->mask
& HDI_TEXT
) {
902 if (!phdi
->pszText
) /* null pointer check */
904 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
905 len
= MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, NULL
, 0);
906 lpItem
->pszText
= COMCTL32_Alloc( len
*sizeof(WCHAR
) );
907 MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, lpItem
->pszText
, len
);
910 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
913 if (phdi
->mask
& HDI_FORMAT
)
914 lpItem
->fmt
= phdi
->fmt
;
916 if (lpItem
->fmt
== 0)
917 lpItem
->fmt
= HDF_LEFT
;
919 if (!(lpItem
->fmt
& HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
921 lpItem
->fmt
|= HDF_STRING
;
923 if (phdi
->mask
& HDI_BITMAP
)
924 lpItem
->hbm
= phdi
->hbm
;
926 if (phdi
->mask
& HDI_LPARAM
)
927 lpItem
->lParam
= phdi
->lParam
;
929 if (phdi
->mask
& HDI_IMAGE
)
930 lpItem
->iImage
= phdi
->iImage
;
932 if (phdi
->mask
& HDI_ORDER
)
934 lpItem
->iOrder
= phdi
->iOrder
;
937 lpItem
->iOrder
=nItem
;
940 HEADER_SetItemBounds (hwnd
);
942 InvalidateRect(hwnd
, NULL
, FALSE
);
949 HEADER_InsertItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
951 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
952 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
953 INT nItem
= (INT
)wParam
;
957 if ((phdi
== NULL
) || (nItem
< 0))
960 if (nItem
> infoPtr
->uNumItem
)
961 nItem
= infoPtr
->uNumItem
;
963 if (infoPtr
->uNumItem
== 0) {
964 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
));
968 HEADER_ITEM
*oldItems
= infoPtr
->items
;
971 infoPtr
->items
= COMCTL32_Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
973 memcpy (&infoPtr
->items
[1], &oldItems
[0],
974 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
978 /* pre insert copy */
980 memcpy (&infoPtr
->items
[0], &oldItems
[0],
981 nItem
* sizeof(HEADER_ITEM
));
984 /* post insert copy */
985 if (nItem
< infoPtr
->uNumItem
- 1) {
986 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
987 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
991 COMCTL32_Free (oldItems
);
994 lpItem
= &infoPtr
->items
[nItem
];
995 lpItem
->bDown
= FALSE
;
997 if (phdi
->mask
& HDI_WIDTH
)
998 lpItem
->cxy
= phdi
->cxy
;
1000 if (phdi
->mask
& HDI_TEXT
) {
1001 WCHAR wide_null_char
= 0;
1002 if (!phdi
->pszText
) /* null pointer check */
1003 phdi
->pszText
= &wide_null_char
;
1004 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1005 len
= strlenW (phdi
->pszText
);
1006 lpItem
->pszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1007 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1010 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1013 if (phdi
->mask
& HDI_FORMAT
)
1014 lpItem
->fmt
= phdi
->fmt
;
1016 if (lpItem
->fmt
== 0)
1017 lpItem
->fmt
= HDF_LEFT
;
1019 if (!(lpItem
->fmt
&HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
1021 lpItem
->fmt
|= HDF_STRING
;
1023 if (phdi
->mask
& HDI_BITMAP
)
1024 lpItem
->hbm
= phdi
->hbm
;
1026 if (phdi
->mask
& HDI_LPARAM
)
1027 lpItem
->lParam
= phdi
->lParam
;
1029 if (phdi
->mask
& HDI_IMAGE
)
1030 lpItem
->iImage
= phdi
->iImage
;
1032 if (phdi
->mask
& HDI_ORDER
)
1034 lpItem
->iOrder
= phdi
->iOrder
;
1037 lpItem
->iOrder
= nItem
;
1039 HEADER_SetItemBounds (hwnd
);
1041 InvalidateRect(hwnd
, NULL
, FALSE
);
1048 HEADER_Layout (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1050 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1051 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
1053 lpLayout
->pwpos
->hwnd
= hwnd
;
1054 lpLayout
->pwpos
->hwndInsertAfter
= 0;
1055 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
1056 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
1057 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
1058 if (GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_HIDDEN
)
1059 lpLayout
->pwpos
->cy
= 0;
1061 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
1062 lpLayout
->prc
->top
+= infoPtr
->nHeight
;
1064 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
1066 TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
1067 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
1068 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
1070 infoPtr
->bRectsValid
= FALSE
;
1077 HEADER_SetImageList (HWND hwnd
, HIMAGELIST himl
)
1079 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1082 TRACE("(himl 0x%x)\n", (int)himl
);
1083 himlOld
= infoPtr
->himl
;
1084 infoPtr
->himl
= himl
;
1086 /* FIXME: Refresh needed??? */
1088 return (LRESULT
)himlOld
;
1093 HEADER_SetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1095 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1096 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
1097 INT nItem
= (INT
)wParam
;
1098 HEADER_ITEM
*lpItem
;
1102 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1105 TRACE("[nItem=%d]\n", nItem
);
1107 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, nItem
, phdi
->mask
))
1110 lpItem
= &infoPtr
->items
[nItem
];
1111 if (phdi
->mask
& HDI_BITMAP
)
1112 lpItem
->hbm
= phdi
->hbm
;
1114 if (phdi
->mask
& HDI_FORMAT
)
1115 lpItem
->fmt
= phdi
->fmt
;
1117 if (phdi
->mask
& HDI_LPARAM
)
1118 lpItem
->lParam
= phdi
->lParam
;
1120 if (phdi
->mask
& HDI_TEXT
) {
1121 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
1122 if (lpItem
->pszText
) {
1123 COMCTL32_Free (lpItem
->pszText
);
1124 lpItem
->pszText
= NULL
;
1126 if (phdi
->pszText
) {
1127 INT len
= MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,NULL
,0);
1128 lpItem
->pszText
= COMCTL32_Alloc( len
*sizeof(WCHAR
) );
1129 MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,lpItem
->pszText
,len
);
1133 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1136 if (phdi
->mask
& HDI_WIDTH
)
1137 lpItem
->cxy
= phdi
->cxy
;
1139 if (phdi
->mask
& HDI_IMAGE
)
1140 lpItem
->iImage
= phdi
->iImage
;
1142 if (phdi
->mask
& HDI_ORDER
)
1144 lpItem
->iOrder
= phdi
->iOrder
;
1147 lpItem
->iOrder
= nItem
;
1149 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGEDA
, nItem
, phdi
->mask
);
1151 HEADER_SetItemBounds (hwnd
);
1153 InvalidateRect(hwnd
, NULL
, FALSE
);
1160 HEADER_SetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1162 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1163 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
1164 INT nItem
= (INT
)wParam
;
1165 HEADER_ITEM
*lpItem
;
1169 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1172 TRACE("[nItem=%d]\n", nItem
);
1174 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
))
1177 lpItem
= &infoPtr
->items
[nItem
];
1178 if (phdi
->mask
& HDI_BITMAP
)
1179 lpItem
->hbm
= phdi
->hbm
;
1181 if (phdi
->mask
& HDI_FORMAT
)
1182 lpItem
->fmt
= phdi
->fmt
;
1184 if (phdi
->mask
& HDI_LPARAM
)
1185 lpItem
->lParam
= phdi
->lParam
;
1187 if (phdi
->mask
& HDI_TEXT
) {
1188 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1189 if (lpItem
->pszText
) {
1190 COMCTL32_Free (lpItem
->pszText
);
1191 lpItem
->pszText
= NULL
;
1193 if (phdi
->pszText
) {
1194 INT len
= strlenW (phdi
->pszText
);
1195 lpItem
->pszText
= COMCTL32_Alloc ((len
+1)*sizeof(WCHAR
));
1196 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1200 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1203 if (phdi
->mask
& HDI_WIDTH
)
1204 lpItem
->cxy
= phdi
->cxy
;
1206 if (phdi
->mask
& HDI_IMAGE
)
1207 lpItem
->iImage
= phdi
->iImage
;
1209 if (phdi
->mask
& HDI_ORDER
)
1211 lpItem
->iOrder
= phdi
->iOrder
;
1214 lpItem
->iOrder
= nItem
;
1216 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
);
1218 HEADER_SetItemBounds (hwnd
);
1220 InvalidateRect(hwnd
, NULL
, FALSE
);
1225 inline static LRESULT
1226 HEADER_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
)
1228 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1229 BOOL bTemp
= infoPtr
->bUnicode
;
1231 infoPtr
->bUnicode
= (BOOL
)wParam
;
1238 HEADER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1240 HEADER_INFO
*infoPtr
;
1245 infoPtr
= (HEADER_INFO
*)COMCTL32_Alloc (sizeof(HEADER_INFO
));
1246 SetWindowLongA (hwnd
, 0, (DWORD
)infoPtr
);
1248 infoPtr
->hwndNotify
= GetParent(hwnd
);
1249 infoPtr
->uNumItem
= 0;
1250 infoPtr
->nHeight
= 20;
1253 infoPtr
->bRectsValid
= FALSE
;
1254 infoPtr
->hcurArrow
= LoadCursorA (0, IDC_ARROWA
);
1255 infoPtr
->hcurDivider
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDER
));
1256 infoPtr
->hcurDivopen
= LoadCursorA (COMCTL32_hModule
, MAKEINTRESOURCEA(IDC_DIVIDEROPEN
));
1257 infoPtr
->bPressed
= FALSE
;
1258 infoPtr
->bTracking
= FALSE
;
1259 infoPtr
->iMoveItem
= 0;
1261 infoPtr
->iHotItem
= -1;
1262 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
1263 infoPtr
->nNotifyFormat
=
1264 SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
1267 hOldFont
= SelectObject (hdc
, GetStockObject (SYSTEM_FONT
));
1268 GetTextMetricsA (hdc
, &tm
);
1269 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1270 SelectObject (hdc
, hOldFont
);
1278 HEADER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1280 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1281 HEADER_ITEM
*lpItem
;
1284 if (infoPtr
->items
) {
1285 lpItem
= infoPtr
->items
;
1286 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
1287 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
))
1288 COMCTL32_Free (lpItem
->pszText
);
1290 COMCTL32_Free (infoPtr
->items
);
1294 ImageList_Destroy (infoPtr
->himl
);
1296 COMCTL32_Free (infoPtr
);
1297 SetWindowLongA (hwnd
, 0, 0);
1302 static inline LRESULT
1303 HEADER_GetFont (HWND hwnd
)
1305 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1307 return (LRESULT
)infoPtr
->hFont
;
1312 HEADER_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1318 pt
.x
= (INT
)LOWORD(lParam
);
1319 pt
.y
= (INT
)HIWORD(lParam
);
1320 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1322 if ((GetWindowLongA (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
1323 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMDBLCLICKA
, nItem
,0);
1324 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
1325 HEADER_SendHeaderNotify (hwnd
, HDN_DIVIDERDBLCLICKA
, nItem
,0);
1332 HEADER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1334 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1335 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1341 pt
.x
= (INT
)LOWORD(lParam
);
1342 pt
.y
= (INT
)HIWORD(lParam
);
1343 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1345 if ((dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
1347 infoPtr
->bCaptured
= TRUE
;
1348 infoPtr
->bPressed
= TRUE
;
1349 infoPtr
->iMoveItem
= nItem
;
1351 infoPtr
->items
[nItem
].bDown
= TRUE
;
1353 /* Send WM_CUSTOMDRAW */
1355 HEADER_RefreshItem (hwnd
, hdc
, nItem
);
1356 ReleaseDC (hwnd
, hdc
);
1358 TRACE("Pressed item %d!\n", nItem
);
1360 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
1361 if (!(HEADER_SendHeaderNotify (hwnd
, HDN_BEGINTRACKA
, nItem
,0))) {
1363 infoPtr
->bCaptured
= TRUE
;
1364 infoPtr
->bTracking
= TRUE
;
1365 infoPtr
->iMoveItem
= nItem
;
1366 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
1367 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
1369 if (!(dwStyle
& HDS_FULLDRAG
)) {
1370 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
1372 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1373 ReleaseDC (hwnd
, hdc
);
1376 TRACE("Begin tracking item %d!\n", nItem
);
1385 HEADER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1387 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1389 *DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1396 pt
.x
= (INT
)SLOWORD(lParam
);
1397 pt
.y
= (INT
)SHIWORD(lParam
);
1398 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1400 if (infoPtr
->bPressed
) {
1401 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1402 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1404 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1405 ReleaseDC (hwnd
, hdc
);
1407 HEADER_SendClickNotify (hwnd
, HDN_ITEMCLICKA
, infoPtr
->iMoveItem
);
1409 else if (flags
== HHT_ONHEADER
)
1411 HEADER_ITEM
*lpItem
;
1412 INT newindex
= HEADER_IndexToOrder(hwnd
,nItem
);
1413 INT oldindex
= HEADER_IndexToOrder(hwnd
,infoPtr
->iMoveItem
);
1415 TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
1416 infoPtr
->iMoveItem
,oldindex
,nItem
,newindex
);
1417 lpItem
= &infoPtr
->items
[nItem
];
1418 lpItem
->iOrder
=oldindex
;
1420 lpItem
= &infoPtr
->items
[infoPtr
->iMoveItem
];
1421 lpItem
->iOrder
= newindex
;
1423 infoPtr
->bRectsValid
= FALSE
;
1424 InvalidateRect(hwnd
, NULL
, FALSE
);
1425 /* FIXME: Should some WM_NOTIFY be sent */
1428 TRACE("Released item %d!\n", infoPtr
->iMoveItem
);
1429 infoPtr
->bPressed
= FALSE
;
1431 else if (infoPtr
->bTracking
) {
1432 TRACE("End tracking item %d!\n", infoPtr
->iMoveItem
);
1433 infoPtr
->bTracking
= FALSE
;
1435 HEADER_SendHeaderNotify (hwnd
, HDN_ENDTRACKA
, infoPtr
->iMoveItem
,HDI_WIDTH
);
1438 * we want to do this even for HDS_FULLDRAG because this is where
1439 * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications
1441 * if (!(dwStyle & HDS_FULLDRAG)) {
1445 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1446 ReleaseDC (hwnd
, hdc
);
1447 if (HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1449 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1452 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1455 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1458 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1459 HEADER_SetItemBounds (hwnd
);
1460 InvalidateRect(hwnd
, NULL
, FALSE
);
1466 if (infoPtr
->bCaptured
) {
1467 infoPtr
->bCaptured
= FALSE
;
1469 HEADER_SendSimpleNotify (hwnd
, NM_RELEASEDCAPTURE
);
1477 HEADER_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1479 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1484 return infoPtr
->nNotifyFormat
;
1487 infoPtr
->nNotifyFormat
=
1488 SendMessageA ((HWND
)wParam
, WM_NOTIFYFORMAT
,
1489 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1490 return infoPtr
->nNotifyFormat
;
1498 HEADER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1500 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1501 DWORD dwStyle
= GetWindowLongA (hwnd
, GWL_STYLE
);
1507 pt
.x
= (INT
)SLOWORD(lParam
);
1508 pt
.y
= (INT
)SHIWORD(lParam
);
1509 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1511 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1512 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1513 infoPtr
->iHotItem
= nItem
;
1515 infoPtr
->iHotItem
= -1;
1516 InvalidateRect(hwnd
, NULL
, FALSE
);
1519 if (infoPtr
->bCaptured
) {
1520 if (infoPtr
->bPressed
) {
1521 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1522 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1524 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1526 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1527 ReleaseDC (hwnd
, hdc
);
1529 TRACE("Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1531 else if (infoPtr
->bTracking
) {
1532 if (dwStyle
& HDS_FULLDRAG
) {
1533 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1535 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1538 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1539 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1541 HEADER_SetItemBounds (hwnd
);
1542 InvalidateRect(hwnd
, NULL
, FALSE
);
1546 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1547 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1548 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1549 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1550 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1551 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1552 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1553 ReleaseDC (hwnd
, hdc
);
1554 HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1557 TRACE("Tracking item %d!\n", infoPtr
->iMoveItem
);
1561 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1562 FIXME("hot track support!\n");
1570 HEADER_Paint (HWND hwnd
, WPARAM wParam
)
1575 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1576 HEADER_Refresh (hwnd
, hdc
);
1578 EndPaint (hwnd
, &ps
);
1584 HEADER_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1589 pt
.x
= LOWORD(lParam
);
1590 pt
.y
= HIWORD(lParam
);
1592 /* Send a Notify message */
1593 bRet
= HEADER_SendSimpleNotify (hwnd
, NM_RCLICK
);
1595 /* Change to screen coordinate for WM_CONTEXTMENU */
1596 ClientToScreen(hwnd
, &pt
);
1598 /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */
1599 SendMessageA( hwnd
, WM_CONTEXTMENU
, (WPARAM
) hwnd
, MAKELPARAM(pt
.x
, pt
.y
));
1606 HEADER_SetCursor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1608 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1613 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1616 ScreenToClient (hwnd
, &pt
);
1618 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1620 if (flags
== HHT_ONDIVIDER
)
1621 SetCursor (infoPtr
->hcurDivider
);
1622 else if (flags
== HHT_ONDIVOPEN
)
1623 SetCursor (infoPtr
->hcurDivopen
);
1625 SetCursor (infoPtr
->hcurArrow
);
1632 HEADER_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1634 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1636 HFONT hFont
, hOldFont
;
1639 infoPtr
->hFont
= (HFONT
)wParam
;
1641 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
1644 hOldFont
= SelectObject (hdc
, hFont
);
1645 GetTextMetricsA (hdc
, &tm
);
1646 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1647 SelectObject (hdc
, hOldFont
);
1650 infoPtr
->bRectsValid
= FALSE
;
1653 InvalidateRect(hwnd
, NULL
, FALSE
);
1660 static LRESULT WINAPI
1661 HEADER_WindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1663 TRACE("hwnd=%x msg=%x wparam=%x lParam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1664 if (!HEADER_GetInfoPtr (hwnd
) && (msg
!= WM_CREATE
))
1665 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1667 /* case HDM_CLEARFILTER: */
1669 case HDM_CREATEDRAGIMAGE
:
1670 return HEADER_CreateDragImage (hwnd
, wParam
);
1672 case HDM_DELETEITEM
:
1673 return HEADER_DeleteItem (hwnd
, wParam
);
1675 /* case HDM_EDITFILTER: */
1677 /* case HDM_GETBITMAPMARGIN: */
1679 case HDM_GETIMAGELIST
:
1680 return HEADER_GetImageList (hwnd
);
1683 return HEADER_GetItemA (hwnd
, wParam
, lParam
);
1686 return HEADER_GetItemW (hwnd
, wParam
, lParam
);
1688 case HDM_GETITEMCOUNT
:
1689 return HEADER_GetItemCount (hwnd
);
1691 case HDM_GETITEMRECT
:
1692 return HEADER_GetItemRect (hwnd
, wParam
, lParam
);
1694 case HDM_GETORDERARRAY
:
1695 return HEADER_GetOrderArray(hwnd
, wParam
, lParam
);
1697 case HDM_GETUNICODEFORMAT
:
1698 return HEADER_GetUnicodeFormat (hwnd
);
1701 return HEADER_HitTest (hwnd
, wParam
, lParam
);
1703 case HDM_INSERTITEMA
:
1704 return HEADER_InsertItemA (hwnd
, wParam
, lParam
);
1706 case HDM_INSERTITEMW
:
1707 return HEADER_InsertItemW (hwnd
, wParam
, lParam
);
1710 return HEADER_Layout (hwnd
, wParam
, lParam
);
1712 case HDM_ORDERTOINDEX
:
1713 return HEADER_OrderToIndex(hwnd
, wParam
);
1715 /* case HDM_SETBITMAPMARGIN: */
1717 /* case HDM_SETFILTERCHANGETIMEOUT: */
1719 /* case HDM_SETHOTDIVIDER: */
1721 case HDM_SETIMAGELIST
:
1722 return HEADER_SetImageList (hwnd
, (HIMAGELIST
)lParam
);
1725 return HEADER_SetItemA (hwnd
, wParam
, lParam
);
1728 return HEADER_SetItemW (hwnd
, wParam
, lParam
);
1730 case HDM_SETORDERARRAY
:
1731 return HEADER_SetOrderArray(hwnd
, wParam
, lParam
);
1733 case HDM_SETUNICODEFORMAT
:
1734 return HEADER_SetUnicodeFormat (hwnd
, wParam
);
1737 return HEADER_Create (hwnd
, wParam
, lParam
);
1740 return HEADER_Destroy (hwnd
, wParam
, lParam
);
1746 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1749 return HEADER_GetFont (hwnd
);
1751 case WM_LBUTTONDBLCLK
:
1752 return HEADER_LButtonDblClk (hwnd
, wParam
, lParam
);
1754 case WM_LBUTTONDOWN
:
1755 return HEADER_LButtonDown (hwnd
, wParam
, lParam
);
1758 return HEADER_LButtonUp (hwnd
, wParam
, lParam
);
1761 return HEADER_MouseMove (hwnd
, wParam
, lParam
);
1763 case WM_NOTIFYFORMAT
:
1764 return HEADER_NotifyFormat (hwnd
, wParam
, lParam
);
1767 return HEADER_Size (hwnd
, wParam
);
1770 return HEADER_Paint (hwnd
, wParam
);
1773 return HEADER_RButtonUp (hwnd
, wParam
, lParam
);
1776 return HEADER_SetCursor (hwnd
, wParam
, lParam
);
1779 return HEADER_SetFont (hwnd
, wParam
, lParam
);
1782 if ((msg
>= WM_USER
) && (msg
< WM_APP
))
1783 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1784 msg
, wParam
, lParam
);
1785 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1792 HEADER_Register (void)
1796 ZeroMemory (&wndClass
, sizeof(WNDCLASSA
));
1797 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1798 wndClass
.lpfnWndProc
= (WNDPROC
)HEADER_WindowProc
;
1799 wndClass
.cbClsExtra
= 0;
1800 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1801 wndClass
.hCursor
= LoadCursorA (0, IDC_ARROWA
);
1802 wndClass
.lpszClassName
= WC_HEADERA
;
1804 RegisterClassA (&wndClass
);
1809 HEADER_Unregister (void)
1811 UnregisterClassA (WC_HEADERA
, (HINSTANCE
)NULL
);