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"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(header
);
60 INT iOrder
; /* see documentation of HD_ITEM */
62 BOOL bDown
; /* is item pressed? (used for drawing) */
63 RECT rect
; /* bounding rectangle of the item */
69 HWND hwndNotify
; /* Owner window to send notifications to */
70 INT nNotifyFormat
; /* format used for WM_NOTIFY messages */
71 UINT uNumItem
; /* number of items (columns) */
72 INT nHeight
; /* height of the header (pixels) */
73 HFONT hFont
; /* handle to the current font */
74 HCURSOR hcurArrow
; /* handle to the arrow cursor */
75 HCURSOR hcurDivider
; /* handle to a cursor (used over dividers) <-|-> */
76 HCURSOR hcurDivopen
; /* handle to a cursor (used over dividers) <-||-> */
77 BOOL bCaptured
; /* Is the mouse captured? */
78 BOOL bPressed
; /* Is a header item pressed (down)? */
79 BOOL bTracking
; /* Is in tracking mode? */
80 BOOL bUnicode
; /* Unicode flag */
81 INT iMoveItem
; /* index of tracked item. (Tracking mode) */
82 INT xTrackOffset
; /* distance between the right side of the tracked item and the cursor */
83 INT xOldTrack
; /* track offset (see above) after the last WM_MOUSEMOVE */
84 INT nOldWidth
; /* width of a sizing item after the last WM_MOUSEMOVE */
85 INT iHotItem
; /* index of hot item (cursor is over this item) */
86 INT iMargin
; /* width of the margin that surrounds a bitmap */
88 HIMAGELIST himl
; /* handle to an image list (may be 0) */
89 HEADER_ITEM
*items
; /* pointer to array of HEADER_ITEM's */
90 INT
*order
; /* array of item IDs indexed by order */
91 BOOL bRectsValid
; /* validity flag for bounding rectangles */
96 #define DIVIDER_WIDTH 10
98 #define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongPtrW(hwnd,0))
100 static const WCHAR themeClass
[] = {'H','e','a','d','e','r',0};
103 inline static LRESULT
104 HEADER_IndexToOrder (HWND hwnd
, INT iItem
)
106 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
107 HEADER_ITEM
*lpItem
= &infoPtr
->items
[iItem
];
108 return lpItem
->iOrder
;
113 HEADER_OrderToIndex(HWND hwnd
, WPARAM wParam
)
115 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
116 INT iorder
= (INT
)wParam
;
118 if ((iorder
<0) || iorder
>= infoPtr
->uNumItem
)
120 return infoPtr
->order
[iorder
];
124 HEADER_SetItemBounds (HWND hwnd
)
126 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
132 infoPtr
->bRectsValid
= TRUE
;
134 if (infoPtr
->uNumItem
== 0)
137 GetClientRect (hwnd
, &rect
);
140 for (i
= 0; i
< infoPtr
->uNumItem
; i
++) {
141 phdi
= &infoPtr
->items
[HEADER_OrderToIndex(hwnd
,i
)];
142 phdi
->rect
.top
= rect
.top
;
143 phdi
->rect
.bottom
= rect
.bottom
;
145 phdi
->rect
.right
= phdi
->rect
.left
+ ((phdi
->cxy
>0)?phdi
->cxy
:0);
146 x
= phdi
->rect
.right
;
151 HEADER_Size (HWND hwnd
, WPARAM wParam
)
153 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
155 infoPtr
->bRectsValid
= FALSE
;
162 HEADER_DrawItem (HWND hwnd
, HDC hdc
, INT iItem
, BOOL bHotTrack
)
164 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
165 HEADER_ITEM
*phdi
= &infoPtr
->items
[iItem
];
167 INT oldBkMode
, cxEdge
= GetSystemMetrics(SM_CXEDGE
);
168 HTHEME theme
= GetWindowTheme (hwnd
);
171 TRACE("DrawItem(iItem %d bHotTrack %d unicode flag %d)\n", iItem
, bHotTrack
, infoPtr
->bUnicode
);
173 if (!infoPtr
->bRectsValid
)
174 HEADER_SetItemBounds(hwnd
);
177 if (r
.right
- r
.left
== 0)
178 return phdi
->rect
.right
;
181 int state
= (phdi
->bDown
) ? HIS_PRESSED
:
182 (bHotTrack
? HIS_HOT
: HIS_NORMAL
);
183 DrawThemeBackground (theme
, hdc
, HP_HEADERITEM
, state
,
185 GetThemeBackgroundContentRect (theme
, hdc
, HP_HEADERITEM
, state
,
189 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) {
191 DrawEdge (hdc
, &r
, BDR_RAISEDOUTER
,
192 BF_RECT
| BF_FLAT
| BF_MIDDLE
| BF_ADJUST
);
195 DrawEdge (hdc
, &r
, EDGE_RAISED
,
196 BF_RECT
| BF_SOFT
| BF_MIDDLE
| BF_ADJUST
);
199 DrawEdge (hdc
, &r
, EDGE_ETCHED
, BF_BOTTOM
| BF_RIGHT
| BF_ADJUST
);
209 /* Set the colors before sending NM_CUSTOMDRAW so that it can change them */
210 SetTextColor (hdc
, (bHotTrack
&& !theme
) ? COLOR_HIGHLIGHT
: COLOR_BTNTEXT
);
211 SetBkColor(hdc
, GetSysColor(COLOR_3DFACE
));
213 nmcd
.hdr
.hwndFrom
= hwnd
;
214 nmcd
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
215 nmcd
.hdr
.code
= NM_CUSTOMDRAW
;
216 nmcd
.dwDrawStage
= CDDS_PREPAINT
| CDDS_ITEM
| CDDS_ITEMPOSTERASE
;
218 nmcd
.dwItemSpec
= iItem
;
220 nmcd
.uItemState
= phdi
->bDown
? CDIS_SELECTED
: 0;
221 nmcd
.lItemlParam
= phdi
->lParam
;
223 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
, nmcd
.hdr
.idFrom
, (LPARAM
)&nmcd
);
225 if (phdi
->fmt
& HDF_OWNERDRAW
) {
228 dis
.CtlType
= ODT_HEADER
;
229 dis
.CtlID
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
231 dis
.itemAction
= ODA_DRAWENTIRE
;
232 dis
.itemState
= phdi
->bDown
? ODS_SELECTED
: 0;
236 dis
.itemData
= phdi
->lParam
;
237 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
238 SendMessageW (infoPtr
->hwndNotify
, WM_DRAWITEM
,
239 (WPARAM
)dis
.CtlID
, (LPARAM
)&dis
);
240 if (oldBkMode
!= TRANSPARENT
)
241 SetBkMode(hdc
, oldBkMode
);
244 UINT rw
, rh
, /* width and height of r */
245 *x
= NULL
, *w
= NULL
; /* x and width of the pic (bmp or img) which is part of cnt */
246 /* cnt,txt,img,bmp */
251 cw
= tw
= iw
= bw
= 0;
252 rw
= r
.right
- r
.left
;
253 rh
= r
.bottom
- r
.top
;
256 HBRUSH hbr
= CreateSolidBrush(GetBkColor(hdc
));
257 RECT rcBackground
= r
;
259 rcBackground
.right
-= cxEdge
;
260 FillRect(hdc
, &rcBackground
, hbr
);
263 if (phdi
->fmt
& HDF_STRING
) {
266 DrawTextW (hdc
, phdi
->pszText
, -1,
267 &textRect
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
|DT_CALCRECT
);
268 cw
= textRect
.right
- textRect
.left
+ 2 * infoPtr
->iMargin
;
271 if ((phdi
->fmt
& HDF_IMAGE
) && (infoPtr
->himl
)) {
272 iw
= infoPtr
->himl
->cx
+ 2 * infoPtr
->iMargin
;
277 if ((phdi
->fmt
& HDF_BITMAP
) && (phdi
->hbm
)) {
278 GetObjectW (phdi
->hbm
, sizeof(BITMAP
), (LPVOID
)&bmp
);
279 bw
= bmp
.bmWidth
+ 2 * infoPtr
->iMargin
;
289 /* align cx using the unclipped cw */
290 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_LEFT
)
292 else if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_CENTER
)
293 cx
= r
.left
+ rw
/ 2 - cw
/ 2;
300 if (cx
+ cw
> r
.right
)
303 tx
= cx
+ infoPtr
->iMargin
;
304 /* since cw might have changed we have to recalculate tw */
305 tw
= cw
- infoPtr
->iMargin
* 2;
309 if (phdi
->fmt
& HDF_BITMAP_ON_RIGHT
) {
310 /* put pic behind text */
311 *x
= cx
+ tw
+ infoPtr
->iMargin
* 3;
313 *x
= cx
+ infoPtr
->iMargin
;
314 /* move text behind pic */
320 /* since we're done with the layout we can
321 now calculate the position of bmp which
322 has no influence on alignment and layout
324 if ((phdi
->fmt
& HDF_JUSTIFYMASK
) == HDF_RIGHT
)
325 bx
= cx
- bw
+ infoPtr
->iMargin
;
327 bx
= cx
+ cw
+ infoPtr
->iMargin
;
331 HDC hClipDC
= GetDC(hwnd
);
332 HRGN hClipRgn
= CreateRectRgn(r
.left
, r
.top
, r
.right
, r
.bottom
);
333 SelectClipRgn(hClipDC
, hClipRgn
);
336 HDC hdcBitmap
= CreateCompatibleDC (hClipDC
);
337 SelectObject (hdcBitmap
, phdi
->hbm
);
338 BitBlt (hClipDC
, bx
, r
.top
+ ((INT
)rh
- bmp
.bmHeight
) / 2,
339 bmp
.bmWidth
, bmp
.bmHeight
, hdcBitmap
, 0, 0, SRCCOPY
);
340 DeleteDC (hdcBitmap
);
344 ImageList_DrawEx (infoPtr
->himl
, phdi
->iImage
, hClipDC
,
345 ix
, r
.top
+ ((INT
)rh
- infoPtr
->himl
->cy
) / 2,
346 infoPtr
->himl
->cx
, infoPtr
->himl
->cy
, CLR_DEFAULT
, CLR_DEFAULT
, 0);
349 DeleteObject(hClipRgn
);
350 ReleaseDC(hwnd
, hClipDC
);
353 if (((phdi
->fmt
& HDF_STRING
)
354 || (!(phdi
->fmt
& (HDF_OWNERDRAW
|HDF_STRING
|HDF_BITMAP
|
355 HDF_BITMAP_ON_RIGHT
|HDF_IMAGE
)))) /* no explicit format specified? */
356 && (phdi
->pszText
)) {
357 oldBkMode
= SetBkMode(hdc
, TRANSPARENT
);
360 DrawTextW (hdc
, phdi
->pszText
, -1,
361 &r
, DT_LEFT
|DT_END_ELLIPSIS
|DT_VCENTER
|DT_SINGLELINE
);
362 if (oldBkMode
!= TRANSPARENT
)
363 SetBkMode(hdc
, oldBkMode
);
367 return phdi
->rect
.right
;
372 HEADER_Refresh (HWND hwnd
, HDC hdc
)
374 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
375 HFONT hFont
, hOldFont
;
380 HTHEME theme
= GetWindowTheme (hwnd
);
382 /* get rect for the bar, adjusted for the border */
383 GetClientRect (hwnd
, &rect
);
385 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
386 hOldFont
= SelectObject (hdc
, hFont
);
388 /* draw Background */
390 hbrBk
= GetSysColorBrush(COLOR_3DFACE
);
391 FillRect(hdc
, &rect
, hbrBk
);
395 for (i
= 0; x
<= rect
.right
&& i
< infoPtr
->uNumItem
; i
++) {
396 x
= HEADER_DrawItem (hwnd
, hdc
, HEADER_OrderToIndex(hwnd
,i
),
397 infoPtr
->iHotItem
== i
);
400 if ((x
<= rect
.right
) && (infoPtr
->uNumItem
> 0)) {
403 DrawThemeBackground (theme
, hdc
, HP_HEADERITEM
, HIS_NORMAL
, &rect
,
407 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
)
408 DrawEdge (hdc
, &rect
, EDGE_RAISED
, BF_TOP
|BF_LEFT
|BF_BOTTOM
|BF_SOFT
);
410 DrawEdge (hdc
, &rect
, EDGE_ETCHED
, BF_BOTTOM
);
414 SelectObject (hdc
, hOldFont
);
419 HEADER_RefreshItem (HWND hwnd
, HDC hdc
, INT iItem
)
421 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
422 HFONT hFont
, hOldFont
;
424 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
425 hOldFont
= SelectObject (hdc
, hFont
);
426 HEADER_DrawItem (hwnd
, hdc
, iItem
, infoPtr
->iHotItem
== iItem
);
427 SelectObject (hdc
, hOldFont
);
432 HEADER_InternalHitTest (HWND hwnd
, LPPOINT lpPt
, UINT
*pFlags
, INT
*pItem
)
434 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
440 GetClientRect (hwnd
, &rect
);
444 if (PtInRect (&rect
, *lpPt
))
446 if (infoPtr
->uNumItem
== 0) {
447 *pFlags
|= HHT_NOWHERE
;
453 /* somewhere inside */
454 for (iCount
= 0; iCount
< infoPtr
->uNumItem
; iCount
++) {
455 rect
= infoPtr
->items
[iCount
].rect
;
456 width
= rect
.right
- rect
.left
;
461 if (PtInRect (&rect
, *lpPt
)) {
462 if (width
<= 2 * DIVIDER_WIDTH
) {
463 *pFlags
|= HHT_ONHEADER
;
465 TRACE("ON HEADER %d\n", iCount
);
470 rcTest
.right
= rcTest
.left
+ DIVIDER_WIDTH
;
471 if (PtInRect (&rcTest
, *lpPt
)) {
473 *pFlags
|= HHT_ONDIVOPEN
;
475 TRACE("ON DIVOPEN %d\n", *pItem
);
479 *pFlags
|= HHT_ONDIVIDER
;
481 TRACE("ON DIVIDER %d\n", *pItem
);
487 rcTest
.left
= rcTest
.right
- DIVIDER_WIDTH
;
488 if (PtInRect (&rcTest
, *lpPt
)) {
489 *pFlags
|= HHT_ONDIVIDER
;
491 TRACE("ON DIVIDER %d\n", *pItem
);
495 *pFlags
|= HHT_ONHEADER
;
497 TRACE("ON HEADER %d\n", iCount
);
502 /* check for last divider part (on nowhere) */
503 rect
= infoPtr
->items
[infoPtr
->uNumItem
-1].rect
;
504 rect
.left
= rect
.right
;
505 rect
.right
+= DIVIDER_WIDTH
;
506 if (PtInRect (&rect
, *lpPt
)) {
508 *pFlags
|= HHT_ONDIVOPEN
;
509 *pItem
= infoPtr
->uNumItem
- 1;
510 TRACE("ON DIVOPEN %d\n", *pItem
);
514 *pFlags
|= HHT_ONDIVIDER
;
515 *pItem
= infoPtr
->uNumItem
-1;
516 TRACE("ON DIVIDER %d\n", *pItem
);
521 *pFlags
|= HHT_NOWHERE
;
528 if (lpPt
->x
< rect
.left
) {
530 *pFlags
|= HHT_TOLEFT
;
532 else if (lpPt
->x
> rect
.right
) {
534 *pFlags
|= HHT_TORIGHT
;
537 if (lpPt
->y
< rect
.top
) {
539 *pFlags
|= HHT_ABOVE
;
541 else if (lpPt
->y
> rect
.bottom
) {
543 *pFlags
|= HHT_BELOW
;
548 TRACE("flags=0x%X\n", *pFlags
);
554 HEADER_DrawTrackLine (HWND hwnd
, HDC hdc
, INT x
)
560 GetClientRect (hwnd
, &rect
);
562 hOldPen
= SelectObject (hdc
, GetStockObject (BLACK_PEN
));
563 oldRop
= SetROP2 (hdc
, R2_XORPEN
);
564 MoveToEx (hdc
, x
, rect
.top
, NULL
);
565 LineTo (hdc
, x
, rect
.bottom
);
566 SetROP2 (hdc
, oldRop
);
567 SelectObject (hdc
, hOldPen
);
572 HEADER_SendSimpleNotify (HWND hwnd
, UINT code
)
574 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
577 nmhdr
.hwndFrom
= hwnd
;
578 nmhdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
581 return (BOOL
)SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
582 (WPARAM
)nmhdr
.idFrom
, (LPARAM
)&nmhdr
);
586 HEADER_SendHeaderNotify (HWND hwnd
, UINT code
, INT iItem
, INT mask
)
588 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
592 nmhdr
.hdr
.hwndFrom
= hwnd
;
593 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
594 nmhdr
.hdr
.code
= code
;
597 nmhdr
.pitem
= &nmitem
;
599 nmitem
.cxy
= infoPtr
->items
[iItem
].cxy
;
600 nmitem
.hbm
= infoPtr
->items
[iItem
].hbm
;
601 nmitem
.pszText
= NULL
;
602 nmitem
.cchTextMax
= 0;
603 /* nmitem.pszText = infoPtr->items[iItem].pszText; */
604 /* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
605 nmitem
.fmt
= infoPtr
->items
[iItem
].fmt
;
606 nmitem
.lParam
= infoPtr
->items
[iItem
].lParam
;
607 nmitem
.iOrder
= infoPtr
->items
[iItem
].iOrder
;
608 nmitem
.iImage
= infoPtr
->items
[iItem
].iImage
;
610 return (BOOL
)SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFY
,
611 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
615 * Send Disp Info notification.
616 * depends on NMHDDISPINFOW having same structure as NMHDDISPINFOA
617 * (so we handle the two cases only doing a specific cast for pszText).
619 * @param hwnd : hwnd header container handler
620 * @param mask : notification mask (usually HDI_TEXT or HDI_IMAGE)
621 * @param pDispInfo : NMHDDISPINFO structure (can be unicode or ansi)
622 * @param isW : TRUE if dispinfo is Unicode
625 HEADER_SendHeaderDispInfoNotify(HWND hwnd
, INT iItem
, INT mask
, LPHDITEMW phdi
, HEADER_ITEM
* lpItem
, BOOL isW
)
627 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
629 BOOL convertToAnsi
= FALSE
;
630 BOOL convertToUnicode
= FALSE
;
631 BOOL isUnicodeNotify
= FALSE
;
632 NMHDDISPINFOW dispInfo
;
636 convertToAnsi
= (isW
&& infoPtr
->nNotifyFormat
== NFR_ANSI
);
637 convertToUnicode
= (!isW
&& infoPtr
->nNotifyFormat
== NFR_UNICODE
);
639 isUnicodeNotify
= (isW
&& !convertToAnsi
);
641 memset(&dispInfo
, 0, sizeof(NMHDDISPINFOW
));
642 dispInfo
.hdr
.hwndFrom
= hwnd
;
643 dispInfo
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
644 if (isUnicodeNotify
|| convertToUnicode
)
646 dispInfo
.hdr
.code
= HDN_GETDISPINFOW
;
650 dispInfo
.hdr
.code
= HDN_GETDISPINFOA
;
652 dispInfo
.iItem
= iItem
;
653 dispInfo
.mask
= mask
;
655 dispInfo.pszText = Alloc(sizeof(WCHAR) * 260);
656 dispInfo.cchTextMax = 260;
658 ret
= (BOOL
) SendMessageW(infoPtr
->hwndNotify
, WM_NOTIFY
,
659 (WPARAM
) dispInfo
.hdr
.idFrom
,
662 TRACE("SendMessage returns(mask:0x%x,str:%s,lParam:%p)\n",
664 (isUnicodeNotify
? debugstr_w(dispInfo
.pszText
) : (LPSTR
) dispInfo
.pszText
),
665 (void*) dispInfo
.lParam
);
667 if (dispInfo
.mask
& HDI_DI_SETITEM
)
669 if (dispInfo
.mask
& HDI_IMAGE
)
671 lpItem
->iImage
= dispInfo
.iImage
;
673 if (dispInfo
.mask
& HDI_TEXT
)
675 if (isUnicodeNotify
|| convertToUnicode
)
676 Str_SetPtrW(&lpItem
->pszText
, (LPCWSTR
)dispInfo
.pszText
);
677 else /*if (convertToAnsi || !isW)*/
678 Str_SetPtrAtoW(&lpItem
->pszText
, (LPCSTR
)dispInfo
.pszText
);
681 FIXME("NMHDDISPINFO returns with flags HDI_DI_SETITEM\n");
686 if ((phdi
->mask
& mask
) & HDI_IMAGE
)
688 phdi
->iImage
= dispInfo
.iImage
;
690 if ((phdi
->mask
& mask
) & HDI_TEXT
)
693 Str_GetPtrW ((LPCWSTR
)dispInfo
.pszText
, phdi
->pszText
, phdi
->cchTextMax
);
694 else if (convertToUnicode
)
695 Str_GetPtrWtoA ((LPCWSTR
)dispInfo
.pszText
, (LPSTR
)phdi
->pszText
, phdi
->cchTextMax
);
697 Str_GetPtrA ((LPCSTR
)dispInfo
.pszText
, (LPSTR
)phdi
->pszText
, phdi
->cchTextMax
);
705 HEADER_SendClickNotify (HWND hwnd
, UINT code
, INT iItem
)
707 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
710 nmhdr
.hdr
.hwndFrom
= hwnd
;
711 nmhdr
.hdr
.idFrom
= GetWindowLongPtrW (hwnd
, GWLP_ID
);
712 nmhdr
.hdr
.code
= code
;
717 return (BOOL
)SendMessageA (infoPtr
->hwndNotify
, WM_NOTIFY
,
718 (WPARAM
)nmhdr
.hdr
.idFrom
, (LPARAM
)&nmhdr
);
723 HEADER_CreateDragImage (HWND hwnd
, WPARAM wParam
)
725 FIXME("empty stub!\n");
731 HEADER_DeleteItem (HWND hwnd
, WPARAM wParam
)
733 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
734 INT iItem
= (INT
)wParam
;
736 TRACE("[iItem=%d]\n", iItem
);
738 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
741 if (infoPtr
->uNumItem
== 1) {
742 TRACE("Simple delete!\n");
743 if (infoPtr
->items
[0].pszText
)
744 Free (infoPtr
->items
[0].pszText
);
745 Free (infoPtr
->items
);
746 Free(infoPtr
->order
);
749 infoPtr
->uNumItem
= 0;
752 HEADER_ITEM
*oldItems
= infoPtr
->items
;
755 TRACE("Complex delete! [iItem=%d]\n", iItem
);
757 for (i
= 0; i
< infoPtr
->uNumItem
; i
++)
758 TRACE("%d: order=%d, iOrder=%d, ->iOrder=%d\n", i
, infoPtr
->order
[i
], infoPtr
->items
[i
].iOrder
, infoPtr
->items
[infoPtr
->order
[i
]].iOrder
);
759 if (infoPtr
->items
[iItem
].pszText
)
760 Free (infoPtr
->items
[iItem
].pszText
);
761 iOrder
= infoPtr
->items
[iItem
].iOrder
;
764 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
765 /* pre delete copy */
767 memcpy (&infoPtr
->items
[0], &oldItems
[0],
768 iItem
* sizeof(HEADER_ITEM
));
771 /* post delete copy */
772 if (iItem
< infoPtr
->uNumItem
) {
773 memcpy (&infoPtr
->items
[iItem
], &oldItems
[iItem
+1],
774 (infoPtr
->uNumItem
- iItem
) * sizeof(HEADER_ITEM
));
777 /* Correct the orders */
778 if (iOrder
< infoPtr
->uNumItem
)
780 memmove(&infoPtr
->order
[iOrder
], &infoPtr
->order
[iOrder
+ 1],
781 (infoPtr
->uNumItem
- iOrder
) * sizeof(INT
));
782 for (i
= 0; i
< infoPtr
->uNumItem
; i
++)
784 if (infoPtr
->order
[i
] > iItem
)
787 infoPtr
->items
[infoPtr
->order
[i
]].iOrder
= infoPtr
->order
[i
];
791 for (i
= 0; i
< infoPtr
->uNumItem
; i
++)
792 TRACE("%d: order=%d, iOrder=%d, ->iOrder=%d\n", i
, infoPtr
->order
[i
], infoPtr
->items
[i
].iOrder
, infoPtr
->items
[infoPtr
->order
[i
]].iOrder
);
796 HEADER_SetItemBounds (hwnd
);
798 InvalidateRect(hwnd
, NULL
, FALSE
);
805 HEADER_GetImageList (HWND hwnd
)
807 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
809 return (LRESULT
)infoPtr
->himl
;
814 HEADER_GetItemT (HWND hwnd
, INT nItem
, LPHDITEMW phdi
, BOOL bUnicode
)
816 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
822 TRACE("[nItem=%d]\n", nItem
);
826 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
829 lpItem
= &infoPtr
->items
[nItem
];
831 if (phdi
->mask
& HDI_BITMAP
)
832 phdi
->hbm
= (lpItem
!= NULL
) ? lpItem
->hbm
: 0;
834 if (phdi
->mask
& HDI_FORMAT
)
835 phdi
->fmt
= (lpItem
!= NULL
) ? lpItem
->fmt
: 0;
837 if (phdi
->mask
& HDI_WIDTH
)
838 phdi
->cxy
= (lpItem
!= NULL
) ? lpItem
->cxy
: 0;
840 if (phdi
->mask
& HDI_LPARAM
)
841 phdi
->lParam
= (lpItem
!= NULL
) ? lpItem
->lParam
: 0;
843 if (phdi
->mask
& HDI_IMAGE
)
845 phdi
->iImage
= (lpItem
!= NULL
) ? lpItem
->iImage
: 0;
846 if (lpItem
->iImage
== I_IMAGECALLBACK
)
848 HEADER_SendHeaderDispInfoNotify(hwnd
, nItem
, HDI_IMAGE
, phdi
, lpItem
, bUnicode
);
852 if (phdi
->mask
& HDI_ORDER
)
853 phdi
->iOrder
= (lpItem
!= NULL
) ? lpItem
->iOrder
: 0;
855 if (phdi
->mask
& HDI_TEXT
)
857 if (lpItem
== NULL
) *phdi
->pszText
= 0; /* null pointer check */
858 else if (lpItem
->pszText
== LPSTR_TEXTCALLBACKW
) /* covers == TEXTCALLBACKA too */
860 HEADER_SendHeaderDispInfoNotify(hwnd
, nItem
, HDI_TEXT
, phdi
, lpItem
, bUnicode
);
865 Str_GetPtrW (lpItem
->pszText
, phdi
->pszText
, phdi
->cchTextMax
);
867 Str_GetPtrWtoA (lpItem
->pszText
, (LPSTR
)phdi
->pszText
, phdi
->cchTextMax
);
875 inline static LRESULT
876 HEADER_GetItemCount (HWND hwnd
)
878 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
879 return infoPtr
->uNumItem
;
884 HEADER_GetItemRect (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
886 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
887 INT iItem
= (INT
)wParam
;
888 LPRECT lpRect
= (LPRECT
)lParam
;
890 if ((iItem
< 0) || (iItem
>= (INT
)infoPtr
->uNumItem
))
893 lpRect
->left
= infoPtr
->items
[iItem
].rect
.left
;
894 lpRect
->right
= infoPtr
->items
[iItem
].rect
.right
;
895 lpRect
->top
= infoPtr
->items
[iItem
].rect
.top
;
896 lpRect
->bottom
= infoPtr
->items
[iItem
].rect
.bottom
;
903 HEADER_GetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
905 LPINT order
= (LPINT
) lParam
;
906 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
908 if ((unsigned int)wParam
<infoPtr
->uNumItem
)
911 memcpy(order
, infoPtr
->order
, infoPtr
->uNumItem
* sizeof(INT
));
916 HEADER_SetOrderArray(HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
919 LPINT order
= (LPINT
) lParam
;
920 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
923 if ((unsigned int)wParam
<infoPtr
->uNumItem
)
925 memcpy(infoPtr
->order
, order
, infoPtr
->uNumItem
* sizeof(INT
));
926 for (i
=0; i
<(int)wParam
; i
++)
928 lpItem
= &infoPtr
->items
[*order
++];
931 infoPtr
->bRectsValid
=0;
932 InvalidateRect(hwnd
, NULL
, FALSE
);
936 inline static LRESULT
937 HEADER_GetUnicodeFormat (HWND hwnd
)
939 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
940 return infoPtr
->bUnicode
;
945 HEADER_HitTest (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
947 LPHDHITTESTINFO phti
= (LPHDHITTESTINFO
)lParam
;
949 HEADER_InternalHitTest (hwnd
, &phti
->pt
, &phti
->flags
, &phti
->iItem
);
951 if (phti
->flags
== HHT_NOWHERE
)
959 HEADER_InsertItemT (HWND hwnd
, INT nItem
, LPHDITEMW phdi
, BOOL bUnicode
)
961 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
966 if ((phdi
== NULL
) || (nItem
< 0))
969 if (nItem
> infoPtr
->uNumItem
)
970 nItem
= infoPtr
->uNumItem
;
972 iOrder
= (phdi
->mask
& HDI_ORDER
) ? phdi
->iOrder
: nItem
;
975 else if (infoPtr
->uNumItem
< iOrder
)
976 iOrder
= infoPtr
->uNumItem
;
978 if (infoPtr
->uNumItem
== 0) {
979 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
));
980 infoPtr
->order
= Alloc(sizeof(INT
));
984 HEADER_ITEM
*oldItems
= infoPtr
->items
;
985 INT
*oldOrder
= infoPtr
->order
;
988 infoPtr
->items
= Alloc (sizeof (HEADER_ITEM
) * infoPtr
->uNumItem
);
990 memcpy (&infoPtr
->items
[1], &oldItems
[0],
991 (infoPtr
->uNumItem
-1) * sizeof(HEADER_ITEM
));
995 /* pre insert copy */
997 memcpy (&infoPtr
->items
[0], &oldItems
[0],
998 nItem
* sizeof(HEADER_ITEM
));
1001 /* post insert copy */
1002 if (nItem
< infoPtr
->uNumItem
- 1) {
1003 memcpy (&infoPtr
->items
[nItem
+1], &oldItems
[nItem
],
1004 (infoPtr
->uNumItem
- nItem
- 1) * sizeof(HEADER_ITEM
));
1008 infoPtr
->order
= Alloc(sizeof(INT
) * infoPtr
->uNumItem
);
1009 memcpy(infoPtr
->order
, oldOrder
, iOrder
* sizeof(INT
));
1010 infoPtr
->order
[iOrder
] = nItem
;
1011 memcpy(&infoPtr
->order
[iOrder
+ 1], &oldOrder
[iOrder
],
1012 (infoPtr
->uNumItem
- iOrder
- 1) * sizeof(INT
));
1018 for (i
= 0; i
< infoPtr
->uNumItem
; i
++)
1020 if (i
!= iOrder
&& infoPtr
->order
[i
] >= nItem
)
1021 infoPtr
->order
[i
]++;
1022 infoPtr
->items
[infoPtr
->order
[i
]].iOrder
= infoPtr
->order
[i
];
1025 lpItem
= &infoPtr
->items
[nItem
];
1026 lpItem
->bDown
= FALSE
;
1028 if (phdi
->mask
& HDI_WIDTH
)
1029 lpItem
->cxy
= phdi
->cxy
;
1031 if (phdi
->mask
& HDI_FORMAT
)
1032 lpItem
->fmt
= phdi
->fmt
;
1034 if (lpItem
->fmt
== 0)
1035 lpItem
->fmt
= HDF_LEFT
;
1037 if (phdi
->mask
& HDI_BITMAP
)
1038 lpItem
->hbm
= phdi
->hbm
;
1040 if (phdi
->mask
& HDI_LPARAM
)
1041 lpItem
->lParam
= phdi
->lParam
;
1043 if (phdi
->mask
& HDI_IMAGE
)
1045 if (phdi
->iImage
!= I_IMAGECALLBACK
)
1047 lpItem
->iImage
= phdi
->iImage
;
1051 lpItem
->iImage
= phdi
->iImage
;
1052 HEADER_SendHeaderDispInfoNotify(hwnd
, nItem
, HDI_IMAGE
, NULL
, lpItem
, bUnicode
);
1056 if (phdi
->mask
& HDI_TEXT
)
1058 if (!phdi
->pszText
) phdi
->pszText
= '\0'; /* null pointer check */
1059 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) /* covers != TEXTCALLBACKA too */
1062 Str_SetPtrW(&lpItem
->pszText
, phdi
->pszText
);
1064 Str_SetPtrAtoW(&lpItem
->pszText
, (LPSTR
)phdi
->pszText
);
1068 lpItem
->pszText
= phdi
->pszText
;
1069 HEADER_SendHeaderDispInfoNotify(hwnd
, nItem
, HDI_TEXT
, NULL
, lpItem
, bUnicode
);
1071 lpItem
->fmt
|= HDF_STRING
;
1074 lpItem
->iOrder
= iOrder
;
1076 HEADER_SetItemBounds (hwnd
);
1078 InvalidateRect(hwnd
, NULL
, FALSE
);
1085 HEADER_Layout (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1087 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1088 LPHDLAYOUT lpLayout
= (LPHDLAYOUT
)lParam
;
1090 lpLayout
->pwpos
->hwnd
= hwnd
;
1091 lpLayout
->pwpos
->hwndInsertAfter
= 0;
1092 lpLayout
->pwpos
->x
= lpLayout
->prc
->left
;
1093 lpLayout
->pwpos
->y
= lpLayout
->prc
->top
;
1094 lpLayout
->pwpos
->cx
= lpLayout
->prc
->right
- lpLayout
->prc
->left
;
1095 if (GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_HIDDEN
)
1096 lpLayout
->pwpos
->cy
= 0;
1098 lpLayout
->pwpos
->cy
= infoPtr
->nHeight
;
1099 lpLayout
->prc
->top
+= infoPtr
->nHeight
;
1101 lpLayout
->pwpos
->flags
= SWP_NOZORDER
;
1103 TRACE("Layout x=%d y=%d cx=%d cy=%d\n",
1104 lpLayout
->pwpos
->x
, lpLayout
->pwpos
->y
,
1105 lpLayout
->pwpos
->cx
, lpLayout
->pwpos
->cy
);
1107 infoPtr
->bRectsValid
= FALSE
;
1114 HEADER_SetImageList (HWND hwnd
, HIMAGELIST himl
)
1116 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1119 TRACE("(himl %p)\n", himl
);
1120 himlOld
= infoPtr
->himl
;
1121 infoPtr
->himl
= himl
;
1123 /* FIXME: Refresh needed??? */
1125 return (LRESULT
)himlOld
;
1130 HEADER_GetBitmapMargin(HWND hwnd
)
1132 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr(hwnd
);
1134 return infoPtr
->iMargin
;
1138 HEADER_SetBitmapMargin(HWND hwnd
, WPARAM wParam
)
1140 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1141 INT oldMargin
= infoPtr
->iMargin
;
1143 infoPtr
->iMargin
= (INT
)wParam
;
1149 HEADER_SetItemT (HWND hwnd
, INT nItem
, LPHDITEMW phdi
, BOOL bUnicode
)
1151 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1152 HEADER_ITEM
*lpItem
;
1156 if ((nItem
< 0) || (nItem
>= (INT
)infoPtr
->uNumItem
))
1159 TRACE("[nItem=%d]\n", nItem
);
1161 if (HEADER_SendHeaderNotify (hwnd
, bUnicode
? HDN_ITEMCHANGINGW
: HDN_ITEMCHANGINGA
,
1165 lpItem
= &infoPtr
->items
[nItem
];
1166 if (phdi
->mask
& HDI_BITMAP
)
1167 lpItem
->hbm
= phdi
->hbm
;
1169 if (phdi
->mask
& HDI_FORMAT
)
1170 lpItem
->fmt
= phdi
->fmt
;
1172 if (phdi
->mask
& HDI_LPARAM
)
1173 lpItem
->lParam
= phdi
->lParam
;
1175 if (phdi
->mask
& HDI_WIDTH
)
1176 lpItem
->cxy
= phdi
->cxy
;
1178 if (phdi
->mask
& HDI_IMAGE
)
1180 if (phdi
->iImage
!= I_IMAGECALLBACK
)
1182 lpItem
->iImage
= phdi
->iImage
;
1186 lpItem
->iImage
= phdi
->iImage
;
1187 HEADER_SendHeaderDispInfoNotify(hwnd
, nItem
, HDI_IMAGE
, NULL
, lpItem
, bUnicode
);
1191 if (phdi
->mask
& HDI_TEXT
)
1193 if (phdi
->pszText
!= LPSTR_TEXTCALLBACKW
) /* covers != TEXTCALLBACKA too */
1195 if (lpItem
->pszText
)
1197 Free(lpItem
->pszText
);
1198 lpItem
->pszText
= NULL
;
1203 Str_SetPtrW(&lpItem
->pszText
, phdi
->pszText
);
1205 Str_SetPtrAtoW(&lpItem
->pszText
, (LPSTR
)phdi
->pszText
);
1210 lpItem
->pszText
= phdi
->pszText
;
1211 HEADER_SendHeaderDispInfoNotify(hwnd
, nItem
, HDI_TEXT
, NULL
, lpItem
, bUnicode
);
1215 if (phdi
->mask
& HDI_ORDER
)
1219 if (lpItem
->iOrder
< phdi
->iOrder
)
1221 memmove(&infoPtr
->order
[lpItem
->iOrder
],
1222 &infoPtr
->order
[lpItem
->iOrder
+ 1],
1223 (phdi
->iOrder
- lpItem
->iOrder
) * sizeof(INT
));
1225 if (phdi
->iOrder
< lpItem
->iOrder
)
1227 memmove(&infoPtr
->order
[phdi
->iOrder
+ 1],
1228 &infoPtr
->order
[phdi
->iOrder
],
1229 (lpItem
->iOrder
- phdi
->iOrder
) * sizeof(INT
));
1231 infoPtr
->order
[phdi
->iOrder
] = nItem
;
1232 nMin
= min(lpItem
->iOrder
, phdi
->iOrder
);
1233 nMax
= max(lpItem
->iOrder
, phdi
->iOrder
);
1234 for (i
= nMin
; i
<= nMax
; i
++)
1236 infoPtr
->items
[infoPtr
->order
[i
]].iOrder
= infoPtr
->order
[i
];
1240 HEADER_SendHeaderNotify (hwnd
, bUnicode
? HDN_ITEMCHANGEDW
: HDN_ITEMCHANGEDA
,
1243 HEADER_SetItemBounds (hwnd
);
1245 InvalidateRect(hwnd
, NULL
, FALSE
);
1250 inline static LRESULT
1251 HEADER_SetUnicodeFormat (HWND hwnd
, WPARAM wParam
)
1253 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1254 BOOL bTemp
= infoPtr
->bUnicode
;
1256 infoPtr
->bUnicode
= (BOOL
)wParam
;
1263 HEADER_Create (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1265 HEADER_INFO
*infoPtr
;
1270 infoPtr
= (HEADER_INFO
*)Alloc (sizeof(HEADER_INFO
));
1271 SetWindowLongPtrW (hwnd
, 0, (DWORD_PTR
)infoPtr
);
1273 infoPtr
->hwndNotify
= ((LPCREATESTRUCTA
)lParam
)->hwndParent
;
1274 infoPtr
->uNumItem
= 0;
1278 infoPtr
->bRectsValid
= FALSE
;
1279 infoPtr
->hcurArrow
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1280 infoPtr
->hcurDivider
= LoadCursorW (COMCTL32_hModule
, MAKEINTRESOURCEW(IDC_DIVIDER
));
1281 infoPtr
->hcurDivopen
= LoadCursorW (COMCTL32_hModule
, MAKEINTRESOURCEW(IDC_DIVIDEROPEN
));
1282 infoPtr
->bPressed
= FALSE
;
1283 infoPtr
->bTracking
= FALSE
;
1284 infoPtr
->iMoveItem
= 0;
1286 infoPtr
->iHotItem
= -1;
1287 infoPtr
->bUnicode
= IsWindowUnicode (hwnd
);
1288 infoPtr
->iMargin
= 3*GetSystemMetrics(SM_CXEDGE
);
1289 infoPtr
->nNotifyFormat
=
1290 SendMessageW (infoPtr
->hwndNotify
, WM_NOTIFYFORMAT
, (WPARAM
)hwnd
, NF_QUERY
);
1293 hOldFont
= SelectObject (hdc
, GetStockObject (SYSTEM_FONT
));
1294 GetTextMetricsW (hdc
, &tm
);
1295 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1296 SelectObject (hdc
, hOldFont
);
1299 OpenThemeData(hwnd
, themeClass
);
1306 HEADER_Destroy (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1308 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1309 HEADER_ITEM
*lpItem
;
1313 if (infoPtr
->items
) {
1314 lpItem
= infoPtr
->items
;
1315 for (nItem
= 0; nItem
< infoPtr
->uNumItem
; nItem
++, lpItem
++) {
1316 if ((lpItem
->pszText
) && (lpItem
->pszText
!= LPSTR_TEXTCALLBACKW
))
1317 Free (lpItem
->pszText
);
1319 Free (infoPtr
->items
);
1323 Free(infoPtr
->order
);
1326 ImageList_Destroy (infoPtr
->himl
);
1328 SetWindowLongPtrW (hwnd
, 0, 0);
1331 theme
= GetWindowTheme(hwnd
);
1332 CloseThemeData(theme
);
1337 static inline LRESULT
1338 HEADER_GetFont (HWND hwnd
)
1340 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1342 return (LRESULT
)infoPtr
->hFont
;
1347 HEADER_LButtonDblClk (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1353 pt
.x
= (INT
)LOWORD(lParam
);
1354 pt
.y
= (INT
)HIWORD(lParam
);
1355 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1357 if ((GetWindowLongW (hwnd
, GWL_STYLE
) & HDS_BUTTONS
) && (flags
== HHT_ONHEADER
))
1358 HEADER_SendHeaderNotify (hwnd
, HDN_ITEMDBLCLICKA
, nItem
,0);
1359 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
))
1360 HEADER_SendHeaderNotify (hwnd
, HDN_DIVIDERDBLCLICKA
, nItem
,0);
1367 HEADER_LButtonDown (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1369 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1370 DWORD dwStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
1376 pt
.x
= (INT
)LOWORD(lParam
);
1377 pt
.y
= (INT
)HIWORD(lParam
);
1378 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1380 if ((dwStyle
& HDS_BUTTONS
) && (flags
== HHT_ONHEADER
)) {
1382 infoPtr
->bCaptured
= TRUE
;
1383 infoPtr
->bPressed
= TRUE
;
1384 infoPtr
->iMoveItem
= nItem
;
1386 infoPtr
->items
[nItem
].bDown
= TRUE
;
1388 /* Send WM_CUSTOMDRAW */
1390 HEADER_RefreshItem (hwnd
, hdc
, nItem
);
1391 ReleaseDC (hwnd
, hdc
);
1393 TRACE("Pressed item %d!\n", nItem
);
1395 else if ((flags
== HHT_ONDIVIDER
) || (flags
== HHT_ONDIVOPEN
)) {
1396 if (!(HEADER_SendHeaderNotify (hwnd
, HDN_BEGINTRACKA
, nItem
,0))) {
1398 infoPtr
->bCaptured
= TRUE
;
1399 infoPtr
->bTracking
= TRUE
;
1400 infoPtr
->iMoveItem
= nItem
;
1401 infoPtr
->nOldWidth
= infoPtr
->items
[nItem
].cxy
;
1402 infoPtr
->xTrackOffset
= infoPtr
->items
[nItem
].rect
.right
- pt
.x
;
1404 if (!(dwStyle
& HDS_FULLDRAG
)) {
1405 infoPtr
->xOldTrack
= infoPtr
->items
[nItem
].rect
.right
;
1407 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1408 ReleaseDC (hwnd
, hdc
);
1411 TRACE("Begin tracking item %d!\n", nItem
);
1420 HEADER_LButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1422 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1424 *DWORD dwStyle = GetWindowLongW (hwnd, GWL_STYLE);
1431 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1432 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1433 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1435 if (infoPtr
->bPressed
) {
1436 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
)) {
1437 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1439 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1440 ReleaseDC (hwnd
, hdc
);
1442 HEADER_SendClickNotify (hwnd
, HDN_ITEMCLICKA
, infoPtr
->iMoveItem
);
1444 else if (flags
== HHT_ONHEADER
)
1446 HEADER_ITEM
*lpItem
;
1447 INT newindex
= HEADER_IndexToOrder(hwnd
,nItem
);
1448 INT oldindex
= HEADER_IndexToOrder(hwnd
,infoPtr
->iMoveItem
);
1450 TRACE("Exchanging [index:order] [%d:%d] [%d:%d]\n",
1451 infoPtr
->iMoveItem
,oldindex
,nItem
,newindex
);
1452 lpItem
= &infoPtr
->items
[nItem
];
1453 lpItem
->iOrder
=oldindex
;
1455 lpItem
= &infoPtr
->items
[infoPtr
->iMoveItem
];
1456 lpItem
->iOrder
= newindex
;
1458 infoPtr
->order
[oldindex
] = nItem
;
1459 infoPtr
->order
[newindex
] = infoPtr
->iMoveItem
;
1461 infoPtr
->bRectsValid
= FALSE
;
1462 InvalidateRect(hwnd
, NULL
, FALSE
);
1463 /* FIXME: Should some WM_NOTIFY be sent */
1466 TRACE("Released item %d!\n", infoPtr
->iMoveItem
);
1467 infoPtr
->bPressed
= FALSE
;
1469 else if (infoPtr
->bTracking
) {
1470 TRACE("End tracking item %d!\n", infoPtr
->iMoveItem
);
1471 infoPtr
->bTracking
= FALSE
;
1473 HEADER_SendHeaderNotify (hwnd
, HDN_ENDTRACKA
, infoPtr
->iMoveItem
,HDI_WIDTH
);
1476 * we want to do this even for HDS_FULLDRAG because this is where
1477 * we send the HDN_ITEMCHANGING and HDN_ITEMCHANGED notifications
1479 * if (!(dwStyle & HDS_FULLDRAG)) {
1483 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1484 ReleaseDC (hwnd
, hdc
);
1485 if (HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGINGA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1487 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= infoPtr
->nOldWidth
;
1490 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1493 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1496 HEADER_SetItemBounds (hwnd
);
1497 InvalidateRect(hwnd
, NULL
, TRUE
);
1498 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1504 if (infoPtr
->bCaptured
) {
1505 infoPtr
->bCaptured
= FALSE
;
1507 HEADER_SendSimpleNotify (hwnd
, NM_RELEASEDCAPTURE
);
1515 HEADER_NotifyFormat (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1517 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1522 return infoPtr
->nNotifyFormat
;
1525 infoPtr
->nNotifyFormat
=
1526 SendMessageW ((HWND
)wParam
, WM_NOTIFYFORMAT
,
1527 (WPARAM
)hwnd
, (LPARAM
)NF_QUERY
);
1528 return infoPtr
->nNotifyFormat
;
1536 HEADER_MouseLeave (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1538 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1539 /* Reset hot-tracked item when mouse leaves control. */
1540 INT oldHotItem
= infoPtr
->iHotItem
;
1541 HDC hdc
= GetDC (hwnd
);
1543 infoPtr
->iHotItem
= -1;
1544 if (oldHotItem
!= -1) HEADER_RefreshItem (hwnd
, hdc
, oldHotItem
);
1545 ReleaseDC (hwnd
, hdc
);
1552 HEADER_MouseMove (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1554 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1555 DWORD dwStyle
= GetWindowLongW (hwnd
, GWL_STYLE
);
1560 /* With theming, hottracking is always enabled */
1561 BOOL hotTrackEnabled
=
1562 ((dwStyle
& HDS_BUTTONS
) && (dwStyle
& HDS_HOTTRACK
))
1563 || (GetWindowTheme (hwnd
) != NULL
);
1564 INT oldHotItem
= infoPtr
->iHotItem
;
1566 pt
.x
= (INT
)(SHORT
)LOWORD(lParam
);
1567 pt
.y
= (INT
)(SHORT
)HIWORD(lParam
);
1568 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1570 if (hotTrackEnabled
) {
1571 if (flags
& (HHT_ONHEADER
| HHT_ONDIVIDER
| HHT_ONDIVOPEN
))
1572 infoPtr
->iHotItem
= nItem
;
1574 infoPtr
->iHotItem
= -1;
1577 if (infoPtr
->bCaptured
) {
1578 if (infoPtr
->bPressed
) {
1579 BOOL oldState
= infoPtr
->items
[infoPtr
->iMoveItem
].bDown
;
1580 if ((nItem
== infoPtr
->iMoveItem
) && (flags
== HHT_ONHEADER
))
1581 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= TRUE
;
1583 infoPtr
->items
[infoPtr
->iMoveItem
].bDown
= FALSE
;
1584 if (oldState
!= infoPtr
->items
[infoPtr
->iMoveItem
].bDown
) {
1586 HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iMoveItem
);
1587 ReleaseDC (hwnd
, hdc
);
1590 TRACE("Moving pressed item %d!\n", infoPtr
->iMoveItem
);
1592 else if (infoPtr
->bTracking
) {
1593 if (dwStyle
& HDS_FULLDRAG
) {
1594 if (HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
))
1596 nWidth
= pt
.x
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
+ infoPtr
->xTrackOffset
;
1599 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
= nWidth
;
1600 HEADER_SendHeaderNotify(hwnd
, HDN_ITEMCHANGEDA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1602 HEADER_SetItemBounds (hwnd
);
1606 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1607 infoPtr
->xOldTrack
= pt
.x
+ infoPtr
->xTrackOffset
;
1608 if (infoPtr
->xOldTrack
< infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
)
1609 infoPtr
->xOldTrack
= infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1610 infoPtr
->items
[infoPtr
->iMoveItem
].cxy
=
1611 infoPtr
->xOldTrack
- infoPtr
->items
[infoPtr
->iMoveItem
].rect
.left
;
1612 HEADER_DrawTrackLine (hwnd
, hdc
, infoPtr
->xOldTrack
);
1613 ReleaseDC (hwnd
, hdc
);
1614 HEADER_SendHeaderNotify (hwnd
, HDN_TRACKA
, infoPtr
->iMoveItem
, HDI_WIDTH
);
1617 TRACE("Tracking item %d!\n", infoPtr
->iMoveItem
);
1621 if (hotTrackEnabled
) {
1622 TRACKMOUSEEVENT tme
;
1623 if (oldHotItem
!= infoPtr
->iHotItem
) {
1625 if (oldHotItem
!= -1) HEADER_RefreshItem (hwnd
, hdc
, oldHotItem
);
1626 if (infoPtr
->iHotItem
!= -1) HEADER_RefreshItem (hwnd
, hdc
, infoPtr
->iHotItem
);
1627 ReleaseDC (hwnd
, hdc
);
1629 tme
.cbSize
= sizeof( tme
);
1630 tme
.dwFlags
= TME_LEAVE
;
1631 tme
.hwndTrack
= hwnd
;
1632 TrackMouseEvent( &tme
);
1640 HEADER_Paint (HWND hwnd
, WPARAM wParam
)
1645 hdc
= wParam
==0 ? BeginPaint (hwnd
, &ps
) : (HDC
)wParam
;
1646 HEADER_Refresh (hwnd
, hdc
);
1648 EndPaint (hwnd
, &ps
);
1654 HEADER_RButtonUp (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1659 pt
.x
= LOWORD(lParam
);
1660 pt
.y
= HIWORD(lParam
);
1662 /* Send a Notify message */
1663 bRet
= HEADER_SendSimpleNotify (hwnd
, NM_RCLICK
);
1665 /* Change to screen coordinate for WM_CONTEXTMENU */
1666 ClientToScreen(hwnd
, &pt
);
1668 /* Send a WM_CONTEXTMENU message in response to the RBUTTONUP */
1669 SendMessageW( hwnd
, WM_CONTEXTMENU
, (WPARAM
) hwnd
, MAKELPARAM(pt
.x
, pt
.y
));
1676 HEADER_SetCursor (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1678 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1683 TRACE("code=0x%X id=0x%X\n", LOWORD(lParam
), HIWORD(lParam
));
1686 ScreenToClient (hwnd
, &pt
);
1688 HEADER_InternalHitTest (hwnd
, &pt
, &flags
, &nItem
);
1690 if (flags
== HHT_ONDIVIDER
)
1691 SetCursor (infoPtr
->hcurDivider
);
1692 else if (flags
== HHT_ONDIVOPEN
)
1693 SetCursor (infoPtr
->hcurDivopen
);
1695 SetCursor (infoPtr
->hcurArrow
);
1702 HEADER_SetFont (HWND hwnd
, WPARAM wParam
, LPARAM lParam
)
1704 HEADER_INFO
*infoPtr
= HEADER_GetInfoPtr (hwnd
);
1706 HFONT hFont
, hOldFont
;
1709 infoPtr
->hFont
= (HFONT
)wParam
;
1711 hFont
= infoPtr
->hFont
? infoPtr
->hFont
: GetStockObject (SYSTEM_FONT
);
1714 hOldFont
= SelectObject (hdc
, hFont
);
1715 GetTextMetricsW (hdc
, &tm
);
1716 infoPtr
->nHeight
= tm
.tmHeight
+ VERT_BORDER
;
1717 SelectObject (hdc
, hOldFont
);
1720 infoPtr
->bRectsValid
= FALSE
;
1723 InvalidateRect(hwnd
, NULL
, FALSE
);
1729 /* Update the theme handle after a theme change */
1730 static LRESULT
HEADER_ThemeChanged(HWND hwnd
)
1732 HTHEME theme
= GetWindowTheme(hwnd
);
1733 CloseThemeData(theme
);
1734 OpenThemeData(hwnd
, themeClass
);
1735 InvalidateRect(hwnd
, NULL
, FALSE
);
1740 static LRESULT WINAPI
1741 HEADER_WindowProc (HWND hwnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1743 TRACE("hwnd=%p msg=%x wparam=%x lParam=%lx\n", hwnd
, msg
, wParam
, lParam
);
1744 if (!HEADER_GetInfoPtr (hwnd
) && (msg
!= WM_CREATE
))
1745 return DefWindowProcW (hwnd
, msg
, wParam
, lParam
);
1747 /* case HDM_CLEARFILTER: */
1749 case HDM_CREATEDRAGIMAGE
:
1750 return HEADER_CreateDragImage (hwnd
, wParam
);
1752 case HDM_DELETEITEM
:
1753 return HEADER_DeleteItem (hwnd
, wParam
);
1755 /* case HDM_EDITFILTER: */
1757 case HDM_GETBITMAPMARGIN
:
1758 return HEADER_GetBitmapMargin(hwnd
);
1760 case HDM_GETIMAGELIST
:
1761 return HEADER_GetImageList (hwnd
);
1765 return HEADER_GetItemT (hwnd
, (INT
)wParam
, (LPHDITEMW
)lParam
, msg
== HDM_GETITEMW
);
1767 case HDM_GETITEMCOUNT
:
1768 return HEADER_GetItemCount (hwnd
);
1770 case HDM_GETITEMRECT
:
1771 return HEADER_GetItemRect (hwnd
, wParam
, lParam
);
1773 case HDM_GETORDERARRAY
:
1774 return HEADER_GetOrderArray(hwnd
, wParam
, lParam
);
1776 case HDM_GETUNICODEFORMAT
:
1777 return HEADER_GetUnicodeFormat (hwnd
);
1780 return HEADER_HitTest (hwnd
, wParam
, lParam
);
1782 case HDM_INSERTITEMA
:
1783 case HDM_INSERTITEMW
:
1784 return HEADER_InsertItemT (hwnd
, (INT
)wParam
, (LPHDITEMW
)lParam
, msg
== HDM_INSERTITEMW
);
1787 return HEADER_Layout (hwnd
, wParam
, lParam
);
1789 case HDM_ORDERTOINDEX
:
1790 return HEADER_OrderToIndex(hwnd
, wParam
);
1792 case HDM_SETBITMAPMARGIN
:
1793 return HEADER_SetBitmapMargin(hwnd
, wParam
);
1795 /* case HDM_SETFILTERCHANGETIMEOUT: */
1797 /* case HDM_SETHOTDIVIDER: */
1799 case HDM_SETIMAGELIST
:
1800 return HEADER_SetImageList (hwnd
, (HIMAGELIST
)lParam
);
1804 return HEADER_SetItemT (hwnd
, (INT
)wParam
, (LPHDITEMW
)lParam
, msg
== HDM_SETITEMW
);
1806 case HDM_SETORDERARRAY
:
1807 return HEADER_SetOrderArray(hwnd
, wParam
, lParam
);
1809 case HDM_SETUNICODEFORMAT
:
1810 return HEADER_SetUnicodeFormat (hwnd
, wParam
);
1813 return HEADER_Create (hwnd
, wParam
, lParam
);
1816 return HEADER_Destroy (hwnd
, wParam
, lParam
);
1822 return DLGC_WANTTAB
| DLGC_WANTARROWS
;
1825 return HEADER_GetFont (hwnd
);
1827 case WM_LBUTTONDBLCLK
:
1828 return HEADER_LButtonDblClk (hwnd
, wParam
, lParam
);
1830 case WM_LBUTTONDOWN
:
1831 return HEADER_LButtonDown (hwnd
, wParam
, lParam
);
1834 return HEADER_LButtonUp (hwnd
, wParam
, lParam
);
1837 return HEADER_MouseLeave (hwnd
, wParam
, lParam
);
1840 return HEADER_MouseMove (hwnd
, wParam
, lParam
);
1842 case WM_NOTIFYFORMAT
:
1843 return HEADER_NotifyFormat (hwnd
, wParam
, lParam
);
1846 return HEADER_Size (hwnd
, wParam
);
1848 case WM_THEMECHANGED
:
1849 return HEADER_ThemeChanged (hwnd
);
1851 case WM_PRINTCLIENT
:
1853 return HEADER_Paint (hwnd
, wParam
);
1856 return HEADER_RButtonUp (hwnd
, wParam
, lParam
);
1859 return HEADER_SetCursor (hwnd
, wParam
, lParam
);
1862 return HEADER_SetFont (hwnd
, wParam
, lParam
);
1865 if ((msg
>= WM_USER
) && (msg
< WM_APP
))
1866 ERR("unknown msg %04x wp=%04x lp=%08lx\n",
1867 msg
, wParam
, lParam
);
1868 return DefWindowProcA (hwnd
, msg
, wParam
, lParam
);
1874 HEADER_Register (void)
1878 ZeroMemory (&wndClass
, sizeof(WNDCLASSW
));
1879 wndClass
.style
= CS_GLOBALCLASS
| CS_DBLCLKS
;
1880 wndClass
.lpfnWndProc
= HEADER_WindowProc
;
1881 wndClass
.cbClsExtra
= 0;
1882 wndClass
.cbWndExtra
= sizeof(HEADER_INFO
*);
1883 wndClass
.hCursor
= LoadCursorW (0, (LPWSTR
)IDC_ARROW
);
1884 wndClass
.lpszClassName
= WC_HEADERW
;
1886 RegisterClassW (&wndClass
);
1891 HEADER_Unregister (void)
1893 UnregisterClassW (WC_HEADERW
, NULL
);