source: trunk/src/comctl32/header.c@ 1111

Last change on this file since 1111 was 1111, checked in by cbratschi, 26 years ago

several fixes

File size: 43.9 KB
Line 
1/* $Id: header.c,v 1.11 1999-10-02 13:58:21 cbratschi Exp $ */
2/*
3 * Header control
4 *
5 * Copyright 1998 Eric Kohl
6 * Copyright 1999 Achim Hasenmueller
7 * Copyright 1999 Christoph Bratschi
8 *
9 * TODO:
10 * - Imagelist support (partially).
11 * - Callback items (under construction).
12 * - Order list support.
13 * - Control specific cursors (over dividers).
14 * - Hottrack support (partially).
15 * - Custom draw support (including Notifications).
16 * - Drag and Drop support (including Notifications).
17 * - Unicode support.
18 *
19 * FIXME:
20 * - Little flaw when drawing a bitmap on the right side of the text.
21 *
22 * Status: Development in progress, a lot to do :)
23 * Version: 5.00 (target)
24 */
25
26#include <string.h>
27
28#include "winbase.h"
29#include "commctrl.h"
30#include "header.h"
31#include "comctl32.h"
32
33
34#define __HDM_LAYOUT_HACK__
35
36
37#define VERT_BORDER 4
38#define DIVIDER_WIDTH 10
39#define MIN_ITEMWIDTH 0
40#define ITEM_FRAMESIZE 2
41
42#define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO *)GetWindowLongA(hwnd,0))
43
44
45static INT
46HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack,BOOL bEraseTextBkgnd)
47{
48 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
49 HEADER_ITEM *phdi = &infoPtr->items[iItem];
50 RECT r;
51 INT oldBkMode;
52
53 r = phdi->rect;
54 if (r.right - r.left == 0) return phdi->rect.right;
55
56 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS)
57 {
58 if (phdi->bDown)
59 {
60 DrawEdge (hdc, &r, BDR_RAISEDOUTER,
61 BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST);
62 r.left += 2;
63 r.top += 2;
64 }
65 else
66 DrawEdge (hdc, &r, EDGE_RAISED,
67 BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
68 } else
69 DrawEdge (hdc, &r, EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST);
70
71 if (phdi->fmt & HDF_OWNERDRAW)
72 {
73 DRAWITEMSTRUCT dis;
74 dis.CtlType = ODT_HEADER;
75 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
76 dis.itemID = iItem;
77 dis.itemAction = ODA_DRAWENTIRE;
78 dis.itemState = phdi->bDown ? ODS_SELECTED : 0;
79 dis.hwndItem = hwnd;
80 dis.hDC = hdc;
81 dis.rcItem = r;
82 dis.itemData = phdi->lParam;
83 SendMessageA (GetParent (hwnd), WM_DRAWITEM,
84 (WPARAM)dis.CtlID, (LPARAM)&dis);
85 } else
86 {
87 UINT uTextJustify = DT_LEFT;
88
89 if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_CENTER)
90 uTextJustify = DT_CENTER;
91 else if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT)
92 uTextJustify = DT_RIGHT;
93
94 if ((phdi->fmt & HDF_BITMAP) && (phdi->hbm))
95 {
96 BITMAP bmp;
97 HDC hdcBitmap;
98 INT yD, yS, cx, cy, rx, ry;
99
100 GetObjectA (phdi->hbm, sizeof(BITMAP), (LPVOID)&bmp);
101
102 ry = r.bottom - r.top;
103 rx = r.right - r.left;
104
105 if (ry >= bmp.bmHeight)
106 {
107 cy = bmp.bmHeight;
108 yD = r.top + (ry - bmp.bmHeight) / 2;
109 yS = 0;
110 } else
111 {
112 cy = ry;
113 yD = r.top;
114 yS = (bmp.bmHeight - ry) / 2;
115
116 }
117
118 if (rx >= bmp.bmWidth + 6)
119 {
120 cx = bmp.bmWidth;
121 } else
122 {
123 cx = rx - 6;
124 }
125
126 hdcBitmap = CreateCompatibleDC (hdc);
127 SelectObject (hdcBitmap, phdi->hbm);
128 BitBlt (hdc, r.left + 3, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY);
129 DeleteDC (hdcBitmap);
130
131 r.left += (bmp.bmWidth + 3);
132 }
133
134
135 if ((phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm))
136 {
137 BITMAP bmp;
138 HDC hdcBitmap;
139 INT xD, yD, yS, cx, cy, rx, ry, tx;
140 RECT textRect;
141
142 GetObjectA (phdi->hbm, sizeof(BITMAP), (LPVOID)&bmp);
143
144 textRect = r;
145 if (bEraseTextBkgnd)
146 {
147 HBRUSH hbrBk = GetSysColorBrush(COLOR_3DFACE);
148
149 FillRect(hdc,&textRect,hbrBk);
150 }
151 DrawTextExW(hdc,phdi->pszText,lstrlenW(phdi->pszText),
152 &textRect,DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT|DT_END_ELLIPSIS,NULL);
153 tx = textRect.right - textRect.left;
154 ry = r.bottom - r.top;
155 rx = r.right - r.left;
156
157 if (ry >= bmp.bmHeight)
158 {
159 cy = bmp.bmHeight;
160 yD = r.top + (ry - bmp.bmHeight) / 2;
161 yS = 0;
162 } else
163 {
164 cy = ry;
165 yD = r.top;
166 yS = (bmp.bmHeight - ry) / 2;
167
168 }
169
170 if (r.left + tx + bmp.bmWidth + 9 <= r.right)
171 {
172 cx = bmp.bmWidth;
173 xD = r.left + tx + 6;
174 } else
175 {
176 if (rx >= bmp.bmWidth + 6)
177 {
178 cx = bmp.bmWidth;
179 xD = r.right - bmp.bmWidth - 3;
180 r.right = xD - 3;
181 } else
182 {
183 cx = rx - 3;
184 xD = r.left;
185 r.right = r.left;
186 }
187 }
188
189 hdcBitmap = CreateCompatibleDC (hdc);
190 SelectObject (hdcBitmap, phdi->hbm);
191 BitBlt (hdc, xD, yD, cx, cy, hdcBitmap, 0, yS, SRCCOPY);
192 DeleteDC (hdcBitmap);
193 }
194
195 if (phdi->fmt & HDF_IMAGE)
196 {
197
198
199/* ImageList_Draw (infoPtr->himl, phdi->iImage,...); */
200 }
201
202 if ((phdi->fmt & HDF_STRING) && (phdi->pszText))
203 {
204 oldBkMode = SetBkMode(hdc, TRANSPARENT);
205 r.left += 3;
206 r.right -= 3;
207 SetTextColor (hdc, bHotTrack ? COLOR_HIGHLIGHT : COLOR_BTNTEXT);
208 if (bEraseTextBkgnd)
209 {
210 HBRUSH hbrBk = GetSysColorBrush(COLOR_3DFACE);
211
212 FillRect(hdc,&r,hbrBk);
213 }
214 DrawTextExW(hdc,phdi->pszText,lstrlenW (phdi->pszText),
215 &r,uTextJustify|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS,NULL);
216 if (oldBkMode != TRANSPARENT)
217 SetBkMode(hdc, oldBkMode);
218 }
219 }
220
221 return phdi->rect.right;
222}
223
224
225static void
226HEADER_Draw(HWND hwnd,HDC hdc)
227{
228 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
229 HFONT hFont, hOldFont;
230 RECT rect;
231 HBRUSH hbrBk;
232 INT i, x;
233
234 /* get rect for the bar, adjusted for the border */
235 GetClientRect (hwnd, &rect);
236
237 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
238 hOldFont = SelectObject (hdc, hFont);
239
240 /* draw Background */
241 hbrBk = GetSysColorBrush(COLOR_3DFACE);
242 FillRect(hdc, &rect, hbrBk);
243
244 x = rect.left;
245 for (i = 0; i < infoPtr->uNumItem; i++)
246 {
247 x = HEADER_DrawItem(hwnd,hdc,i,FALSE,FALSE);
248 if (x > rect.right)
249 {
250 x = -1;
251 break;
252 }
253 }
254
255 if (x != -1 && (x <= rect.right) && (infoPtr->uNumItem > 0))
256 {
257 rect.left = x;
258 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS)
259 DrawEdge (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT);
260 else
261 DrawEdge (hdc, &rect, EDGE_ETCHED, BF_BOTTOM);
262 }
263
264 SelectObject (hdc, hOldFont);
265}
266
267
268static void
269HEADER_RefreshItem (HWND hwnd, HDC hdc, INT iItem)
270{
271 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
272 HFONT hFont, hOldFont;
273
274 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
275 hOldFont = SelectObject (hdc, hFont);
276 HEADER_DrawItem(hwnd,hdc,iItem,FALSE,TRUE);
277 SelectObject (hdc, hOldFont);
278}
279
280static void
281HEADER_Refresh(HWND hwnd)
282{
283 HDC hdc,hdcCompatible;
284 HBITMAP bitmap,oldbmp;
285 RECT rect;
286
287 GetClientRect(hwnd,&rect);
288 hdc = GetDC(hwnd);
289 hdcCompatible = CreateCompatibleDC(hdc);
290 bitmap = CreateCompatibleBitmap(hdc,rect.right,rect.bottom);
291 oldbmp = SelectObject(hdcCompatible,bitmap);
292 HEADER_Draw(hwnd,hdcCompatible);
293 BitBlt(hdc,0,0,rect.right,rect.bottom,hdcCompatible,0,0,SRCCOPY);
294 SelectObject(hdcCompatible,oldbmp);
295 DeleteObject(bitmap);
296 DeleteDC(hdcCompatible);
297 ReleaseDC(hwnd,hdc);
298}
299
300static void
301HEADER_SetItemBounds(HWND hwnd,INT start)
302{
303 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
304 HEADER_ITEM *phdi;
305 RECT rect;
306 int i, x;
307
308 if (infoPtr->uNumItem == 0) return;
309
310 GetClientRect(hwnd,&rect);
311
312 x = (start > 0) ? infoPtr->items[start-1].rect.right:rect.left;
313 for (i = start;i < infoPtr->uNumItem;i++)
314 {
315 phdi = &infoPtr->items[i];
316 phdi->rect.top = rect.top;
317 phdi->rect.bottom = rect.bottom;
318 phdi->rect.left = x;
319 phdi->rect.right = phdi->rect.left + phdi->cxy;
320 x = phdi->rect.right;
321 }
322}
323
324
325static void
326HEADER_ForceItemBounds (HWND hwnd, INT cy)
327{
328 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
329 HEADER_ITEM *phdi;
330 int i, x;
331
332 if (infoPtr->uNumItem == 0)
333 return;
334
335 x = 0;
336 for (i = 0; i < infoPtr->uNumItem; i++) {
337 phdi = &infoPtr->items[i];
338 phdi->rect.top = 0;
339 phdi->rect.bottom = cy;
340 phdi->rect.left = x;
341 phdi->rect.right = phdi->rect.left + phdi->cxy;
342 x = phdi->rect.right;
343 }
344}
345
346
347static void
348HEADER_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pItem)
349{
350 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
351 RECT rect, rcTest;
352 INT iCount, width;
353 BOOL bNoWidth;
354
355 GetClientRect (hwnd, &rect);
356
357 *pFlags = 0;
358 bNoWidth = FALSE;
359 if (PtInRect (&rect, *lpPt))
360 {
361 if (infoPtr->uNumItem == 0) {
362 *pFlags |= HHT_NOWHERE;
363 *pItem = 1;
364// TRACE (header, "NOWHERE\n");
365 return;
366 }
367 else {
368 /* somewhere inside */
369 for (iCount = 0; iCount < infoPtr->uNumItem; iCount++) {
370 rect = infoPtr->items[iCount].rect;
371 width = rect.right - rect.left;
372 if (width == 0) {
373 bNoWidth = TRUE;
374 continue;
375 }
376 if (PtInRect (&rect, *lpPt)) {
377 if (width <= 2 * DIVIDER_WIDTH) {
378 *pFlags |= HHT_ONHEADER;
379 *pItem = iCount;
380// TRACE (header, "ON HEADER %d\n", iCount);
381 return;
382 }
383 if (iCount > 0) {
384 rcTest = rect;
385 rcTest.right = rcTest.left + DIVIDER_WIDTH;
386 if (PtInRect (&rcTest, *lpPt)) {
387 if (bNoWidth) {
388 *pFlags |= HHT_ONDIVOPEN;
389 *pItem = iCount - 1;
390// TRACE (header, "ON DIVOPEN %d\n", *pItem);
391 return;
392 }
393 else {
394 *pFlags |= HHT_ONDIVIDER;
395 *pItem = iCount - 1;
396// TRACE (header, "ON DIVIDER %d\n", *pItem);
397 return;
398 }
399 }
400 }
401 rcTest = rect;
402 rcTest.left = rcTest.right - DIVIDER_WIDTH;
403 if (PtInRect (&rcTest, *lpPt)) {
404 *pFlags |= HHT_ONDIVIDER;
405 *pItem = iCount;
406// TRACE (header, "ON DIVIDER %d\n", *pItem);
407 return;
408 }
409
410 *pFlags |= HHT_ONHEADER;
411 *pItem = iCount;
412// TRACE (header, "ON HEADER %d\n", iCount);
413 return;
414 }
415 }
416
417 /* check for last divider part (on nowhere) */
418 rect = infoPtr->items[infoPtr->uNumItem-1].rect;
419 rect.left = rect.right;
420 rect.right += DIVIDER_WIDTH;
421 if (PtInRect (&rect, *lpPt)) {
422 if (bNoWidth) {
423 *pFlags |= HHT_ONDIVOPEN;
424 *pItem = infoPtr->uNumItem - 1;
425// TRACE (header, "ON DIVOPEN %d\n", *pItem);
426 return;
427 }
428 else {
429 *pFlags |= HHT_ONDIVIDER;
430 *pItem = infoPtr->uNumItem-1;
431// TRACE (header, "ON DIVIDER %d\n", *pItem);
432 return;
433 }
434 }
435
436 *pFlags |= HHT_NOWHERE;
437 *pItem = 1;
438// TRACE (header, "NOWHERE\n");
439 return;
440 }
441 }
442 else {
443 if (lpPt->x < rect.left) {
444// TRACE (header, "TO LEFT\n");
445 *pFlags |= HHT_TOLEFT;
446 }
447 else if (lpPt->x > rect.right) {
448// TRACE (header, "TO LEFT\n");
449 *pFlags |= HHT_TORIGHT;
450 }
451
452 if (lpPt->y < rect.top) {
453// TRACE (header, "ABOVE\n");
454 *pFlags |= HHT_ABOVE;
455 }
456 else if (lpPt->y > rect.bottom) {
457// TRACE (header, "BELOW\n");
458 *pFlags |= HHT_BELOW;
459 }
460 }
461
462 *pItem = 1;
463// TRACE (header, "flags=0x%X\n", *pFlags);
464 return;
465}
466
467
468static void
469HEADER_DrawTrackLine (HWND hwnd, HDC hdc, INT x)
470{
471 RECT rect;
472 HPEN hOldPen;
473 INT oldRop;
474
475 GetClientRect (hwnd, &rect); //CB: Odin bug!!!
476 hOldPen = SelectObject (hdc, GetStockObject (BLACK_PEN));
477 oldRop = SetROP2 (hdc, R2_XORPEN);
478 MoveToEx (hdc, x, rect.top, NULL);
479 LineTo (hdc, x, rect.bottom);
480 SetROP2 (hdc, oldRop);
481 SelectObject (hdc, hOldPen);
482}
483
484
485static BOOL
486HEADER_SendSimpleNotify (HWND hwnd, UINT code)
487{
488 NMHDR nmhdr;
489
490 nmhdr.hwndFrom = hwnd;
491 nmhdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
492 nmhdr.code = code;
493
494 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
495 (WPARAM)nmhdr.idFrom, (LPARAM)&nmhdr);
496}
497
498
499static BOOL
500HEADER_SendHeaderNotify (HWND hwnd, UINT code, INT iItem)
501{
502 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
503 NMHEADERA nmhdr;
504 HDITEMA nmitem;
505
506 nmhdr.hdr.hwndFrom = hwnd;
507 nmhdr.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
508 nmhdr.hdr.code = code;
509 nmhdr.iItem = iItem;
510 nmhdr.iButton = 0;
511 nmhdr.pitem = &nmitem;
512 nmitem.mask = 0;
513 nmitem.cxy = infoPtr->items[iItem].cxy;
514 nmitem.hbm = infoPtr->items[iItem].hbm;
515 nmitem.pszText = NULL;
516 nmitem.cchTextMax = 0;
517/* nmitem.pszText = infoPtr->items[iItem].pszText; */
518/* nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax; */
519 nmitem.fmt = infoPtr->items[iItem].fmt;
520 nmitem.lParam = infoPtr->items[iItem].lParam;
521 nmitem.iOrder = infoPtr->items[iItem].iOrder;
522 nmitem.iImage = infoPtr->items[iItem].iImage;
523
524 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
525 (WPARAM)nmhdr.hdr.idFrom, (LPARAM)&nmhdr);
526}
527
528
529static BOOL
530HEADER_SendClickNotify (HWND hwnd, UINT code, INT iItem)
531{
532 NMHEADERA nmhdr;
533
534 nmhdr.hdr.hwndFrom = hwnd;
535 nmhdr.hdr.idFrom = GetWindowLongA (hwnd, GWL_ID);
536 nmhdr.hdr.code = code;
537 nmhdr.iItem = iItem;
538 nmhdr.iButton = 0;
539 nmhdr.pitem = NULL;
540
541 return (BOOL)SendMessageA (GetParent (hwnd), WM_NOTIFY,
542 (WPARAM)nmhdr.hdr.idFrom, (LPARAM)&nmhdr);
543}
544
545static LRESULT
546HEADER_ClearFilter(HWND hwnd,WPARAM wParam,LPARAM lParam)
547{
548 //CB:todo
549
550 return 0;
551}
552
553static LRESULT
554HEADER_CreateDragImage (HWND hwnd, WPARAM wParam)
555{
556// FIXME (header, "empty stub!\n");
557 return 0;
558}
559
560
561static LRESULT
562HEADER_DeleteItem (HWND hwnd, WPARAM wParam)
563{
564 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
565 INT iItem = (INT)wParam;
566 HDC hdc;
567
568// TRACE(header, "[iItem=%d]\n", iItem);
569
570 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return FALSE;
571
572 if (infoPtr->uNumItem == 1)
573 {
574 //clear
575 if (infoPtr->items[0].pszText) COMCTL32_Free(infoPtr->items[0].pszText);
576 COMCTL32_Free (infoPtr->items);
577 infoPtr->items = 0;
578 infoPtr->uNumItem = 0;
579
580 InvalidateRect(hwnd,NULL,FALSE);
581 } else
582 {
583 HEADER_ITEM *oldItems = infoPtr->items;
584// TRACE(header, "Complex delete! [iItem=%d]\n", iItem);
585
586 if (infoPtr->items[iItem].pszText) COMCTL32_Free(infoPtr->items[iItem].pszText);
587
588 infoPtr->uNumItem--;
589 infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
590 /* pre delete copy */
591 if (iItem > 0)
592 memcpy (&infoPtr->items[0], &oldItems[0],iItem*sizeof(HEADER_ITEM));
593
594 /* post delete copy */
595 if (iItem < infoPtr->uNumItem)
596 memcpy (&infoPtr->items[iItem],&oldItems[iItem+1],(infoPtr->uNumItem-iItem)*sizeof(HEADER_ITEM));
597
598 COMCTL32_Free(oldItems);
599
600 if (iItem < infoPtr->uNumItem) HEADER_SetItemBounds(hwnd,iItem);
601
602 HEADER_Refresh(hwnd);
603
604 }
605
606 return TRUE;
607}
608
609
610static LRESULT
611HEADER_GetImageList (HWND hwnd)
612{
613 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
614
615 return (LRESULT)infoPtr->himl;
616}
617
618
619static LRESULT
620HEADER_GetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
621{
622 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
623 HDITEMA *phdi = (HDITEMA*)lParam;
624 INT nItem = (INT)wParam;
625 HEADER_ITEM *lpItem;
626
627 if (!phdi)
628 return FALSE;
629 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
630 return FALSE;
631
632// TRACE (header, "[nItem=%d]\n", nItem);
633
634 if (phdi->mask == 0)
635 return TRUE;
636
637 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
638 if (phdi->mask & HDI_BITMAP)
639 phdi->hbm = lpItem->hbm;
640
641 if (phdi->mask & HDI_FORMAT)
642 phdi->fmt = lpItem->fmt;
643
644 if (phdi->mask & HDI_WIDTH)
645 phdi->cxy = lpItem->cxy;
646
647 if (phdi->mask & HDI_LPARAM)
648 phdi->lParam = lpItem->lParam;
649
650 if (phdi->mask & HDI_TEXT) {
651 if (lpItem->pszText != LPSTR_TEXTCALLBACKW)
652 lstrcpynWtoA (phdi->pszText, lpItem->pszText, phdi->cchTextMax);
653 else
654 phdi->pszText = LPSTR_TEXTCALLBACKA;
655 }
656
657 if (phdi->mask & HDI_IMAGE)
658 phdi->iImage = lpItem->iImage;
659
660 if (phdi->mask & HDI_ORDER)
661 phdi->iOrder = lpItem->iOrder;
662
663 return TRUE;
664}
665
666
667static LRESULT
668HEADER_GetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
669{
670 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
671 HDITEMW *phdi = (HDITEMW*)lParam;
672 INT nItem = (INT)wParam;
673 HEADER_ITEM *lpItem;
674
675 if (!phdi)
676 return FALSE;
677 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
678 return FALSE;
679
680// TRACE (header, "[nItem=%d]\n", nItem);
681
682 if (phdi->mask == 0)
683 return TRUE;
684
685 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
686 if (phdi->mask & HDI_BITMAP)
687 phdi->hbm = lpItem->hbm;
688
689 if (phdi->mask & HDI_FORMAT)
690 phdi->fmt = lpItem->fmt;
691
692 if (phdi->mask & HDI_WIDTH)
693 phdi->cxy = lpItem->cxy;
694
695 if (phdi->mask & HDI_LPARAM)
696 phdi->lParam = lpItem->lParam;
697
698 if (phdi->mask & HDI_TEXT) {
699 if (lpItem->pszText != LPSTR_TEXTCALLBACKW)
700 lstrcpynW (phdi->pszText, lpItem->pszText, phdi->cchTextMax);
701 else
702 phdi->pszText = LPSTR_TEXTCALLBACKW;
703 }
704
705 if (phdi->mask & HDI_IMAGE)
706 phdi->iImage = lpItem->iImage;
707
708 if (phdi->mask & HDI_ORDER)
709 phdi->iOrder = lpItem->iOrder;
710
711 return TRUE;
712}
713
714
715static LRESULT
716HEADER_GetItemCount (HWND hwnd)
717{
718 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
719 return infoPtr->uNumItem;
720}
721
722
723static LRESULT
724HEADER_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
725{
726 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
727 INT iItem = (INT)wParam;
728 LPRECT lpRect = (LPRECT)lParam;
729
730 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem))
731 return FALSE;
732
733 lpRect->left = infoPtr->items[iItem].rect.left;
734 lpRect->right = infoPtr->items[iItem].rect.right;
735 lpRect->top = infoPtr->items[iItem].rect.top;
736 lpRect->bottom = infoPtr->items[iItem].rect.bottom;
737
738 return TRUE;
739}
740
741
742/* << HEADER_GetOrderArray >> */
743
744
745static LRESULT
746HEADER_GetUnicodeFormat (HWND hwnd)
747{
748 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
749 return infoPtr->bUnicode;
750}
751
752
753static LRESULT
754HEADER_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
755{
756 LPHDHITTESTINFO phti = (LPHDHITTESTINFO)lParam;
757
758 HEADER_InternalHitTest (hwnd, &phti->pt, &phti->flags, &phti->iItem);
759
760 return phti->flags;
761}
762
763
764static LRESULT
765HEADER_InsertItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
766{
767 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
768 HDITEMA *phdi = (HDITEMA*)lParam;
769 INT nItem = (INT)wParam;
770 HEADER_ITEM *lpItem;
771 HDC hdc;
772 INT len;
773
774 if ((phdi == NULL) || (nItem < 0))
775 return -1;
776
777 if (nItem > infoPtr->uNumItem)
778 nItem = infoPtr->uNumItem;
779
780 if (infoPtr->uNumItem == 0) {
781 infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM));
782 infoPtr->uNumItem++;
783 }
784 else {
785 HEADER_ITEM *oldItems = infoPtr->items;
786
787 infoPtr->uNumItem++;
788 infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
789 if (nItem == 0) {
790 memcpy (&infoPtr->items[1], &oldItems[0],
791 (infoPtr->uNumItem-1) * sizeof(HEADER_ITEM));
792 }
793 else
794 {
795 /* pre insert copy */
796 if (nItem > 0) {
797 memcpy (&infoPtr->items[0], &oldItems[0],
798 nItem * sizeof(HEADER_ITEM));
799 }
800
801 /* post insert copy */
802 if (nItem < infoPtr->uNumItem - 1) {
803 memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
804 (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
805 }
806 }
807
808 COMCTL32_Free (oldItems);
809 }
810
811 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
812 lpItem->bDown = FALSE;
813
814 if (phdi->mask & HDI_WIDTH)
815 lpItem->cxy = phdi->cxy;
816
817 if (phdi->mask & HDI_TEXT) {
818 if (!phdi->pszText) /* null pointer check */
819 phdi->pszText = "";
820 if (phdi->pszText != LPSTR_TEXTCALLBACKA) {
821 len = lstrlenA (phdi->pszText);
822 lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
823 lstrcpyAtoW (lpItem->pszText, phdi->pszText);
824 }
825 else
826 lpItem->pszText = LPSTR_TEXTCALLBACKW;
827 }
828
829 if (phdi->mask & HDI_FORMAT)
830 lpItem->fmt = phdi->fmt;
831
832 if (lpItem->fmt == 0)
833 lpItem->fmt = HDF_LEFT;
834
835 if (phdi->mask & HDI_BITMAP)
836 lpItem->hbm = phdi->hbm;
837
838 if (phdi->mask & HDI_LPARAM)
839 lpItem->lParam = phdi->lParam;
840
841 if (phdi->mask & HDI_IMAGE)
842 lpItem->iImage = phdi->iImage;
843
844 if (phdi->mask & HDI_ORDER)
845 lpItem->iOrder = phdi->iOrder;
846
847 HEADER_SetItemBounds (hwnd,nItem);
848
849 HEADER_Refresh(hwnd);
850
851 return nItem;
852}
853
854
855static LRESULT
856HEADER_InsertItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
857{
858 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
859 HDITEMW *phdi = (HDITEMW*)lParam;
860 INT nItem = (INT)wParam;
861 HEADER_ITEM *lpItem;
862 HDC hdc;
863 INT len;
864
865 if ((phdi == NULL) || (nItem < 0))
866 return -1;
867
868 if (nItem > infoPtr->uNumItem)
869 nItem = infoPtr->uNumItem;
870
871 if (infoPtr->uNumItem == 0) {
872 infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM));
873 infoPtr->uNumItem++;
874 }
875 else {
876 HEADER_ITEM *oldItems = infoPtr->items;
877
878 infoPtr->uNumItem++;
879 infoPtr->items = COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
880 /* pre insert copy */
881 if (nItem > 0) {
882 memcpy (&infoPtr->items[0], &oldItems[0],
883 nItem * sizeof(HEADER_ITEM));
884 }
885
886 /* post insert copy */
887 if (nItem < infoPtr->uNumItem - 1) {
888 memcpy (&infoPtr->items[nItem+1], &oldItems[nItem],
889 (infoPtr->uNumItem - nItem) * sizeof(HEADER_ITEM));
890 }
891
892 COMCTL32_Free (oldItems);
893 }
894
895 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
896 lpItem->bDown = FALSE;
897
898 if (phdi->mask & HDI_WIDTH)
899 lpItem->cxy = phdi->cxy;
900
901 if (phdi->mask & HDI_TEXT) {
902 WCHAR wide_null_char = 0;
903 if (!phdi->pszText) /* null pointer check */
904 phdi->pszText = &wide_null_char;
905 if (phdi->pszText != LPSTR_TEXTCALLBACKW) {
906 len = lstrlenW (phdi->pszText);
907 lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
908 lstrcpyW (lpItem->pszText, phdi->pszText);
909 }
910 else
911 lpItem->pszText = LPSTR_TEXTCALLBACKW;
912 }
913
914 if (phdi->mask & HDI_FORMAT)
915 lpItem->fmt = phdi->fmt;
916
917 if (lpItem->fmt == 0)
918 lpItem->fmt = HDF_LEFT;
919
920 if (phdi->mask & HDI_BITMAP)
921 lpItem->hbm = phdi->hbm;
922
923 if (phdi->mask & HDI_LPARAM)
924 lpItem->lParam = phdi->lParam;
925
926 if (phdi->mask & HDI_IMAGE)
927 lpItem->iImage = phdi->iImage;
928
929 if (phdi->mask & HDI_ORDER)
930 lpItem->iOrder = phdi->iOrder;
931
932 HEADER_SetItemBounds (hwnd,nItem);
933
934 HEADER_Refresh(hwnd);
935
936 return nItem;
937}
938
939
940static LRESULT
941HEADER_Layout (HWND hwnd, WPARAM wParam, LPARAM lParam)
942{
943 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
944 LPHDLAYOUT lpLayout = (LPHDLAYOUT)lParam;
945
946 lpLayout->pwpos->hwnd = hwnd;
947 lpLayout->pwpos->hwndInsertAfter = 0;
948 lpLayout->pwpos->x = lpLayout->prc->left;
949 lpLayout->pwpos->y = lpLayout->prc->top;
950 lpLayout->pwpos->cx = lpLayout->prc->right - lpLayout->prc->left;
951 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_HIDDEN)
952 lpLayout->pwpos->cy = 0;
953 else
954 lpLayout->pwpos->cy = infoPtr->nHeight;
955 lpLayout->pwpos->flags = SWP_NOZORDER;
956
957// TRACE (header, "Layout x=%d y=%d cx=%d cy=%d\n",
958// lpLayout->pwpos->x, lpLayout->pwpos->y,
959// lpLayout->pwpos->cx, lpLayout->pwpos->cy);
960
961 HEADER_ForceItemBounds (hwnd, lpLayout->pwpos->cy);
962
963 /* hack */
964#ifdef __HDM_LAYOUT_HACK__
965 MoveWindow (lpLayout->pwpos->hwnd, lpLayout->pwpos->x, lpLayout->pwpos->y,
966 lpLayout->pwpos->cx, lpLayout->pwpos->cy, TRUE);
967#endif
968
969 return TRUE;
970}
971
972
973static LRESULT
974HEADER_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
975{
976 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
977 HIMAGELIST himlOld;
978
979 himlOld = infoPtr->himl;
980 infoPtr->himl = (HIMAGELIST)lParam;
981
982 /* FIXME: Refresh needed??? */
983
984 return (LRESULT)himlOld;
985}
986
987
988static LRESULT
989HEADER_SetItemA (HWND hwnd, WPARAM wParam, LPARAM lParam)
990{
991 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
992 HDITEMA *phdi = (HDITEMA*)lParam;
993 INT nItem = (INT)wParam;
994 HEADER_ITEM *lpItem;
995 HDC hdc;
996
997 if (phdi == NULL)
998 return FALSE;
999 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
1000 return FALSE;
1001
1002// TRACE (header, "[nItem=%d]\n", nItem);
1003
1004 if (HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGINGA, nItem))
1005 return FALSE;
1006
1007 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1008 if (phdi->mask & HDI_BITMAP)
1009 lpItem->hbm = phdi->hbm;
1010
1011 if (phdi->mask & HDI_FORMAT)
1012 lpItem->fmt = phdi->fmt;
1013
1014 if (phdi->mask & HDI_LPARAM)
1015 lpItem->lParam = phdi->lParam;
1016
1017 if (phdi->mask & HDI_TEXT) {
1018 if (phdi->pszText != LPSTR_TEXTCALLBACKA) {
1019 if (lpItem->pszText) {
1020 COMCTL32_Free (lpItem->pszText);
1021 lpItem->pszText = NULL;
1022 }
1023 if (phdi->pszText) {
1024 INT len = lstrlenA (phdi->pszText);
1025 lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1026 lstrcpyAtoW (lpItem->pszText, phdi->pszText);
1027 }
1028 }
1029 else
1030 lpItem->pszText = LPSTR_TEXTCALLBACKW;
1031 }
1032
1033 if (phdi->mask & HDI_WIDTH)
1034 lpItem->cxy = phdi->cxy;
1035
1036 if (phdi->mask & HDI_IMAGE)
1037 lpItem->iImage = phdi->iImage;
1038
1039 if (phdi->mask & HDI_ORDER)
1040 lpItem->iOrder = phdi->iOrder;
1041
1042 HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA, nItem);
1043
1044 HEADER_SetItemBounds (hwnd,0);
1045 HEADER_Refresh(hwnd);
1046
1047 return TRUE;
1048}
1049
1050
1051static LRESULT
1052HEADER_SetItemW (HWND hwnd, WPARAM wParam, LPARAM lParam)
1053{
1054 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1055 HDITEMW *phdi = (HDITEMW*)lParam;
1056 INT nItem = (INT)wParam;
1057 HEADER_ITEM *lpItem;
1058 HDC hdc;
1059
1060 if (phdi == NULL)
1061 return FALSE;
1062 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem))
1063 return FALSE;
1064
1065// TRACE (header, "[nItem=%d]\n", nItem);
1066
1067 if (HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGINGA, nItem))
1068 return FALSE;
1069
1070 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1071 if (phdi->mask & HDI_BITMAP)
1072 lpItem->hbm = phdi->hbm;
1073
1074 if (phdi->mask & HDI_FORMAT)
1075 lpItem->fmt = phdi->fmt;
1076
1077 if (phdi->mask & HDI_LPARAM)
1078 lpItem->lParam = phdi->lParam;
1079
1080 if (phdi->mask & HDI_TEXT) {
1081 if (phdi->pszText != LPSTR_TEXTCALLBACKW) {
1082 if (lpItem->pszText) {
1083 COMCTL32_Free (lpItem->pszText);
1084 lpItem->pszText = NULL;
1085 }
1086 if (phdi->pszText) {
1087 INT len = lstrlenW (phdi->pszText);
1088 lpItem->pszText = COMCTL32_Alloc ((len+1)*sizeof(WCHAR));
1089 lstrcpyW (lpItem->pszText, phdi->pszText);
1090 }
1091 }
1092 else
1093 lpItem->pszText = LPSTR_TEXTCALLBACKW;
1094 }
1095
1096 if (phdi->mask & HDI_WIDTH)
1097 lpItem->cxy = phdi->cxy;
1098
1099 if (phdi->mask & HDI_IMAGE)
1100 lpItem->iImage = phdi->iImage;
1101
1102 if (phdi->mask & HDI_ORDER)
1103 lpItem->iOrder = phdi->iOrder;
1104
1105 HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA, nItem);
1106
1107 HEADER_SetItemBounds (hwnd,0);
1108 HEADER_Refresh(hwnd);
1109
1110 return TRUE;
1111}
1112
1113
1114/* << HEADER_SetOrderArray >> */
1115
1116
1117static LRESULT
1118HEADER_SetUnicodeFormat (HWND hwnd, WPARAM wParam)
1119{
1120 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1121 BOOL bTemp = infoPtr->bUnicode;
1122
1123 infoPtr->bUnicode = (BOOL)wParam;
1124
1125 return bTemp;
1126}
1127
1128
1129static LRESULT
1130HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1131{
1132 HEADER_INFO *infoPtr;
1133 TEXTMETRICA tm;
1134 HFONT hOldFont;
1135 HDC hdc;
1136
1137 infoPtr = (HEADER_INFO *)COMCTL32_Alloc (sizeof(HEADER_INFO));
1138 SetWindowLongA (hwnd, 0, (DWORD)infoPtr);
1139
1140 infoPtr->uNumItem = 0;
1141 infoPtr->hFont = 0;
1142 infoPtr->items = 0;
1143 infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
1144 infoPtr->hcurDivider = LoadCursorA (0, IDC_SIZEWEA);
1145 infoPtr->hcurDivopen = LoadCursorA (0, IDC_SIZENSA);
1146 infoPtr->bPressed = FALSE;
1147 infoPtr->bTracking = FALSE;
1148 infoPtr->iMoveItem = 0;
1149 infoPtr->himl = 0;
1150 infoPtr->iHotItem = -1;
1151 infoPtr->bUnicode = IsWindowUnicode (hwnd);
1152
1153 hdc = GetDC (0);
1154 hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT));
1155 GetTextMetricsA (hdc, &tm);
1156 infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
1157 SelectObject (hdc, hOldFont);
1158 ReleaseDC (0, hdc);
1159
1160 return 0;
1161}
1162
1163
1164static LRESULT
1165HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1166{
1167 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1168 HEADER_ITEM *lpItem;
1169 INT nItem;
1170
1171 if (infoPtr->items) {
1172 lpItem = (HEADER_ITEM*)infoPtr->items;
1173 for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
1174 if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACKW))
1175 COMCTL32_Free (lpItem->pszText);
1176 }
1177 COMCTL32_Free (infoPtr->items);
1178 }
1179
1180 if (infoPtr->himl)
1181 ImageList_Destroy (infoPtr->himl);
1182
1183 COMCTL32_Free (infoPtr);
1184
1185 return 0;
1186}
1187
1188static LRESULT
1189HEADER_EraseBackground(HWND hwnd,WPARAM wParam,LPARAM lParam)
1190{
1191 return TRUE;
1192}
1193
1194static LRESULT
1195HEADER_GetDlgCode(HWND hwnd,WPARAM wParam,LPARAM lParam)
1196{
1197 return DLGC_WANTTAB | DLGC_WANTARROWS;
1198}
1199
1200static LRESULT
1201HEADER_GetFont (HWND hwnd)
1202{
1203 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1204
1205 return (LRESULT)infoPtr->hFont;
1206}
1207
1208
1209static LRESULT
1210HEADER_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
1211{
1212 POINT pt;
1213 UINT flags;
1214 INT nItem;
1215
1216 pt.x = (INT)LOWORD(lParam);
1217 pt.y = (INT)HIWORD(lParam);
1218 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1219
1220 if ((GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS) && (flags == HHT_ONHEADER))
1221 HEADER_SendHeaderNotify (hwnd, HDN_ITEMDBLCLICKA, nItem);
1222 else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
1223 HEADER_SendHeaderNotify (hwnd, HDN_DIVIDERDBLCLICKA, nItem);
1224
1225 return 0;
1226}
1227
1228
1229static LRESULT
1230HEADER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1231{
1232 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1233 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1234 POINT pt;
1235 UINT flags;
1236 INT nItem;
1237 HDC hdc;
1238
1239 pt.x = (INT)LOWORD(lParam);
1240 pt.y = (INT)HIWORD(lParam);
1241 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1242
1243 if ((dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER))
1244 {
1245 SetCapture (hwnd);
1246 infoPtr->bCaptured = TRUE;
1247 infoPtr->bPressed = TRUE;
1248 infoPtr->iMoveItem = nItem;
1249
1250 infoPtr->items[nItem].bDown = TRUE;
1251
1252 /* Send WM_CUSTOMDRAW */
1253 hdc = GetDC (hwnd);
1254 HEADER_RefreshItem (hwnd, hdc, nItem);
1255 ReleaseDC (hwnd, hdc);
1256
1257// TRACE (header, "Pressed item %d!\n", nItem);
1258 }
1259 else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
1260 {
1261 if (!(HEADER_SendHeaderNotify (hwnd, HDN_BEGINTRACKA, nItem)))
1262 {
1263 SetCapture (hwnd);
1264 infoPtr->bCaptured = TRUE;
1265 infoPtr->bTracking = TRUE;
1266 infoPtr->iMoveItem = nItem;
1267 infoPtr->nOldWidth = infoPtr->items[nItem].cxy;
1268 infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
1269
1270 if (!(dwStyle & HDS_FULLDRAG))
1271 {
1272 infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
1273 hdc = GetDC (hwnd);
1274 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1275 ReleaseDC (hwnd, hdc);
1276 }
1277
1278// TRACE (header, "Begin tracking item %d!\n", nItem);
1279 }
1280 }
1281
1282 return 0;
1283}
1284
1285
1286static LRESULT
1287HEADER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1288{
1289 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1290 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1291 POINT pt;
1292 UINT flags;
1293 INT nItem, nWidth;
1294 HDC hdc;
1295
1296 pt.x = (INT)LOWORD(lParam);
1297 pt.y = (INT)HIWORD(lParam);
1298 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1299
1300 if (infoPtr->bPressed)
1301 {
1302 if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
1303 {
1304 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1305 hdc = GetDC (hwnd);
1306 HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem);
1307 ReleaseDC (hwnd, hdc);
1308
1309 HEADER_SendClickNotify (hwnd, HDN_ITEMCLICKA, infoPtr->iMoveItem);
1310 }
1311// TRACE (header, "Released item %d!\n", infoPtr->iMoveItem);
1312 infoPtr->bPressed = FALSE;
1313 }
1314 else if (infoPtr->bTracking)
1315 {
1316// TRACE (header, "End tracking item %d!\n", infoPtr->iMoveItem);
1317 infoPtr->bTracking = FALSE;
1318
1319 HEADER_SendHeaderNotify (hwnd, HDN_ENDTRACKA, infoPtr->iMoveItem);
1320
1321 if (!(dwStyle & HDS_FULLDRAG))
1322 {
1323 hdc = GetDC (hwnd);
1324 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1325 ReleaseDC (hwnd, hdc);
1326 if (HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGINGA, infoPtr->iMoveItem))
1327 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1328 else
1329 {
1330 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1331 if (nWidth < MIN_ITEMWIDTH) nWidth = MIN_ITEMWIDTH;
1332
1333 if (infoPtr->nOldWidth != nWidth)
1334 {
1335 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1336 HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA, infoPtr->iMoveItem);
1337
1338 HEADER_SetItemBounds (hwnd,infoPtr->iMoveItem);
1339
1340 HEADER_Refresh(hwnd);
1341 }
1342 }
1343 }
1344 }
1345
1346 if (infoPtr->bCaptured) {
1347 infoPtr->bCaptured = FALSE;
1348 ReleaseCapture ();
1349 HEADER_SendSimpleNotify (hwnd, NM_RELEASEDCAPTURE);
1350 }
1351
1352 return 0;
1353}
1354
1355
1356static LRESULT
1357HEADER_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
1358{
1359 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1360 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1361 POINT pt;
1362 UINT flags;
1363 INT nItem, nWidth;
1364 HDC hdc;
1365
1366 pt.x = (INT)LOWORD(lParam);
1367 pt.y = (INT)HIWORD(lParam);
1368 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1369
1370 if ((dwStyle & HDS_BUTTONS) && (dwStyle & HDS_HOTTRACK))
1371 {
1372 INT newItem;
1373
1374 if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN))
1375 newItem = nItem;
1376 else
1377 newItem = -1;
1378 if (newItem != infoPtr->iHotItem)
1379 {
1380 INT oldItem = infoPtr->iHotItem;
1381
1382 infoPtr->iHotItem = newItem;
1383 hdc = GetDC (hwnd);
1384 if (oldItem != -1) HEADER_DrawItem(hwnd,hdc,oldItem,FALSE,TRUE);
1385 if (newItem != -1) HEADER_DrawItem(hwnd,hdc,newItem,TRUE,TRUE);
1386 ReleaseDC (hwnd, hdc);
1387 }
1388 }
1389
1390 if (infoPtr->bCaptured)
1391 {
1392 if (infoPtr->bPressed)
1393 {
1394 BOOL newDown;
1395
1396 if ((nItem == infoPtr->iMoveItem) && (flags == HHT_ONHEADER))
1397 newDown = TRUE;
1398 else
1399 newDown = FALSE;
1400
1401 if (newDown != infoPtr->items[infoPtr->iMoveItem].bDown)
1402 {
1403 infoPtr->items[infoPtr->iMoveItem].bDown = newDown;
1404 hdc = GetDC (hwnd);
1405 HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem);
1406 ReleaseDC (hwnd, hdc);
1407 }
1408// TRACE (header, "Moving pressed item %d!\n", infoPtr->iMoveItem);
1409 }
1410 else if (infoPtr->bTracking) {
1411 if (dwStyle & HDS_FULLDRAG) {
1412 if (HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGINGA, infoPtr->iMoveItem))
1413 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1414 else {
1415 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1416 if (nWidth < MIN_ITEMWIDTH)
1417 nWidth = MIN_ITEMWIDTH;
1418 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1419 HEADER_SendHeaderNotify (hwnd, HDN_ITEMCHANGEDA,
1420 infoPtr->iMoveItem);
1421 }
1422 HEADER_SetItemBounds (hwnd,infoPtr->iMoveItem);
1423 HEADER_Refresh(hwnd);
1424 }
1425 else {
1426 hdc = GetDC (hwnd);
1427 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1428 infoPtr->xOldTrack = pt.x + infoPtr->xTrackOffset;
1429 if (infoPtr->xOldTrack < infoPtr->items[infoPtr->iMoveItem].rect.left)
1430 infoPtr->xOldTrack = infoPtr->items[infoPtr->iMoveItem].rect.left;
1431 infoPtr->items[infoPtr->iMoveItem].cxy =
1432 infoPtr->xOldTrack - infoPtr->items[infoPtr->iMoveItem].rect.left;
1433 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1434 ReleaseDC (hwnd, hdc);
1435 }
1436
1437 HEADER_SendHeaderNotify (hwnd, HDN_TRACKA, infoPtr->iMoveItem);
1438// TRACE (header, "Tracking item %d!\n", infoPtr->iMoveItem);
1439 }
1440 }
1441
1442 if ((dwStyle & HDS_BUTTONS) && (dwStyle & HDS_HOTTRACK)) {
1443// FIXME (header, "hot track support!\n");
1444 }
1445
1446 return 0;
1447}
1448
1449
1450static LRESULT
1451HEADER_Paint (HWND hwnd, WPARAM wParam)
1452{
1453 HDC hdc;
1454 PAINTSTRUCT ps;
1455
1456 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
1457 HEADER_Draw (hwnd, hdc);
1458 if(!wParam)
1459 EndPaint (hwnd, &ps);
1460
1461 return 0;
1462}
1463
1464
1465static LRESULT
1466HEADER_RButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1467{
1468 return HEADER_SendSimpleNotify (hwnd, NM_RCLICK);
1469}
1470
1471
1472static LRESULT
1473HEADER_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam)
1474{
1475 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1476 POINT pt;
1477 UINT flags;
1478 INT nItem;
1479
1480// TRACE (header, "code=0x%X id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
1481
1482 GetCursorPos (&pt);
1483 ScreenToClient (hwnd, &pt);
1484
1485 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1486
1487 if (flags == HHT_ONDIVIDER)
1488 SetCursor (infoPtr->hcurDivider);
1489 else if (flags == HHT_ONDIVOPEN)
1490 SetCursor (infoPtr->hcurDivopen);
1491 else
1492 SetCursor (infoPtr->hcurArrow);
1493
1494 return 0;
1495}
1496
1497
1498static LRESULT
1499HEADER_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
1500{
1501 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1502 TEXTMETRICA tm;
1503 HFONT hFont, hOldFont;
1504 HDC hdc;
1505
1506 infoPtr->hFont = (HFONT)wParam;
1507
1508 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
1509
1510 hdc = GetDC (0);
1511 hOldFont = SelectObject (hdc, hFont);
1512 GetTextMetricsA (hdc, &tm);
1513 infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
1514 SelectObject (hdc, hOldFont);
1515 ReleaseDC (0, hdc);
1516
1517 if (lParam) {
1518 HEADER_ForceItemBounds (hwnd, infoPtr->nHeight);
1519 HEADER_Refresh(hwnd);
1520 }
1521
1522 return 0;
1523}
1524
1525
1526static LRESULT WINAPI
1527HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
1528{
1529 switch (msg)
1530 {
1531// case HDM_CLEARFILTER: //CB:add const
1532// return HEADER_ClearFilter(hwnd,wParam,lParam);
1533
1534 case HDM_CREATEDRAGIMAGE:
1535 return HEADER_CreateDragImage (hwnd, wParam);
1536
1537 case HDM_DELETEITEM:
1538 return HEADER_DeleteItem (hwnd, wParam);
1539
1540 case HDM_GETIMAGELIST:
1541 return HEADER_GetImageList (hwnd);
1542
1543 case HDM_GETITEMA:
1544 return HEADER_GetItemA (hwnd, wParam, lParam);
1545
1546 case HDM_GETITEMW:
1547 return HEADER_GetItemW (hwnd, wParam, lParam);
1548
1549 case HDM_GETITEMCOUNT:
1550 return HEADER_GetItemCount (hwnd);
1551
1552 case HDM_GETITEMRECT:
1553 return HEADER_GetItemRect (hwnd, wParam, lParam);
1554
1555/* case HDM_GETORDERARRAY: */
1556
1557 case HDM_GETUNICODEFORMAT:
1558 return HEADER_GetUnicodeFormat (hwnd);
1559
1560 case HDM_HITTEST:
1561 return HEADER_HitTest (hwnd, wParam, lParam);
1562
1563 case HDM_INSERTITEMA:
1564 return HEADER_InsertItemA (hwnd, wParam, lParam);
1565
1566 case HDM_INSERTITEMW:
1567 return HEADER_InsertItemW (hwnd, wParam, lParam);
1568
1569 case HDM_LAYOUT:
1570 return HEADER_Layout (hwnd, wParam, lParam);
1571
1572 case HDM_SETIMAGELIST:
1573 return HEADER_SetImageList (hwnd, wParam, lParam);
1574
1575 case HDM_SETITEMA:
1576 return HEADER_SetItemA (hwnd, wParam, lParam);
1577
1578 case HDM_SETITEMW:
1579 return HEADER_SetItemW (hwnd, wParam, lParam);
1580
1581/* case HDM_SETORDERARRAY: */
1582
1583 case HDM_SETUNICODEFORMAT:
1584 return HEADER_SetUnicodeFormat (hwnd, wParam);
1585
1586 case WM_CREATE:
1587 return HEADER_Create (hwnd, wParam, lParam);
1588
1589 case WM_DESTROY:
1590 return HEADER_Destroy (hwnd, wParam, lParam);
1591
1592 case WM_ERASEBKGND:
1593 return HEADER_EraseBackground(hwnd,wParam,lParam);
1594
1595 case WM_GETDLGCODE:
1596 return HEADER_GetDlgCode(hwnd,wParam,lParam);
1597
1598 case WM_GETFONT:
1599 return HEADER_GetFont (hwnd);
1600
1601 case WM_LBUTTONDBLCLK:
1602 return HEADER_LButtonDblClk (hwnd, wParam, lParam);
1603
1604 case WM_LBUTTONDOWN:
1605 return HEADER_LButtonDown (hwnd, wParam, lParam);
1606
1607 case WM_LBUTTONUP:
1608 return HEADER_LButtonUp (hwnd, wParam, lParam);
1609
1610 case WM_MOUSEMOVE:
1611 return HEADER_MouseMove (hwnd, wParam, lParam);
1612
1613/* case WM_NOTIFYFORMAT: */
1614
1615 case WM_PAINT:
1616 return HEADER_Paint(hwnd,wParam);
1617
1618 case WM_RBUTTONUP:
1619 return HEADER_RButtonUp (hwnd, wParam, lParam);
1620
1621 case WM_SETCURSOR:
1622 return HEADER_SetCursor (hwnd, wParam, lParam);
1623
1624 case WM_SETFONT:
1625 return HEADER_SetFont (hwnd, wParam, lParam);
1626
1627 default:
1628// if (msg >= WM_USER)
1629// ERR (header, "unknown msg %04x wp=%04x lp=%08lx\n",
1630// msg, wParam, lParam );
1631 return DefWindowProcA (hwnd, msg, wParam, lParam);
1632 }
1633 return 0;
1634}
1635
1636
1637VOID
1638HEADER_Register (VOID)
1639{
1640 WNDCLASSA wndClass;
1641
1642 if (GlobalFindAtomA (WC_HEADERA)) return;
1643
1644 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
1645 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS;
1646 wndClass.lpfnWndProc = (WNDPROC)HEADER_WindowProc;
1647 wndClass.cbClsExtra = 0;
1648 wndClass.cbWndExtra = sizeof(HEADER_INFO *);
1649 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
1650 wndClass.lpszClassName = WC_HEADERA;
1651
1652 RegisterClassA (&wndClass);
1653}
1654
1655
1656VOID
1657HEADER_Unregister (VOID)
1658{
1659 if (GlobalFindAtomA (WC_HEADERA))
1660 UnregisterClassA (WC_HEADERA, (HINSTANCE)NULL);
1661}
1662
Note: See TracBrowser for help on using the repository browser.