4 * Copyright 1998 Eric Kohl
5 * Copyright 2000 Eric Kohl for CodeWeavers
6 * Copyright 2003 Maxime Bellenge
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * - Imagelist support (partially).
24 * - Callback items (under construction).
25 * - Hottrack support (partially).
26 * - Custom draw support (including Notifications).
27 * - Drag and Drop support (including Notifications).
29 * - Use notification format
30 * - Correct the order maintenance code to preserve valid order
39 #include "wine/unicode.h"
45 #include "imagelist.h"
46 #include "wine/debug.h"
48 WINE_DEFAULT_DEBUG_CHANNEL(header
);
58 INT iOrder
; /* see documentation of HD_ITEM */
60 BOOL bDown
; /* is item pressed? (used for drawing) */
61 RECT rect
; /* bounding rectangle of the item */
67 HWND hwndNotify
; /* Owner window to send notifications to */
68 INT nNotifyFormat
; /* format used for WM_NOTIFY messages */
69 UINT uNumItem
; /* number of items (columns) */
70 INT nHeight
; /* height of the header (pixels) */
71 HFONT hFont
; /* handle to the current font */
72 HCURSOR hcurArrow
; /* handle to the arrow cursor */
73 HCURSOR hcurDivider
; /* handle to a cursor (used over dividers) <-|-> */
74 HCURSOR hcurDivopen
; /* handle to a cursor (used over dividers) <-||-> */
75 BOOL bCaptured
; /* Is the mouse captured? */
76 BOOL bPressed
; /* Is a header item pressed (down)? */
77 BOOL bTracking
; /* Is in tracking mode? */
78 BOOL bUnicode
; /* Unicode flag */
79 INT iMoveItem
; /* index of tracked item. (Tracking mode) */
80 INT xTrackOffset
; /* distance between the right side of the tracked item and the cursor */
81 INT xOldTrack
; /* track offset (see above) after the last WM_MOUSEMOVE */
82 INT nOldWidth
; /* width of a sizing item after the last WM_MOUSEMOVE */
83 INT iHotItem
; /* index of hot item (cursor is over this item) */
84 INT iMargin
; /* width of the margin that surrounds a bitmap */
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 *)GetWindowLongPtrW(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 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
);
131 infoPtr
->bRectsValid
= TRUE
;
133 if (infoPtr
->uNumItem
== 0)
136 GetClientRect (hwnd
, &rect
);
139 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
140 phdi
= &infoPtr
->items
[HEADER_OrderToIndex(hwnd
,i
)];
141 phdi
->rect
.top
= rect
.top
;
142 phdi
->rect
.bottom
= rect
.bottom
;
144 phdi
->rect
.right
= phdi
->rect
.left
+ ((phdi
->cxy
>0)?phdi
->cxy
:0);
145 x
= phdi
->rect
.right
;
150 HEADER_Size (HWND hwnd
, WPARAM wParam
)
152 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
154 infoPtr
->bRectsValid
= FALSE
;
161 HEADER_DrawItem (HWND hwnd
, HDC hdc
, INT iItem
, BOOL bHotTrack
)
163 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
164 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
168 TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem
, bHotTrack
, infoPtr
->bUnicode
);
170 if (!infoPtr
->bRectsValid
)
171 HEADER_SetItemBounds(hwnd
);
174 if (r
.right
- r
.left
== 0)
175 return phdi
->rect
.right
;
177 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) {
179 DrawEdge (hdc
, &r
, BDR_RAISEDOUTER
,
180 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
185 DrawEdge (hdc
, &r
, EDGE_RAISED
,
186 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
189 DrawEdge (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
191 if (phdi
->fmt
& HDF_OWNERDRAW
) {
193 dis
.CtlType
= ODT_HEADER
;
194 dis
.CtlID
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
196 dis
.itemAction
= ODA_DRAWENTIRE
;
197 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
201 dis
.itemData
= phdi
->lParam
;
202 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
203 SendMessageW (infoPtr
->hwndNotify
, WM_DRAWITEM
,
204 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
205 if (oldBkMode
!= TRANSPARENT
)
206 SetBkMode(hdc
, oldBkMode
);
209 UINT uTextJustify
= DT_LEFT
;
211 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
212 uTextJustify
= DT_CENTER
;
213 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
214 uTextJustify
= DT_RIGHT
;
216 if ((phdi
->fmt
& HDF_BITMAP
) && !(phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
219 INT yD
, yS
, cx
, cy
, rx
, ry
;
221 GetObjectW (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
223 ry
= r
.bottom
- r
.top
;
224 rx
= r
.right
- r
.left
;
226 if (ry
>= bmp
.bmHeight
) {
228 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
234 yS
= (bmp
.bmHeight
- ry
) / 2;
238 if (rx
>= bmp
.bmWidth
+ infoPtr
->iMargin
) {
242 cx
= rx
- infoPtr
->iMargin
;
245 hdcBitmap
= CreateCompatibleDC (hdc
);
246 SelectObject (hdcBitmap
, phdi
->hbm
);
247 BitBlt (hdc
, r
.left
+ infoPtr
->iMargin
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
248 DeleteDC (hdcBitmap
);
250 r
.left
+= (bmp
.bmWidth
+ infoPtr
->iMargin
);
254 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (phdi
->hbm
)) {
257 INT xD
, yD
, yS
, cx
, cy
, rx
, ry
, tx
;
260 GetObjectW (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
263 if (phdi
->fmt
& HDF_STRING
) {
264 DrawTextW (hdc
, phdi
->pszText
, -1,
265 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
266 tx
= textRect
.right
- textRect
.left
;
270 ry
= r
.bottom
- r
.top
;
271 rx
= r
.right
- r
.left
;
273 if (ry
>= bmp
.bmHeight
) {
275 yD
= r
.top
+ (ry
- bmp
.bmHeight
) / 2;
281 yS
= (bmp
.bmHeight
- ry
) / 2;
285 if (r
.left
+ tx
+ bmp
.bmWidth
+ 2*infoPtr
->iMargin
<= r
.right
) {
287 xD
= r
.left
+ tx
+ infoPtr
->iMargin
;
290 if (rx
>= bmp
.bmWidth
+ infoPtr
->iMargin
) {
292 xD
= r
.right
- bmp
.bmWidth
- infoPtr
->iMargin
;
293 r
.right
= xD
- infoPtr
->iMargin
;
296 cx
= rx
- infoPtr
->iMargin
;
302 hdcBitmap
= CreateCompatibleDC (hdc
);
303 SelectObject (hdcBitmap
, phdi
->hbm
);
304 BitBlt (hdc
, xD
, yD
, cx
, cy
, hdcBitmap
, 0, yS
, SRCCOPY
);
305 DeleteDC (hdcBitmap
);
308 if ((phdi
->fmt
& HDF_IMAGE
) && !(phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (infoPtr
->himl
)) {
309 r
.left
+= infoPtr
->iMargin
;
310 ImageList_DrawEx(infoPtr
->himl
, phdi
->iImage
, hdc
, r
.left
, r
.top
+ (r
.bottom
-r
.top
- infoPtr
->himl
->cy
)/2,
311 infoPtr
->himl
->cx
, r
.bottom
-r
.top
, CLR_DEFAULT
, CLR_DEFAULT
, 0);
312 r
.left
+= infoPtr
->himl
->cx
;
315 if ((phdi
->fmt
& HDF_IMAGE
) && (phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) && (infoPtr
->himl
)) {
320 if (phdi
->fmt
& HDF_STRING
) {
321 DrawTextW (hdc
, phdi
->pszText
, -1,
322 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
323 tx
= textRect
.right
- textRect
.left
;
328 if (tx
< (r
.right
-r
.left
- infoPtr
->himl
->cx
- GetSystemMetrics(SM_CXEDGE
)))
329 ImageList_DrawEx(infoPtr
->himl
, phdi
->iImage
, hdc
, r
.left
+ tx
+ 2*infoPtr
->iMargin
,
330 r
.top
+ (r
.bottom
-r
.top
-infoPtr
->himl
->cy
)/2, infoPtr
->himl
->cx
, r
.bottom
-r
.top
,
331 CLR_DEFAULT
, CLR_DEFAULT
, 0);
333 INT x
= max(r
.right
- infoPtr
->iMargin
- infoPtr
->himl
->cx
, r
.left
);
334 INT cx
= min(infoPtr
->himl
->cx
, r
.right
-r
.left
- GetSystemMetrics(SM_CXEDGE
));
335 ImageList_DrawEx(infoPtr
->himl
, phdi
->iImage
, hdc
, x
,
336 r
.top
+ (r
.bottom
-r
.top
-infoPtr
->himl
->cy
)/2, cx
, r
.bottom
-r
.top
,
337 CLR_DEFAULT
, CLR_DEFAULT
, 0);
338 r
.right
-= infoPtr
->himl
->cx
- infoPtr
->iMargin
;
342 if (((phdi
->fmt
& HDF_STRING
)
343 || (!(phdi
->fmt
& (HDF_OWNERDRAW
|HDF_STRING
|HDF_BITMAP
|
344 HDF_BITMAP_ON_RIGHT
|HDF_IMAGE
)))) /* no explicit format specified? */
345 && (phdi
->pszText
)) {
346 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
347 r
.left
+= infoPtr
->iMargin
;
348 r
.right
-= infoPtr
->iMargin
;
349 SetTextColor (hdc
, (bHotTrack
) ? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
350 DrawTextW (hdc
, phdi
->pszText
, -1,
351 &r
, uTextJustify
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
352 if (oldBkMode
!= TRANSPARENT
)
353 SetBkMode(hdc
, oldBkMode
);
357 return phdi
->rect
.right
;
362 HEADER_Refresh (HWND hwnd
, HDC hdc
)
364 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
365 HFONT hFont
, hOldFont
;
371 /* get rect for the bar, adjusted for the border */
372 GetClientRect (hwnd
, &rect
);
374 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
375 hOldFont
= SelectObject (hdc
, hFont
);
377 /* draw Background */
378 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
379 FillRect(hdc
, &rect
, hbrBk
);
382 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
383 x
= HEADER_DrawItem (hwnd
, hdc
, HEADER_OrderToIndex(hwnd
,i
), FALSE
);
386 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
388 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
)
389 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
391 DrawEdge (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
394 SelectObject (hdc
, hOldFont
);
399 HEADER_RefreshItem (HWND hwnd
, HDC hdc
, INT iItem
)
401 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
402 HFONT hFont
, hOldFont
;
404 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
405 hOldFont
= SelectObject (hdc
, hFont
);
406 HEADER_DrawItem (hwnd
, hdc
, iItem
, FALSE
);
407 SelectObject (hdc
, hOldFont
);
412 HEADER_InternalHitTest (HWND hwnd
, LPPOINT lpPt
, UINT
*pFlags
, INT
*pItem
)
414 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
420 GetClientRect (hwnd
, &rect
);
424 if (PtInRect (&rect
, *lpPt
))
426 if (infoPtr
->uNumItem
== 0) {
427 *pFlags
|= HHT_NOWHERE
;
433 /* somewhere inside */
434 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
435 rect
= infoPtr
->items
[iCount
].rect
;
436 width
= rect
.right
- rect
.left
;
441 if (PtInRect (&rect
, *lpPt
)) {
442 if (width
<= 2 * DIVIDER_WIDTH
) {
443 *pFlags
|= HHT_ONHEADER
;
445 TRACE("ON HEADER %d\n", iCount
);
450 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
451 if (PtInRect (&rcTest
, *lpPt
)) {
453 *pFlags
|= HHT_ONDIVOPEN
;
455 TRACE("ON DIVOPEN %d\n", *pItem
);
459 *pFlags
|= HHT_ONDIVIDER
;
461 TRACE("ON DIVIDER %d\n", *pItem
);
467 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
468 if (PtInRect (&rcTest
, *lpPt
)) {
469 *pFlags
|= HHT_ONDIVIDER
;
471 TRACE("ON DIVIDER %d\n", *pItem
);
475 *pFlags
|= HHT_ONHEADER
;
477 TRACE("ON HEADER %d\n", iCount
);
482 /* check for last divider part (on nowhere) */
483 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
484 rect
.left
= rect
.right
;
485 rect
.right
+= DIVIDER_WIDTH
;
486 if (PtInRect (&rect
, *lpPt
)) {
488 *pFlags
|= HHT_ONDIVOPEN
;
489 *pItem
= infoPtr
->uNumItem
- 1;
490 TRACE("ON DIVOPEN %d\n", *pItem
);
494 *pFlags
|= HHT_ONDIVIDER
;
495 *pItem
= infoPtr
->uNumItem
-1;
496 TRACE("ON DIVIDER %d\n", *pItem
);
501 *pFlags
|= HHT_NOWHERE
;
508 if (lpPt
->x
< rect
.left
) {
510 *pFlags
|= HHT_TOLEFT
;
512 else if (lpPt
->x
> rect
.right
) {
514 *pFlags
|= HHT_TORIGHT
;
517 if (lpPt
->y
< rect
.top
) {
519 *pFlags
|= HHT_ABOVE
;
521 else if (lpPt
->y
> rect
.bottom
) {
523 *pFlags
|= HHT_BELOW
;
528 TRACE("flags=0x%X\n", *pFlags
);
534 HEADER_DrawTrackLine (HWND hwnd
, HDC hdc
, INT x
)
540 GetClientRect (hwnd
, &rect
);
542 hOldPen
= SelectObject (hdc
, GetStockObject (BLACK_PEN
));
543 oldRop
= SetROP2 (hdc
, R2_XORPEN
);
544 MoveToEx (hdc
, x
, rect
.top
, NULL
);
545 LineTo (hdc
, x
, rect
.bottom
);
546 SetROP2 (hdc
, oldRop
);
547 SelectObject (hdc
, hOldPen
);
552 HEADER_SendSimpleNotify (HWND hwnd
, UINT code
)
554 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
557 nmhdr
.hwndFrom
= hwnd
;
558 nmhdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
561 return (BOOL
)SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
562 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
566 HEADER_SendHeaderNotify (HWND hwnd
, UINT code
, INT iItem
, INT mask
)
568 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
572 nmhdr
.hdr
.hwndFrom
= hwnd
;
573 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
574 nmhdr
.hdr
.code
= code
;
577 nmhdr
.pitem
= &nmitem
;
579 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
580 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
581 nmitem
.pszText
= NULL
;
582 nmitem
.cchTextMax
= 0;
583 /* nmitem.pszText = infoPtr->items[iItem].pszText; */
584 /* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
585 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
586 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
587 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
588 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
590 return (BOOL
)SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
591 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
596 HEADER_SendClickNotify (HWND hwnd
, UINT code
, INT iItem
)
598 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
601 nmhdr
.hdr
.hwndFrom
= hwnd
;
602 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
603 nmhdr
.hdr
.code
= code
;
608 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
609 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
614 HEADER_CreateDragImage (HWND hwnd
, WPARAM wParam
)
616 FIXME("empty stub!\n");
622 HEADER_DeleteItem (HWND hwnd
, WPARAM wParam
)
624 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
625 INT iItem
= (INT
)wParam
;
627 TRACE("[iItem=%d]\n", iItem
);
629 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
632 if (infoPtr
->uNumItem
== 1) {
633 TRACE("Simple delete!\n");
634 if (infoPtr
->items
[0].pszText
)
635 Free (infoPtr
->items
[0].pszText
);
636 Free (infoPtr
->items
);
638 infoPtr
->uNumItem
= 0;
641 HEADER_ITEM
*oldItems
= infoPtr
->items
;
645 TRACE("Complex delete! [iItem=%d]\n", iItem
);
647 if (infoPtr
->items
[iItem
].pszText
)
648 Free (infoPtr
->items
[iItem
].pszText
);
649 iOrder
= infoPtr
->items
[iItem
].iOrder
;
652 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
653 /* pre delete copy */
655 memcpy (&infoPtr
->items
[0], &oldItems
[0],
656 iItem
* sizeof(HEADER_ITEM
));
659 /* post delete copy */
660 if (iItem
< infoPtr
->uNumItem
) {
661 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
662 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
665 /* Correct the orders */
666 for (i
=infoPtr
->uNumItem
, pItem
= infoPtr
->items
; i
; i
--, pItem
++)
668 if (pItem
->iOrder
> iOrder
)
674 HEADER_SetItemBounds (hwnd
);
676 InvalidateRect(hwnd
, NULL
, FALSE
);
683 HEADER_GetImageList (HWND hwnd
)
685 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
687 return (LRESULT
)infoPtr
->himl
;
692 HEADER_GetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
694 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
695 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
696 INT nItem
= (INT
)wParam
;
702 TRACE("[nItem=%d]\n", nItem
);
707 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
)) {
711 lpItem
= &infoPtr
->items
[nItem
];
714 if (phdi
->mask
& HDI_BITMAP
)
715 phdi
->hbm
= (lpItem
!= NULL
) ? lpItem
->hbm
: 0;
717 if (phdi
->mask
& HDI_FORMAT
)
718 phdi
->fmt
= (lpItem
!= NULL
) ? lpItem
->fmt
: 0;
720 if (phdi
->mask
& HDI_WIDTH
)
721 phdi
->cxy
= (lpItem
!= NULL
) ? lpItem
->cxy
: 0;
723 if (phdi
->mask
& HDI_LPARAM
)
724 phdi
->lParam
= (lpItem
!= NULL
) ? lpItem
->lParam
: 0;
726 if (phdi
->mask
& HDI_TEXT
) {
727 if (lpItem
== NULL
) {
730 else if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
732 WideCharToMultiByte (CP_ACP
, 0, lpItem
->pszText
, -1,
733 phdi
->pszText
, phdi
->cchTextMax
, NULL
, NULL
);
738 phdi
->pszText
= LPSTR_TEXTCALLBACKA
;
741 if (phdi
->mask
& HDI_IMAGE
)
742 phdi
->iImage
= (lpItem
!= NULL
) ? lpItem
->iImage
: 0;
744 if (phdi
->mask
& HDI_ORDER
)
745 phdi
->iOrder
= (lpItem
!= NULL
) ? lpItem
->iOrder
: 0;
752 HEADER_GetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
754 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
755 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
756 INT nItem
= (INT
)wParam
;
762 TRACE("[nItem=%d]\n", nItem
);
767 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
)) {
771 lpItem
= &infoPtr
->items
[nItem
];
774 if (phdi
->mask
& HDI_BITMAP
)
775 phdi
->hbm
= (lpItem
!= NULL
) ? lpItem
->hbm
: 0;
777 if (phdi
->mask
& HDI_FORMAT
)
778 phdi
->fmt
= (lpItem
!= NULL
) ? lpItem
->fmt
: 0;
780 if (phdi
->mask
& HDI_WIDTH
)
781 phdi
->cxy
= (lpItem
!= NULL
) ? lpItem
->cxy
: 0;
783 if (phdi
->mask
& HDI_LPARAM
)
784 phdi
->lParam
= (lpItem
!= NULL
) ? lpItem
->lParam
: 0;
786 if (phdi
->mask
& HDI_TEXT
) {
787 if (lpItem
== NULL
) {
790 else if (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
) {
792 lstrcpynW (phdi
->pszText
, lpItem
->pszText
, phdi
->cchTextMax
);
797 phdi
->pszText
= LPSTR_TEXTCALLBACKW
;
800 if (phdi
->mask
& HDI_IMAGE
)
801 phdi
->iImage
= (lpItem
!= NULL
) ? lpItem
->iImage
: 0;
803 if (phdi
->mask
& HDI_ORDER
)
804 phdi
->iOrder
= (lpItem
!= NULL
) ? lpItem
->iOrder
: 0;
810 inline static LRESULT
811 HEADER_GetItemCount (HWND hwnd
)
813 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
814 return infoPtr
->uNumItem
;
819 HEADER_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
821 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
822 INT iItem
= (INT
)wParam
;
823 LPRECT lpRect
= (LPRECT
)lParam
;
825 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
828 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
829 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
830 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
831 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
838 HEADER_GetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
841 LPINT order
= (LPINT
) lParam
;
842 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
844 if ((unsigned int)wParam
<infoPtr
->uNumItem
)
846 for (i
=0; i
<(int)wParam
; i
++)
847 *order
++=HEADER_OrderToIndex(hwnd
,i
);
852 HEADER_SetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
855 LPINT order
= (LPINT
) lParam
;
856 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
859 if ((unsigned int)wParam
<infoPtr
->uNumItem
)
861 for (i
=0; i
<(int)wParam
; i
++)
863 lpItem
= &infoPtr
->items
[*order
++];
866 infoPtr
->bRectsValid
=0;
867 InvalidateRect(hwnd
, NULL
, FALSE
);
871 inline static LRESULT
872 HEADER_GetUnicodeFormat (HWND hwnd
)
874 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
875 return infoPtr
->bUnicode
;
880 HEADER_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
882 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
884 HEADER_InternalHitTest (hwnd
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
886 if (phti
->flags
== HHT_NOWHERE
)
894 HEADER_InsertItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
896 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
897 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
898 INT nItem
= (INT
)wParam
;
903 if ((phdi
== NULL
) || (nItem
< 0))
906 if (nItem
> infoPtr
->uNumItem
)
907 nItem
= infoPtr
->uNumItem
;
909 iOrder
= (phdi
->mask
& HDI_ORDER
) ? phdi
->iOrder
: nItem
;
911 if (infoPtr
->uNumItem
== 0) {
912 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
));
916 HEADER_ITEM
*oldItems
= infoPtr
->items
;
919 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
921 memcpy (&infoPtr
->items
[1], &oldItems
[0],
922 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
926 /* pre insert copy */
928 memcpy (&infoPtr
->items
[0], &oldItems
[0],
929 nItem
* sizeof(HEADER_ITEM
));
932 /* post insert copy */
933 if (nItem
< infoPtr
->uNumItem
- 1) {
934 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
935 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
942 for (i
=0; i
< infoPtr
->uNumItem
; i
++)
944 if (infoPtr
->items
[i
].iOrder
>= iOrder
)
945 infoPtr
->items
[i
].iOrder
++;
948 lpItem
= &infoPtr
->items
[nItem
];
949 lpItem
->bDown
= FALSE
;
951 if (phdi
->mask
& HDI_WIDTH
)
952 lpItem
->cxy
= phdi
->cxy
;
954 if (phdi
->mask
& HDI_TEXT
) {
955 if (!phdi
->pszText
) /* null pointer check */
957 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
958 len
= MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, NULL
, 0);
959 lpItem
->pszText
= Alloc( len
*sizeof(WCHAR
) );
960 MultiByteToWideChar(CP_ACP
, 0, phdi
->pszText
, -1, lpItem
->pszText
, len
);
963 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
966 if (phdi
->mask
& HDI_FORMAT
)
967 lpItem
->fmt
= phdi
->fmt
;
969 if (lpItem
->fmt
== 0)
970 lpItem
->fmt
= HDF_LEFT
;
972 if (!(lpItem
->fmt
& HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
974 lpItem
->fmt
|= HDF_STRING
;
976 if (phdi
->mask
& HDI_BITMAP
)
977 lpItem
->hbm
= phdi
->hbm
;
979 if (phdi
->mask
& HDI_LPARAM
)
980 lpItem
->lParam
= phdi
->lParam
;
982 if (phdi
->mask
& HDI_IMAGE
)
983 lpItem
->iImage
= phdi
->iImage
;
985 lpItem
->iOrder
= iOrder
;
987 HEADER_SetItemBounds (hwnd
);
989 InvalidateRect(hwnd
, NULL
, FALSE
);
996 HEADER_InsertItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
998 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
999 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
1000 INT nItem
= (INT
)wParam
;
1001 HEADER_ITEM
*lpItem
;
1005 if ((phdi
== NULL
) || (nItem
< 0))
1008 if (nItem
> infoPtr
->uNumItem
)
1009 nItem
= infoPtr
->uNumItem
;
1011 iOrder
= (phdi
->mask
& HDI_ORDER
) ? phdi
->iOrder
: nItem
;
1013 if (infoPtr
->uNumItem
== 0) {
1014 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
));
1015 infoPtr
->uNumItem
++;
1018 HEADER_ITEM
*oldItems
= infoPtr
->items
;
1020 infoPtr
->uNumItem
++;
1021 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
1023 memcpy (&infoPtr
->items
[1], &oldItems
[0],
1024 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
1028 /* pre insert copy */
1030 memcpy (&infoPtr
->items
[0], &oldItems
[0],
1031 nItem
* sizeof(HEADER_ITEM
));
1034 /* post insert copy */
1035 if (nItem
< infoPtr
->uNumItem
- 1) {
1036 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
1037 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
1044 for (i
=0; i
< infoPtr
->uNumItem
; i
++)
1046 if (infoPtr
->items
[i
].iOrder
>= iOrder
)
1047 infoPtr
->items
[i
].iOrder
++;
1050 lpItem
= &infoPtr
->items
[nItem
];
1051 lpItem
->bDown
= FALSE
;
1053 if (phdi
->mask
& HDI_WIDTH
)
1054 lpItem
->cxy
= phdi
->cxy
;
1056 if (phdi
->mask
& HDI_TEXT
) {
1057 WCHAR wide_null_char
= 0;
1058 if (!phdi
->pszText
) /* null pointer check */
1059 phdi
->pszText
= &wide_null_char
;
1060 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1061 len
= strlenW (phdi
->pszText
);
1062 lpItem
->pszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1063 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1066 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1069 if (phdi
->mask
& HDI_FORMAT
)
1070 lpItem
->fmt
= phdi
->fmt
;
1072 if (lpItem
->fmt
== 0)
1073 lpItem
->fmt
= HDF_LEFT
;
1075 if (!(lpItem
->fmt
&HDF_STRING
) && (phdi
->mask
& HDI_TEXT
))
1077 lpItem
->fmt
|= HDF_STRING
;
1079 if (phdi
->mask
& HDI_BITMAP
)
1080 lpItem
->hbm
= phdi
->hbm
;
1082 if (phdi
->mask
& HDI_LPARAM
)
1083 lpItem
->lParam
= phdi
->lParam
;
1085 if (phdi
->mask
& HDI_IMAGE
)
1086 lpItem
->iImage
= phdi
->iImage
;
1088 lpItem
->iOrder
= iOrder
;
1090 HEADER_SetItemBounds (hwnd
);
1092 InvalidateRect(hwnd
, NULL
, FALSE
);
1099 HEADER_Layout (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1101 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1102 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
1104 lpLayout
->pwpos
->hwnd
= hwnd
;
1105 lpLayout
->pwpos
->hwndInsertAfter
= 0;
1106 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
1107 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
1108 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
1109 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_HIDDEN
)
1110 lpLayout
->pwpos
->cy
= 0;
1112 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
1113 lpLayout
->prc
->top
+= infoPtr
->nHeight
;
1115 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
1117 TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
1118 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
1119 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
1121 infoPtr
->bRectsValid
= FALSE
;
1128 HEADER_SetImageList (HWND hwnd
, HIMAGELIST himl
)
1130 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1133 TRACE("(himl 0x%x)\n", (int)himl
);
1134 himlOld
= infoPtr
->himl
;
1135 infoPtr
->himl
= himl
;
1137 /* FIXME: Refresh needed??? */
1139 return (LRESULT
)himlOld
;
1144 HEADER_GetBitmapMargin(HWND hwnd
)
1146 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
1148 return infoPtr
->iMargin
;
1152 HEADER_SetBitmapMargin(HWND hwnd
, WPARAM wParam
)
1154 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1155 INT oldMargin
= infoPtr
->iMargin
;
1157 infoPtr
->iMargin
= (INT
)wParam
;
1163 HEADER_SetItemA (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1165 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1166 HDITEMA
*phdi
= (HDITEMA
*)lParam
;
1167 INT nItem
= (INT
)wParam
;
1168 HEADER_ITEM
*lpItem
;
1172 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1175 TRACE("[nItem=%d]\n", nItem
);
1177 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGA
, nItem
, phdi
->mask
))
1180 lpItem
= &infoPtr
->items
[nItem
];
1181 if (phdi
->mask
& HDI_BITMAP
)
1182 lpItem
->hbm
= phdi
->hbm
;
1184 if (phdi
->mask
& HDI_FORMAT
)
1185 lpItem
->fmt
= phdi
->fmt
;
1187 if (phdi
->mask
& HDI_LPARAM
)
1188 lpItem
->lParam
= phdi
->lParam
;
1190 if (phdi
->mask
& HDI_TEXT
) {
1191 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKA
) {
1192 if (lpItem
->pszText
) {
1193 Free (lpItem
->pszText
);
1194 lpItem
->pszText
= NULL
;
1196 if (phdi
->pszText
) {
1197 INT len
= MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,NULL
,0);
1198 lpItem
->pszText
= Alloc( len
*sizeof(WCHAR
) );
1199 MultiByteToWideChar (CP_ACP
,0,phdi
->pszText
,-1,lpItem
->pszText
,len
);
1203 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1206 if (phdi
->mask
& HDI_WIDTH
)
1207 lpItem
->cxy
= phdi
->cxy
;
1209 if (phdi
->mask
& HDI_IMAGE
)
1210 lpItem
->iImage
= phdi
->iImage
;
1212 if (phdi
->mask
& HDI_ORDER
)
1214 lpItem
->iOrder
= phdi
->iOrder
;
1217 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGEDA
, nItem
, phdi
->mask
);
1219 HEADER_SetItemBounds (hwnd
);
1221 InvalidateRect(hwnd
, NULL
, FALSE
);
1228 HEADER_SetItemW (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1230 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1231 HDITEMW
*phdi
= (HDITEMW
*)lParam
;
1232 INT nItem
= (INT
)wParam
;
1233 HEADER_ITEM
*lpItem
;
1237 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1240 TRACE("[nItem=%d]\n", nItem
);
1242 if (HEADER_SendHeaderNotify (hwnd
, HDN_ITEMCHANGINGW
, nItem
, phdi
->mask
))
1245 lpItem
= &infoPtr
->items
[nItem
];
1246 if (phdi
->mask
& HDI_BITMAP
)
1247 lpItem
->hbm
= phdi
->hbm
;
1249 if (phdi
->mask
& HDI_FORMAT
)
1250 lpItem
->fmt
= phdi
->fmt
;
1252 if (phdi
->mask
& HDI_LPARAM
)
1253 lpItem
->lParam
= phdi
->lParam
;
1255 if (phdi
->mask
& HDI_TEXT
) {
1256 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) {
1257 if (lpItem
->pszText
) {
1258 Free (lpItem
->pszText
);
1259 lpItem
->pszText
= NULL
;
1261 if (phdi
->pszText
) {
1262 INT len
= strlenW (phdi
->pszText
);
1263 lpItem
->pszText
= Alloc ((len
+1)*sizeof(WCHAR
));
1264 strcpyW (lpItem
->pszText
, phdi
->pszText
);
1268 lpItem
->pszText
= LPSTR_TEXTCALLBACKW
;
1271 if (phdi
->mask
& HDI_WIDTH
)
1272 lpItem
->cxy
= phdi
->cxy
;
1274 if (phdi
->mask
& HDI_IMAGE
)
1275 lpItem
->iImage
= phdi
->iImage
;
1277 if (phdi
->mask
& HDI_ORDER
)
1279 lpItem
->iOrder
= phdi
->iOrder
;
1282 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDW
, nItem
, phdi
->mask
);
1284 HEADER_SetItemBounds (hwnd
);
1286 InvalidateRect(hwnd
, NULL
, FALSE
);
1291 inline static LRESULT
1292 HEADER_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
)
1294 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1295 BOOL bTemp
= infoPtr
->bUnicode
;
1297 infoPtr
->bUnicode
= (BOOL
)wParam
;
1304 HEADER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1306 HEADER_INFO
*infoPtr
;
1311 infoPtr
= (HEADER_INFO
*)Alloc (sizeof(HEADER_INFO
));
1312 SetWindowLongPtrW (hwnd
, 0, (DWORD_PTR
)infoPtr
);
1314 infoPtr
->hwndNotify
= ((LPCREATESTRUCTA
)lParam
)->hwndParent
;
1315 infoPtr
->uNumItem
= 0;
1318 infoPtr
->bRectsValid
= FALSE
;
1319 infoPtr
->hcurArrow
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1320 infoPtr
->hcurDivider
= LoadCursorW (COMCTL32_hModule
, MAKEINTRESOURCEW(IDC_DIVIDER
));
1321 infoPtr
->hcurDivopen
= LoadCursorW (COMCTL32_hModule
, MAKEINTRESOURCEW(IDC_DIVIDEROPEN
));
1322 infoPtr
->bPressed
= FALSE
;
1323 infoPtr
->bTracking
= FALSE
;
1324 infoPtr
->iMoveItem
= 0;
1326 infoPtr
->iHotItem
= -1;
1327 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
1328 infoPtr
->iMargin
= 3*GetSystemMetrics(SM_CXEDGE
);
1329 infoPtr
->nNotifyFormat
=
1330 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
1333 hOldFont
= SelectObject (hdc
, GetStockObject (SYSTEM_FONT
));
1334 GetTextMetricsW (hdc
, &tm
);
1335 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1336 SelectObject (hdc
, hOldFont
);
1344 HEADER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1346 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1347 HEADER_ITEM
*lpItem
;
1350 if (infoPtr
->items
) {
1351 lpItem
= infoPtr
->items
;
1352 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
1353 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
))
1354 Free (lpItem
->pszText
);
1356 Free (infoPtr
->items
);
1360 ImageList_Destroy (infoPtr
->himl
);
1362 SetWindowLongPtrW (hwnd
, 0, 0);
1368 static inline LRESULT
1369 HEADER_GetFont (HWND hwnd
)
1371 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1373 return (LRESULT
)infoPtr
->hFont
;
1378 HEADER_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1384 pt
.x
= (INT
)LOWORD(lParam
);
1385 pt
.y
= (INT
)HIWORD(lParam
);
1386 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1388 if ((GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
1389 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMDBLCLICKA
, nItem
,0);
1390 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
1391 HEADER_SendHeaderNotify (hwnd
, HDN_DIVIDERDBLCLICKA
, nItem
,0);
1398 HEADER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1400 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1401 DWORD dwStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
1407 pt
.x
= (INT
)LOWORD(lParam
);
1408 pt
.y
= (INT
)HIWORD(lParam
);
1409 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1411 if ((dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
1413 infoPtr
->bCaptured
= TRUE
;
1414 infoPtr
->bPressed
= TRUE
;
1415 infoPtr
->iMoveItem
= nItem
;
1417 infoPtr
->items
[nItem
].bDown
= TRUE
;
1419 /* Send WM_CUSTOMDRAW */
1421 HEADER_RefreshItem (hwnd
, hdc
, nItem
);
1422 ReleaseDC (hwnd
, hdc
);
1424 TRACE("Pressed item %d!\n", nItem
);
1426 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
1427 if (!(HEADER_SendHeaderNotify (hwnd
, HDN_BEGINTRACKA
, nItem
,0))) {
1429 infoPtr
->bCaptured
= TRUE
;
1430 infoPtr
->bTracking
= TRUE
;
1431 infoPtr
->iMoveItem
= nItem
;
1432 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
1433 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
1435 if (!(dwStyle
& HDS_FULLDRAG
)) {
1436 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
1438 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1439 ReleaseDC (hwnd
, hdc
);
1442 TRACE("Begin tracking item %d!\n", nItem
);
1451 HEADER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1453 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1455 *DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
1462 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1463 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1464 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1466 if (infoPtr
->bPressed
) {
1467 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1468 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1470 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1471 ReleaseDC (hwnd
, hdc
);
1473 HEADER_SendClickNotify (hwnd
, HDN_ITEMCLICKA
, infoPtr
->iMoveItem
);
1475 else if (flags
== HHT_ONHEADER
)
1477 HEADER_ITEM
*lpItem
;
1478 INT newindex
= HEADER_IndexToOrder(hwnd
,nItem
);
1479 INT oldindex
= HEADER_IndexToOrder(hwnd
,infoPtr
->iMoveItem
);
1481 TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
1482 infoPtr
->iMoveItem
,oldindex
,nItem
,newindex
);
1483 lpItem
= &infoPtr
->items
[nItem
];
1484 lpItem
->iOrder
=oldindex
;
1486 lpItem
= &infoPtr
->items
[infoPtr
->iMoveItem
];
1487 lpItem
->iOrder
= newindex
;
1489 infoPtr
->bRectsValid
= FALSE
;
1490 InvalidateRect(hwnd
, NULL
, FALSE
);
1491 /* FIXME: Should some WM_NOTIFY be sent */
1494 TRACE("Released item %d!\n", infoPtr
->iMoveItem
);
1495 infoPtr
->bPressed
= FALSE
;
1497 else if (infoPtr
->bTracking
) {
1498 TRACE("End tracking item %d!\n", infoPtr
->iMoveItem
);
1499 infoPtr
->bTracking
= FALSE
;
1501 HEADER_SendHeaderNotify (hwnd
, HDN_ENDTRACKA
, infoPtr
->iMoveItem
,HDI_WIDTH
);
1504 * we want to do this even for HDS_FULLDRAG because this is where
1505 * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications
1507 * if (!(dwStyle & HDS_FULLDRAG)) {
1511 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1512 ReleaseDC (hwnd
, hdc
);
1513 if (HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1515 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1518 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1521 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1524 HEADER_SetItemBounds (hwnd
);
1525 InvalidateRect(hwnd
, NULL
, TRUE
);
1526 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1532 if (infoPtr
->bCaptured
) {
1533 infoPtr
->bCaptured
= FALSE
;
1535 HEADER_SendSimpleNotify (hwnd
, NM_RELEASEDCAPTURE
);
1543 HEADER_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1545 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1550 return infoPtr
->nNotifyFormat
;
1553 infoPtr
->nNotifyFormat
=
1554 SendMessageW ((HWND
)wParam
, WM_NOTIFYFORMAT
,
1555 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1556 return infoPtr
->nNotifyFormat
;
1564 HEADER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1566 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1567 DWORD dwStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
1573 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1574 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1575 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1577 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1578 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1579 infoPtr
->iHotItem
= nItem
;
1581 infoPtr
->iHotItem
= -1;
1582 InvalidateRect(hwnd
, NULL
, FALSE
);
1585 if (infoPtr
->bCaptured
) {
1586 if (infoPtr
->bPressed
) {
1587 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1588 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1590 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1592 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1593 ReleaseDC (hwnd
, hdc
);
1595 TRACE("Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1597 else if (infoPtr
->bTracking
) {
1598 if (dwStyle
& HDS_FULLDRAG
) {
1599 if (HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1601 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1604 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1605 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1607 HEADER_SetItemBounds (hwnd
);
1611 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1612 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1613 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1614 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1615 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1616 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1617 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1618 ReleaseDC (hwnd
, hdc
);
1619 HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1622 TRACE("Tracking item %d!\n", infoPtr
->iMoveItem
);
1626 if ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
)) {
1627 FIXME("hot track support!\n");
1635 HEADER_Paint (HWND hwnd
, WPARAM wParam
)
1640 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1641 HEADER_Refresh (hwnd
, hdc
);
1643 EndPaint (hwnd
, &ps
);
1649 HEADER_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1654 pt
.x
= LOWORD(lParam
);
1655 pt
.y
= HIWORD(lParam
);
1657 /* Send a Notify message */
1658 bRet
= HEADER_SendSimpleNotify (hwnd
, NM_RCLICK
);
1660 /* Change to screen coordinate for WM_CONTEXTMENU */
1661 ClientToScreen(hwnd
, &pt
);
1663 /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */
1664 SendMessageW( hwnd
, WM_CONTEXTMENU
, (WPARAM
) hwnd
, MAKELPARAM(pt
.x
, pt
.y
));
1671 HEADER_SetCursor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1673 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1678 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1681 ScreenToClient (hwnd
, &pt
);
1683 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1685 if (flags
== HHT_ONDIVIDER
)
1686 SetCursor (infoPtr
->hcurDivider
);
1687 else if (flags
== HHT_ONDIVOPEN
)
1688 SetCursor (infoPtr
->hcurDivopen
);
1690 SetCursor (infoPtr
->hcurArrow
);
1697 HEADER_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1699 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1701 HFONT hFont
, hOldFont
;
1704 infoPtr
->hFont
= (HFONT
)wParam
;
1706 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
1709 hOldFont
= SelectObject (hdc
, hFont
);
1710 GetTextMetricsW (hdc
, &tm
);
1711 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1712 SelectObject (hdc
, hOldFont
);
1715 infoPtr
->bRectsValid
= FALSE
;
1718 InvalidateRect(hwnd
, NULL
, FALSE
);
1725 static LRESULT WINAPI
1726 HEADER_WindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1728 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1729 if (!HEADER_GetInfoPtr (hwnd
) && (msg
!= WM_CREATE
))
1730 return DefWindowProcW (hwnd
, msg
, wParam
, lParam
);
1732 /* case HDM_CLEARFILTER: */
1734 case HDM_CREATEDRAGIMAGE
:
1735 return HEADER_CreateDragImage (hwnd
, wParam
);
1737 case HDM_DELETEITEM
:
1738 return HEADER_DeleteItem (hwnd
, wParam
);
1740 /* case HDM_EDITFILTER: */
1742 case HDM_GETBITMAPMARGIN
:
1743 return HEADER_GetBitmapMargin(hwnd
);
1745 case HDM_GETIMAGELIST
:
1746 return HEADER_GetImageList (hwnd
);
1749 return HEADER_GetItemA (hwnd
, wParam
, lParam
);
1752 return HEADER_GetItemW (hwnd
, wParam
, lParam
);
1754 case HDM_GETITEMCOUNT
:
1755 return HEADER_GetItemCount (hwnd
);
1757 case HDM_GETITEMRECT
:
1758 return HEADER_GetItemRect (hwnd
, wParam
, lParam
);
1760 case HDM_GETORDERARRAY
:
1761 return HEADER_GetOrderArray(hwnd
, wParam
, lParam
);
1763 case HDM_GETUNICODEFORMAT
:
1764 return HEADER_GetUnicodeFormat (hwnd
);
1767 return HEADER_HitTest (hwnd
, wParam
, lParam
);
1769 case HDM_INSERTITEMA
:
1770 return HEADER_InsertItemA (hwnd
, wParam
, lParam
);
1772 case HDM_INSERTITEMW
:
1773 return HEADER_InsertItemW (hwnd
, wParam
, lParam
);
1776 return HEADER_Layout (hwnd
, wParam
, lParam
);
1778 case HDM_ORDERTOINDEX
:
1779 return HEADER_OrderToIndex(hwnd
, wParam
);
1781 case HDM_SETBITMAPMARGIN
:
1782 return HEADER_SetBitmapMargin(hwnd
, wParam
);
1784 /* case HDM_SETFILTERCHANGETIMEOUT: */
1786 /* case HDM_SETHOTDIVIDER: */
1788 case HDM_SETIMAGELIST
:
1789 return HEADER_SetImageList (hwnd
, (HIMAGELIST
)lParam
);
1792 return HEADER_SetItemA (hwnd
, wParam
, lParam
);
1795 return HEADER_SetItemW (hwnd
, wParam
, lParam
);
1797 case HDM_SETORDERARRAY
:
1798 return HEADER_SetOrderArray(hwnd
, wParam
, lParam
);
1800 case HDM_SETUNICODEFORMAT
:
1801 return HEADER_SetUnicodeFormat (hwnd
, wParam
);
1804 return HEADER_Create (hwnd
, wParam
, lParam
);
1807 return HEADER_Destroy (hwnd
, wParam
, lParam
);
1813 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1816 return HEADER_GetFont (hwnd
);
1818 case WM_LBUTTONDBLCLK
:
1819 return HEADER_LButtonDblClk (hwnd
, wParam
, lParam
);
1821 case WM_LBUTTONDOWN
:
1822 return HEADER_LButtonDown (hwnd
, wParam
, lParam
);
1825 return HEADER_LButtonUp (hwnd
, wParam
, lParam
);
1828 return HEADER_MouseMove (hwnd
, wParam
, lParam
);
1830 case WM_NOTIFYFORMAT
:
1831 return HEADER_NotifyFormat (hwnd
, wParam
, lParam
);
1834 return HEADER_Size (hwnd
, wParam
);
1837 return HEADER_Paint (hwnd
, wParam
);
1840 return HEADER_RButtonUp (hwnd
, wParam
, lParam
);
1843 return HEADER_SetCursor (hwnd
, wParam
, lParam
);
1846 return HEADER_SetFont (hwnd
, wParam
, lParam
);
1849 if ((msg
>= WM_USER
) && (msg
< WM_APP
))
1850 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1851 msg
, wParam
, lParam
);
1852 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1858 HEADER_Register (void)
1862 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
1863 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1864 wndClass
.lpfnWndProc
= HEADER_WindowProc
;
1865 wndClass
.cbClsExtra
= 0;
1866 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1867 wndClass
.hCursor
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1868 wndClass
.lpszClassName
= WC_HEADERW
;
1870 RegisterClassW (&wndClass
);
1875 HEADER_Unregister (void)
1877 UnregisterClassW (WC_HEADERW
, NULL
);