source: trunk/src/comctl32/header.cpp@ 3385

Last change on this file since 3385 was 3385, checked in by cbratschi, 25 years ago

new listview item handling, new messages

File size: 59.3 KB
Line 
1/* $Id: header.cpp,v 1.6 2000-04-15 14:22:15 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 * - Control specific cursors (over dividers)
11 *
12 * - HDS_FILTERBAR
13 * - HEADER_SetHotDivider()
14 *
15 * Status: ready (inconsistent parts in Microsoft SDK documentation)
16 * Version: 5.00
17 */
18
19/*
20 - Corel 20000317 level
21*/
22
23#include <string.h>
24
25#include "winbase.h"
26#include "commctrl.h"
27#include "ccbase.h"
28#include "header.h"
29#include "comctl32.h"
30
31
32#define VERT_BORDER 4
33#define DIVIDER_WIDTH 10
34#define MIN_ITEMWIDTH 0
35#define ITEM_FRAMESIZE 2
36#define TEXT_MARGIN 3
37#define TIMER_ID 1
38#define TIMER_MS 200
39
40#define HEADER_GetInfoPtr(hwnd) ((HEADER_INFO*)getInfoPtr(hwnd))
41
42static INT HEADER_CallbackImage(HWND hwnd,HEADER_INFO* infoPtr,HEADER_ITEM* phdi,INT iItem)
43{
44 NMHDDISPINFOW nmhdr;
45
46 nmhdr.iItem = iItem;
47 nmhdr.mask = HDI_IMAGE;
48 nmhdr.iImage = 0;
49 nmhdr.lParam = phdi->lParam;
50 sendNotify(hwnd,isUnicodeNotify(&infoPtr->header) ? HDN_GETDISPINFOW:HDN_GETDISPINFOA,&nmhdr.hdr);
51
52 if (nmhdr.mask & HDI_DI_SETITEM) phdi->iImage = nmhdr.iImage;
53
54 return nmhdr.iImage;
55}
56
57static VOID HEADER_DrawItemImage(HWND hwnd,HDC hdc,HEADER_INFO* infoPtr,HEADER_ITEM* phdi,RECT* r,INT iItem)
58{
59 if (phdi->fmt & HDF_IMAGE)
60 {
61 INT iImage;
62 IMAGEINFO info;
63 INT x,y,cx,cy,w,h,rx,ry;
64
65 if (phdi->iImage == I_IMAGECALLBACK)
66 iImage = HEADER_CallbackImage(hwnd,infoPtr,phdi,iItem);
67 else
68 iImage = phdi->iImage;
69
70 if (iImage == I_IMAGENONE) return;
71 if (!ImageList_GetImageInfo(infoPtr->himl,phdi->iImage,&info)) return;
72 w = info.rcImage.right-info.rcImage.left;
73 h = info.rcImage.bottom-info.rcImage.top;
74
75 ry = r->bottom-r->top;
76 rx = r->right-r->left;
77
78 if (ry >= h)
79 {
80 cy = h;
81 y = r->top+(ry-h)/2;
82 } else
83 {
84 cy = ry;
85 y = r->top;
86 }
87
88 if (rx >= w+infoPtr->xBmpMargin)
89 cx = w;
90 else
91 cx = MAX(0,rx-w-infoPtr->xBmpMargin);
92
93 if (ImageList_DrawEx(infoPtr->himl,phdi->iImage,hdc,x,y,cx,cy,CLR_NONE,CLR_NONE,ILD_TRANSPARENT))
94 {
95 r->left += w+2*infoPtr->xBmpMargin;
96 }
97 }
98}
99
100static VOID
101HEADER_DrawItemBitmap(HDC hdc,HEADER_INFO* infoPtr,HEADER_ITEM* phdi,RECT* r,WCHAR* pszText,UINT uTextJustify)
102{
103 if ((phdi->fmt & HDF_BITMAP) && !(phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm))
104 {
105 BITMAP bmp;
106 HDC hdcBitmap;
107 INT yD,yS,cx,cy,rx,ry;
108
109 GetObjectA (phdi->hbm,sizeof(BITMAP),(LPVOID)&bmp);
110
111 ry = r->bottom-r->top;
112 rx = r->right-r->left;
113
114 if (ry >= bmp.bmHeight)
115 {
116 cy = bmp.bmHeight;
117 yD = r->top + (ry - bmp.bmHeight) / 2;
118 yS = 0;
119 } else
120 {
121 cy = ry;
122 yD = r->top;
123 yS = (bmp.bmHeight - ry) / 2;
124 }
125
126 if (rx >= bmp.bmWidth+infoPtr->xBmpMargin)
127 cx = bmp.bmWidth;
128 else
129 cx = MAX(0,rx-bmp.bmWidth-infoPtr->xBmpMargin);
130
131 hdcBitmap = CreateCompatibleDC (hdc);
132 SelectObject(hdcBitmap,phdi->hbm);
133 BitBlt (hdc,r->left+infoPtr->xBmpMargin,yD,cx,cy,hdcBitmap,0,yS,SRCCOPY);
134 DeleteDC (hdcBitmap);
135
136 r->left += bmp.bmWidth+2*infoPtr->xBmpMargin;
137 } else if ((phdi->fmt & HDF_BITMAP_ON_RIGHT) && (phdi->hbm))
138 {
139 BITMAP bmp;
140 HDC hdcBitmap;
141 INT xD,yD,yS,cx,cy,rx,ry,tx;
142 RECT textRect;
143
144 GetObjectA (phdi->hbm,sizeof(BITMAP),(LPVOID)&bmp);
145
146 textRect = *r;
147 DrawTextExW(hdc,pszText,lstrlenW(pszText),&textRect,DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_CALCRECT|DT_END_ELLIPSIS,NULL);
148 tx = textRect.right - textRect.left;
149 ry = r->bottom-r->top;
150 rx = r->right-r->left;
151
152 if (ry >= bmp.bmHeight)
153 {
154 cy = bmp.bmHeight;
155 yD = r->top + (ry - bmp.bmHeight) / 2;
156 yS = 0;
157 } else
158 {
159 cy = ry;
160 yD = r->top;
161 yS = (bmp.bmHeight - ry) / 2;
162 }
163
164 if (r->left+tx+bmp.bmWidth+2*infoPtr->xBmpMargin <= r->right)
165 {
166 cx = bmp.bmWidth;
167 if (uTextJustify & DT_LEFT)
168 xD = r->left+tx+infoPtr->xBmpMargin;
169 else
170 {
171 xD = r->right-infoPtr->xBmpMargin-bmp.bmWidth;
172 r->right = xD;
173 }
174 } else
175 {
176 if (rx >= bmp.bmWidth+2*infoPtr->xBmpMargin)
177 {
178 cx = bmp.bmWidth;
179 xD = r->right-bmp.bmWidth-infoPtr->xBmpMargin;
180 r->right = xD-infoPtr->xBmpMargin;
181 } else
182 {
183 cx = MAX(0,rx-infoPtr->xBmpMargin);
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
196static WCHAR* HEADER_CallbackText(HWND hwnd,HEADER_INFO* infoPtr,HEADER_ITEM* phdi,INT iItem,BOOL* mustFree)
197{
198 NMHDDISPINFOW nmhdr;
199 WCHAR* orgPtr;
200
201 nmhdr.iItem = iItem;
202 nmhdr.mask = HDI_TEXT;
203 nmhdr.cchTextMax = phdi->cchTextMax;
204 if (isUnicodeNotify(&infoPtr->header))
205 {
206 orgPtr = (WCHAR*)COMCTL32_Alloc(phdi->cchTextMax*sizeof(WCHAR));
207 nmhdr.pszText = orgPtr;
208 if (nmhdr.pszText) nmhdr.pszText[0] = 0;
209 } else
210 {
211 orgPtr = (WCHAR*)COMCTL32_Alloc(phdi->cchTextMax*sizeof(CHAR));
212 nmhdr.pszText = orgPtr;
213 if (nmhdr.pszText) ((LPSTR)nmhdr.pszText)[0] = 0;
214 }
215 nmhdr.lParam = phdi->lParam;
216 sendNotify(hwnd,isUnicodeNotify(&infoPtr->header) ? HDN_GETDISPINFOW:HDN_GETDISPINFOA,&nmhdr.hdr);
217
218 if (nmhdr.pszText == LPSTR_TEXTCALLBACKW)
219 {
220 *mustFree = FALSE;
221 return NULL;
222 }
223
224 if (nmhdr.mask & HDI_DI_SETITEM)
225 {
226 if (isUnicodeNotify(&infoPtr->header))
227 {
228 INT len = nmhdr.pszText ? lstrlenW(nmhdr.pszText):0;
229
230 if (len)
231 {
232 phdi->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
233 lstrcpyW(phdi->pszText,nmhdr.pszText);
234 } else phdi->pszText = NULL;
235 if (nmhdr.pszText == orgPtr) COMCTL32_Free(nmhdr.pszText);
236 } else
237 {
238 INT len = nmhdr.pszText ? lstrlenA((LPSTR)nmhdr.pszText):0;
239
240 if (len)
241 {
242 phdi->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
243 lstrcpyAtoW(phdi->pszText,(LPSTR)nmhdr.pszText);
244 } else phdi->pszText = NULL;
245 }
246 COMCTL32_Free(orgPtr);
247 *mustFree = FALSE;
248
249 return phdi->pszText;
250 }
251 if (nmhdr.pszText != orgPtr)
252 {
253 COMCTL32_Free(orgPtr);
254 *mustFree = FALSE;
255 } else *mustFree = TRUE;
256
257 return nmhdr.pszText;
258}
259
260static VOID
261HEADER_DrawItemText(HDC hdc,HEADER_INFO* infoPtr,HEADER_ITEM* phdi,RECT* r,WCHAR* pszText,UINT uTextJustify,BOOL bEraseTextBkgnd,BOOL bHotTrack)
262{
263 if ((phdi->fmt & HDF_STRING) && (phdi->pszText))
264 {
265 INT oldBkMode = SetBkMode(hdc,TRANSPARENT);
266
267 if ((phdi->fmt & HDF_BITMAP_ON_RIGHT) || !(phdi->fmt & HDF_IMAGE)) r->left += TEXT_MARGIN;
268 if (!(phdi->fmt & HDF_BITMAP_ON_RIGHT)) r->right -= TEXT_MARGIN;
269 if (r->left >= r->right) return;
270
271 SetTextColor (hdc,GetSysColor(bHotTrack ? COLOR_HOTLIGHT:COLOR_BTNTEXT));
272 if (bEraseTextBkgnd)
273 {
274 HBRUSH hbrBk = GetSysColorBrush(COLOR_3DFACE);
275
276 FillRect(hdc,r,hbrBk);
277 }
278
279 DrawTextExW(hdc,pszText,lstrlenW(pszText),r,uTextJustify|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS,NULL);
280 if (oldBkMode != TRANSPARENT) SetBkMode(hdc,oldBkMode);
281 }
282}
283
284static INT
285HEADER_DrawItem (HWND hwnd, HDC hdc, INT iItem, BOOL bHotTrack,BOOL bEraseTextBkgnd)
286{
287 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
288 HEADER_ITEM *phdi = &infoPtr->items[iItem];
289 RECT r;
290
291 r = phdi->rect;
292 if (r.right - r.left == 0) return phdi->rect.right;
293
294 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS)
295 {
296 if (phdi->bDown)
297 {
298 DrawEdge (hdc,&r,BDR_RAISEDOUTER,BF_RECT | BF_FLAT | BF_MIDDLE | BF_ADJUST);
299 r.left += 2;
300 r.top += 2;
301 } else
302 DrawEdge(hdc,&r,EDGE_RAISED,BF_RECT | BF_SOFT | BF_MIDDLE | BF_ADJUST);
303 } else
304 DrawEdge(hdc,&r,EDGE_ETCHED, BF_BOTTOM | BF_RIGHT | BF_ADJUST);
305
306 if (r.left >= r.right) return phdi->rect.right;
307
308 if (phdi->fmt & HDF_OWNERDRAW)
309 {
310 DRAWITEMSTRUCT dis;
311 dis.CtlType = ODT_HEADER;
312 dis.CtlID = GetWindowLongA (hwnd, GWL_ID);
313 dis.itemID = iItem;
314 dis.itemAction = ODA_DRAWENTIRE;
315 dis.itemState = phdi->bDown ? ODS_SELECTED : 0;
316 dis.hwndItem = hwnd;
317 dis.hDC = hdc;
318 dis.rcItem = r;
319 dis.itemData = phdi->lParam;
320 SendMessageA (GetParent(hwnd),WM_DRAWITEM,(WPARAM)dis.CtlID,(LPARAM)&dis);
321 } else
322 {
323 UINT uTextJustify;
324 WCHAR *pszText;
325 BOOL mustFree = FALSE;
326
327 if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_CENTER)
328 uTextJustify = DT_CENTER;
329 else if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_RIGHT)
330 uTextJustify = DT_RIGHT;
331 else uTextJustify = DT_LEFT;
332
333 if (phdi->pszText == LPSTR_TEXTCALLBACKW)
334 pszText = HEADER_CallbackText(hwnd,infoPtr,phdi,iItem,&mustFree);
335 else
336 pszText = phdi->pszText;
337
338 if (!(phdi->fmt & HDF_JUSTIFYMASK) || (phdi->fmt & (HDF_LEFT | HDF_CENTER)))
339 {
340 HEADER_DrawItemImage(hwnd,hdc,infoPtr,phdi,&r,iItem);
341 if (r.left < r.right)
342 {
343 HEADER_DrawItemBitmap(hdc,infoPtr,phdi,&r,pszText,uTextJustify);
344 if (r.left < r.right)
345 HEADER_DrawItemText(hdc,infoPtr,phdi,&r,pszText,uTextJustify,bEraseTextBkgnd,bHotTrack);
346 }
347 } else
348 {
349 HEADER_DrawItemBitmap(hdc,infoPtr,phdi,&r,pszText,uTextJustify);
350 if (r.left < r.right)
351 {
352 HEADER_DrawItemImage(hwnd,hdc,infoPtr,phdi,&r,iItem);
353 if (r.left < r.right)
354 HEADER_DrawItemText(hdc,infoPtr,phdi,&r,pszText,uTextJustify,bEraseTextBkgnd,bHotTrack);
355 }
356 }
357 if (mustFree) COMCTL32_Free(pszText);
358 }
359
360 return phdi->rect.right;
361}
362
363static void
364HEADER_DrawTrackLine (HWND hwnd, HDC hdc, INT x)
365{
366 RECT rect;
367 HPEN hOldPen;
368 INT oldRop;
369
370 GetClientRect (hwnd, &rect);
371
372 rect.left = x;
373 rect.right = x+1;
374 InvertRect(hdc,&rect);
375}
376
377static void
378HEADER_Draw(HWND hwnd,HDC hdc)
379{
380 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
381 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
382 HFONT hFont, hOldFont;
383 RECT rect;
384 HBRUSH hbrBk;
385 INT i, x;
386 NMCUSTOMDRAW cdraw;
387 LRESULT cdctlres,cdres;
388
389 // get rect for the bar, adjusted for the border
390 GetClientRect (hwnd,&rect);
391
392 //Custom draw
393 cdraw.dwDrawStage = CDDS_PREPAINT;
394 cdraw.hdc = hdc;
395 cdraw.dwItemSpec = 0;
396 cdraw.uItemState = CDIS_DEFAULT;
397 cdraw.rc = rect;
398 cdraw.lItemlParam = 0;
399
400 cdctlres = sendNotify(hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
401
402 if (cdctlres & CDRF_SKIPDEFAULT) return;
403
404 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
405 hOldFont = SelectObject (hdc, hFont);
406
407 // draw Background
408 hbrBk = GetSysColorBrush(COLOR_3DFACE);
409 FillRect(hdc, &rect, hbrBk);
410
411 x = rect.left;
412 for (i = 0; i < infoPtr->uNumItem; i++)
413 {
414 if (cdctlres & CDRF_NOTIFYITEMDRAW)
415 {
416 cdraw.dwDrawStage = CDDS_ITEMPREPAINT;
417 cdraw.dwItemSpec = x;
418 cdraw.lItemlParam = infoPtr->items[x].lParam;
419 cdraw.rc = infoPtr->items[x].rect;
420
421 cdres = sendNotify(hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
422 } else cdres = 0;
423
424 if (!(cdres & CDRF_SKIPDEFAULT))
425 {
426 x = HEADER_DrawItem(hwnd,hdc,i,infoPtr->iHotItem == i,FALSE);
427 if (x > rect.right)
428 {
429 x = -1;
430 break;
431 }
432
433 if (cdctlres & CDRF_NOTIFYITEMDRAW)
434 {
435 cdraw.dwDrawStage = CDDS_ITEMPOSTPAINT;
436
437 sendNotify(hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
438 }
439 }
440 }
441
442 if ((x != -1) && (x <= rect.right) && (infoPtr->uNumItem > 0))
443 {
444 rect.left = x;
445 if (dwStyle & HDS_BUTTONS)
446 DrawEdge (hdc, &rect, EDGE_RAISED, BF_TOP|BF_LEFT|BF_BOTTOM|BF_SOFT);
447 else
448 DrawEdge (hdc, &rect, EDGE_ETCHED, BF_BOTTOM);
449 }
450
451 SelectObject (hdc, hOldFont);
452
453 if (infoPtr->bCaptured && infoPtr->bTracking && !(dwStyle & HDS_FULLDRAG)) HEADER_DrawTrackLine(hwnd,hdc,infoPtr->xOldTrack);
454
455 if (infoPtr->bDragDrop)
456 {
457 if ((infoPtr->iDragItem != infoPtr->iMoveItem) && (infoPtr->iDragItem != infoPtr->iMoveItem+1) && (infoPtr->iDragItem != -1))
458 {
459 INT x,y,width;
460 HPEN hPen = CreatePen(PS_DOT,0,GetSysColor(COLOR_HIGHLIGHT)),hOldPen;
461 INT oldBkMode = SetBkMode(hdc,TRANSPARENT);
462
463 hOldPen = SelectObject(hdc,hPen);
464 if (infoPtr->iDragItem == infoPtr->uNumItem)
465 {
466 x = infoPtr->items[infoPtr->uNumItem-1].rect.right-1;
467 width = 2;
468 } else if (infoPtr->iDragItem == 0)
469 {
470 x = infoPtr->items[0].rect.left;
471 width = 1;
472 } else
473 {
474 x = infoPtr->items[infoPtr->iDragItem].rect.left-2;
475 width = 3;
476 }
477
478 for (y = 0;y < width;y++)
479 {
480 MoveToEx(hdc,x,0,NULL);
481 LineTo(hdc,x,rect.bottom);
482 x++;
483 }
484 SetBkMode(hdc,oldBkMode);
485 SelectObject(hdc,hOldPen);
486 DeleteObject(hPen);
487 }
488 ImageList_Draw(infoPtr->dragImage,0,hdc,infoPtr->items[infoPtr->iMoveItem].rect.left+infoPtr->dragPos.x-infoPtr->dragStart.x,0,ILD_NORMAL);
489 }
490
491 if (cdctlres & CDRF_NOTIFYPOSTPAINT)
492 {
493 cdraw.dwDrawStage = CDDS_POSTPAINT;
494 cdraw.dwItemSpec = 0;
495 GetClientRect(hwnd,&cdraw.rc);
496
497 sendNotify(hwnd,NM_CUSTOMDRAW,&cdraw.hdr);
498 }
499}
500
501
502static void
503HEADER_RefreshItem (HWND hwnd, HDC hdc, INT iItem)
504{
505 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
506 HFONT hFont, hOldFont;
507
508 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
509 hOldFont = SelectObject (hdc, hFont);
510 HEADER_DrawItem(hwnd,hdc,iItem,infoPtr->iHotItem == iItem,TRUE);
511 SelectObject (hdc, hOldFont);
512}
513
514static void
515HEADER_Refresh(HWND hwnd)
516{
517 HDC hdc,hdcCompatible;
518 HBITMAP bitmap,oldbmp;
519 RECT rect;
520
521 GetClientRect(hwnd,&rect);
522 hdc = GetDC(hwnd);
523 hdcCompatible = CreateCompatibleDC(hdc);
524 bitmap = CreateCompatibleBitmap(hdc,rect.right,rect.bottom);
525 oldbmp = SelectObject(hdcCompatible,bitmap);
526 HEADER_Draw(hwnd,hdcCompatible);
527 BitBlt(hdc,0,0,rect.right,rect.bottom,hdcCompatible,0,0,SRCCOPY);
528 SelectObject(hdcCompatible,oldbmp);
529 DeleteObject(bitmap);
530 DeleteDC(hdcCompatible);
531 ReleaseDC(hwnd,hdc);
532}
533
534static void
535HEADER_SetItemBounds(HWND hwnd,INT start)
536{
537 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
538 HEADER_ITEM *phdi;
539 RECT rect;
540 int i, x;
541
542 if (infoPtr->uNumItem == 0) return;
543
544 GetClientRect(hwnd,&rect);
545
546 x = (start > 0) ? infoPtr->items[start-1].rect.right:rect.left;
547 for (i = start;i < infoPtr->uNumItem;i++)
548 {
549 phdi = &infoPtr->items[i];
550 phdi->rect.top = rect.top;
551 phdi->rect.bottom = rect.bottom;
552 phdi->rect.left = x;
553 phdi->rect.right = phdi->rect.left + phdi->cxy;
554 x = phdi->rect.right;
555 }
556}
557
558static void
559HEADER_InternalHitTest (HWND hwnd, LPPOINT lpPt, UINT *pFlags, INT *pItem)
560{
561 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
562 RECT rect, rcTest;
563 INT iCount, width,widthCount = 0;
564 BOOL bNoWidth;
565
566 GetClientRect (hwnd, &rect);
567
568 *pFlags = 0;
569 bNoWidth = FALSE;
570 if (PtInRect(&rect,*lpPt))
571 {
572 if (infoPtr->uNumItem == 0)
573 {
574 *pFlags |= HHT_NOWHERE;
575 *pItem = 1;
576// TRACE (header, "NOWHERE\n");
577 return;
578 } else
579 {
580 /* somewhere inside */
581 for (iCount = 0; iCount < infoPtr->uNumItem; iCount++)
582 {
583 rect = infoPtr->items[iCount].rect;
584 width = rect.right - rect.left;
585 if (width == 0)
586 {
587 bNoWidth = TRUE;
588 widthCount = 0;
589 continue;
590 } else widthCount++;
591 if (widthCount > 1) bNoWidth = FALSE;
592 if (PtInRect(&rect,*lpPt))
593 {
594 if (width <= 2 * DIVIDER_WIDTH)
595 {
596 *pFlags |= HHT_ONHEADER;
597 *pItem = iCount;
598// TRACE (header, "ON HEADER %d\n", iCount);
599 return;
600 }
601 if (iCount > 0)
602 {
603 rcTest = rect;
604 rcTest.right = rcTest.left + DIVIDER_WIDTH;
605 if (PtInRect (&rcTest, *lpPt))
606 {
607 if (bNoWidth)
608 {
609 *pFlags |= HHT_ONDIVOPEN;
610 *pItem = iCount - 1;
611// TRACE (header, "ON DIVOPEN %d\n", *pItem);
612 return;
613 } else
614 {
615 *pFlags |= HHT_ONDIVIDER;
616 *pItem = iCount - 1;
617// TRACE (header, "ON DIVIDER %d\n", *pItem);
618 return;
619 }
620 }
621 }
622 rcTest = rect;
623 rcTest.left = rcTest.right - DIVIDER_WIDTH;
624 if (PtInRect (&rcTest, *lpPt))
625 {
626 *pFlags |= HHT_ONDIVIDER;
627 *pItem = iCount;
628// TRACE (header, "ON DIVIDER %d\n", *pItem);
629 return;
630 }
631
632 *pFlags |= HHT_ONHEADER;
633 *pItem = iCount;
634// TRACE (header, "ON HEADER %d\n", iCount);
635 return;
636 }
637 }
638
639 /* check for last divider part (on nowhere) */
640 rect = infoPtr->items[infoPtr->uNumItem-1].rect;
641 rect.left = rect.right;
642 rect.right += DIVIDER_WIDTH;
643 if (widthCount > 0) bNoWidth = FALSE;
644 if (PtInRect (&rect, *lpPt))
645 {
646 if (bNoWidth)
647 {
648 *pFlags |= HHT_ONDIVOPEN;
649 *pItem = infoPtr->uNumItem - 1;
650// TRACE (header, "ON DIVOPEN %d\n", *pItem);
651 return;
652 } else
653 {
654 *pFlags |= HHT_ONDIVIDER;
655 *pItem = infoPtr->uNumItem-1;
656// TRACE (header, "ON DIVIDER %d\n", *pItem);
657 return;
658 }
659 }
660
661 *pFlags |= HHT_NOWHERE;
662 *pItem = 1;
663// TRACE (header, "NOWHERE\n");
664 return;
665 }
666 } else
667 {
668 if (lpPt->x < rect.left)
669 {
670// TRACE (header, "TO LEFT\n");
671 *pFlags |= HHT_TOLEFT;
672 } else if (lpPt->x > rect.right)
673 {
674// TRACE (header, "TO LEFT\n");
675 *pFlags |= HHT_TORIGHT;
676 }
677
678 if (lpPt->y < rect.top)
679 {
680// TRACE (header, "ABOVE\n");
681 *pFlags |= HHT_ABOVE;
682 } else if (lpPt->y > rect.bottom)
683 {
684// TRACE (header, "BELOW\n");
685 *pFlags |= HHT_BELOW;
686 }
687 }
688
689 *pItem = 1;
690// TRACE (header, "flags=0x%X\n", *pFlags);
691 return;
692}
693
694static BOOL HEADER_SendHeaderNotify(HWND hwnd,UINT code,INT iItem,INT iButton,BOOL unicode)
695{
696 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
697 NMHEADERW nmhdr;
698 HDITEMW nmitem;
699 char* text = NULL;
700 BOOL res;
701
702
703 if (unicode)
704 {
705 nmitem.pszText = infoPtr->items[iItem].pszText;
706 } else
707 {
708 if (infoPtr->items[iItem].pszText)
709 {
710 INT len = lstrlenW(infoPtr->items[iItem].pszText);
711
712 if (len > 0)
713 {
714 text = (CHAR*)COMCTL32_Alloc(len+1);
715 lstrcpyWtoA(text,infoPtr->items[iItem].pszText);
716 }
717 }
718 nmitem.pszText = (LPWSTR)text;
719 }
720
721 nmhdr.iItem = iItem;
722 nmhdr.iButton = 0;
723 nmhdr.pitem = &nmitem;
724
725 nmitem.mask = 0;
726 nmitem.cxy = infoPtr->items[iItem].cxy;
727 nmitem.hbm = infoPtr->items[iItem].hbm;
728 nmitem.cchTextMax = infoPtr->items[iItem].cchTextMax;
729 nmitem.fmt = infoPtr->items[iItem].fmt;
730 nmitem.lParam = infoPtr->items[iItem].lParam;
731 nmitem.iImage = infoPtr->items[iItem].iImage;
732 nmitem.iOrder = infoPtr->items[iItem].iOrder;
733 nmitem.type = infoPtr->items[iItem].type;
734 nmitem.pvFilter = infoPtr->items[iItem].pvFilter;
735
736 res = (BOOL)sendNotify(hwnd,code,&nmhdr.hdr);
737
738 if (text) COMCTL32_Free(text);
739
740 return res;
741}
742
743static BOOL HEADER_SendItemChanging(HWND hwnd,INT iItem)
744{
745 BOOL unicode = isUnicodeNotify(hwnd);
746
747 return HEADER_SendHeaderNotify(hwnd,unicode ? HDN_ITEMCHANGINGW:HDN_ITEMCHANGINGA,iItem,0,unicode);
748}
749
750static BOOL HEADER_SendItemChanged(HWND hwnd,INT iItem)
751{
752 BOOL unicode = isUnicodeNotify(hwnd);
753
754 return HEADER_SendHeaderNotify(hwnd,unicode ? HDN_ITEMCHANGEDW:HDN_ITEMCHANGEDA,iItem,0,unicode);
755}
756
757static BOOL HEADER_SendItemDblClick(HWND hwnd,INT iItem,INT iButton)
758{
759 BOOL unicode = isUnicodeNotify(hwnd);
760
761 return HEADER_SendHeaderNotify(hwnd,unicode ? HDN_ITEMDBLCLICKW:HDN_ITEMDBLCLICKA,iItem,iButton,unicode);
762}
763
764static BOOL HEADER_SendDividerDblClick(HWND hwnd,INT iItem,INT iButton)
765{
766 BOOL unicode = isUnicodeNotify(hwnd);
767
768 return HEADER_SendHeaderNotify(hwnd,unicode ? HDN_DIVIDERDBLCLICKW:HDN_DIVIDERDBLCLICKA,iItem,iButton,unicode);
769}
770
771static BOOL HEADER_SendBeginTrack(HWND hwnd,INT iItem,INT iButton)
772{
773 BOOL unicode = isUnicodeNotify(hwnd);
774
775 return HEADER_SendHeaderNotify(hwnd,unicode ? HDN_BEGINTRACKW:HDN_BEGINTRACKA,iItem,iButton,unicode);
776}
777
778static BOOL HEADER_SendEndTrack(HWND hwnd,INT iItem,INT iButton)
779{
780 BOOL unicode = isUnicodeNotify(hwnd);
781
782 return HEADER_SendHeaderNotify(hwnd,unicode ? HDN_ENDTRACKW:HDN_ENDTRACKA,iItem,iButton,unicode);
783}
784
785static BOOL HEADER_SendTrack(HWND hwnd,INT iItem)
786{
787 BOOL unicode = isUnicodeNotify(hwnd);
788
789 return HEADER_SendHeaderNotify(hwnd,unicode ? HDN_TRACKW:HDN_TRACKA,iItem,0,unicode);
790}
791
792static BOOL HEADER_SendClickNotify(HWND hwnd,UINT code,INT iItem,INT iButton,BOOL unicode)
793{
794 NMHEADERW nmhdr;
795
796 nmhdr.iItem = iItem;
797 nmhdr.iButton = iButton;
798 nmhdr.pitem = NULL;
799
800 return (BOOL)sendNotify(hwnd,code,&nmhdr.hdr);
801}
802
803static BOOL HEADER_SendItemClick(HWND hwnd,INT iItem,INT iButton)
804{
805 BOOL unicode = isUnicodeNotify(hwnd);
806
807 return HEADER_SendClickNotify(hwnd,unicode ? HDN_ITEMCLICKW:HDN_ITEMCLICKA,iItem,iButton,unicode);
808}
809
810static BOOL HEADER_SendDragNotify(HWND hwnd,UINT code,INT iItem,INT iButton)
811{
812 NMHEADERW nmhdr;
813
814 nmhdr.iItem = iItem;
815 nmhdr.iButton = iButton;
816 nmhdr.pitem = NULL;
817
818 return (BOOL)sendNotify(hwnd,code,&nmhdr.hdr);
819}
820
821static BOOL HEADER_SendFilterBtnClick(HWND hwnd,INT iItem,RECT iRect)
822{
823 NMHDFILTERBTNCLICK nmhdr;
824
825 nmhdr.iItem = iItem;
826 nmhdr.rc = iRect;
827
828 return (BOOL)sendNotify(hwnd,HDN_FILTERBTNCLICK,&nmhdr.hdr);
829}
830
831static BOOL
832HEADER_SendFilterChange(HWND hwnd,INT iItem)
833{
834 NMHEADERW nmhdr;
835
836 nmhdr.iItem = iItem;
837 nmhdr.iButton = 0;
838 nmhdr.pitem = NULL;
839
840 return (BOOL)sendNotify(hwnd,HDN_FILTERCHANGE,&nmhdr.hdr);
841}
842
843static LRESULT
844HEADER_ClearFilter(HWND hwnd,WPARAM wParam,LPARAM lParam)
845{
846 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
847 INT iItem = (INT)lParam;
848
849 if (iItem == -1)
850 {
851 INT x;
852
853 for (x = 0;x < infoPtr->uNumItem;x++)
854 {
855 //CB:todo
856 }
857 } else
858 {
859 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return iItem;
860
861 //CB:todo
862 }
863
864 HEADER_SendFilterChange(hwnd,-1);
865
866 return iItem;
867}
868
869static LRESULT
870HEADER_EditFilter(HWND hwnd,WPARAM wParam,LPARAM lParam)
871{
872 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
873 INT iItem = (INT)wParam;
874
875 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return 0;
876
877 if (!lParam)
878 {
879 //CB: save changes
880
881 HEADER_SendFilterChange(hwnd,iItem);
882 }
883
884 //CB: todo
885
886 return iItem;
887}
888
889static LRESULT
890HEADER_SetFilterChangeTimeout(HWND hwnd,WPARAM wParam,LPARAM lParam)
891{
892 //CB: todo
893
894 return 0;
895}
896
897static LRESULT
898HEADER_CreateDragImage(HWND hwnd,WPARAM wParam,LPARAM lParam)
899{
900 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
901 INT iItem = (INT)wParam;
902 HEADER_ITEM *phdi;
903 RECT oldRect;
904 HDC hdc,hdcBmp;
905 HBITMAP bmp,mask,oldbmp;
906 HBRUSH hbr;
907 HFONT hFont,hOldFont;
908 HIMAGELIST himl;
909
910 if (iItem < 0 || iItem >= (INT)infoPtr->uNumItem) return 0;
911
912 phdi = &infoPtr->items[iItem];
913 oldRect = phdi->rect;
914 phdi->rect.right -= phdi->rect.left;
915 phdi->rect.left = 0;
916
917 hdc = GetDC(hwnd);
918 hFont = infoPtr->hFont ? infoPtr->hFont:GetStockObject(SYSTEM_FONT);
919 hOldFont = SelectObject(hdc,hFont);
920 hdcBmp = CreateCompatibleDC(hdc);
921 bmp = CreateCompatibleBitmap(hdc,phdi->rect.right,phdi->rect.bottom);
922 mask = CreateCompatibleBitmap(hdc,phdi->rect.right,phdi->rect.bottom);
923 oldbmp = SelectObject(hdcBmp,bmp);
924 HEADER_DrawItem(hwnd,hdcBmp,iItem,FALSE,TRUE);
925 SelectObject(hdcBmp,mask);
926 hbr = CreateSolidBrush(RGB(255,255,255));
927 FillRect(hdcBmp,&phdi->rect,hbr);
928 DeleteObject(hbr);
929 hbr = CreateHatchBrush(HS_DIAGCROSS,RGB(0,0,0));
930 FillRect(hdcBmp,&phdi->rect,hbr);
931 DeleteObject(hbr);
932 SelectObject(hdcBmp,oldbmp);
933
934 himl = ImageList_Create(phdi->rect.right,phdi->rect.bottom,ILC_COLOR | ILC_MASK,1,0);
935 ImageList_Add(himl,bmp,mask);
936
937 DeleteObject(bmp);
938 DeleteObject(mask);
939 SelectObject(hdc,hOldFont);
940 DeleteDC(hdcBmp);
941 ReleaseDC(hwnd,hdc);
942 phdi->rect = oldRect;
943
944 return (LRESULT)himl;
945}
946
947static LRESULT
948HEADER_SetHotDivider(HWND hwnd,WPARAM wParam,LPARAM lParam)
949{
950 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
951
952 if (wParam)
953 {
954 POINT pt;
955
956 pt.x = LOWORD(lParam);
957 pt.y = HIWORD(lParam);
958
959 //CB: todo
960 } else
961 {
962 //CB: todo
963 }
964
965 return 0;
966}
967
968static LRESULT
969HEADER_DeleteItem (HWND hwnd, WPARAM wParam)
970{
971 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
972 INT iItem = (INT)wParam;
973 HDC hdc;
974
975// TRACE(header, "[iItem=%d]\n", iItem);
976
977 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return FALSE;
978
979 if (infoPtr->uNumItem == 1)
980 {
981 //clear
982 if (infoPtr->items[0].pszText) COMCTL32_Free(infoPtr->items[0].pszText);
983 COMCTL32_Free (infoPtr->items);
984 infoPtr->items = 0;
985 infoPtr->uNumItem = 0;
986
987 InvalidateRect(hwnd,NULL,TRUE);
988 } else
989 {
990 HEADER_ITEM *oldItems = infoPtr->items;
991// TRACE(header, "Complex delete! [iItem=%d]\n", iItem);
992
993 if (infoPtr->items[iItem].pszText) COMCTL32_Free(infoPtr->items[iItem].pszText);
994
995 infoPtr->uNumItem--;
996 infoPtr->items = (HEADER_ITEM*)COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
997 /* pre delete copy */
998 if (iItem > 0)
999 memcpy (&infoPtr->items[0], &oldItems[0],iItem*sizeof(HEADER_ITEM));
1000
1001 /* post delete copy */
1002 if (iItem < infoPtr->uNumItem)
1003 memcpy (&infoPtr->items[iItem],&oldItems[iItem+1],(infoPtr->uNumItem-iItem)*sizeof(HEADER_ITEM));
1004
1005 COMCTL32_Free(oldItems);
1006
1007 if (iItem < infoPtr->uNumItem) HEADER_SetItemBounds(hwnd,iItem);
1008
1009 HEADER_Refresh(hwnd);
1010
1011 }
1012
1013 return TRUE;
1014}
1015
1016static LRESULT
1017HEADER_GetBitmapMargin(HWND hwnd,WPARAM wParam,LPARAM lParam)
1018{
1019 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1020
1021 return infoPtr->xBmpMargin;
1022}
1023
1024static LRESULT
1025HEADER_SetBitmapMargin(HWND hwnd,WPARAM wParam,LPARAM lParam)
1026{
1027 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1028 INT oldMargin = infoPtr->xBmpMargin;
1029
1030 if (infoPtr->xBmpMargin != (INT)wParam)
1031 {
1032 infoPtr->xBmpMargin = (INT)wParam;
1033 HEADER_Refresh(hwnd);
1034 }
1035
1036 return oldMargin;
1037}
1038
1039static LRESULT
1040HEADER_GetImageList (HWND hwnd)
1041{
1042 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1043
1044 return (LRESULT)infoPtr->himl;
1045}
1046
1047
1048static LRESULT HEADER_GetItem(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL unicode)
1049{
1050 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1051 HDITEMW *phdi = (HDITEMW*)lParam;
1052 INT nItem = (INT)wParam;
1053 HEADER_ITEM *lpItem;
1054
1055 if (!phdi) return FALSE;
1056 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) return FALSE;
1057
1058 if (phdi->mask == 0) return TRUE;
1059
1060 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1061
1062 if (phdi->mask & HDI_BITMAP) phdi->hbm = lpItem->hbm;
1063
1064 if (phdi->mask & HDI_FORMAT) phdi->fmt = lpItem->fmt;
1065
1066 if (phdi->mask & HDI_FILTER)
1067 {
1068 phdi->type = lpItem->type;
1069 phdi->pvFilter = lpItem->pvFilter;
1070 }
1071
1072 if (phdi->mask & (HDI_WIDTH | HDI_HEIGHT)) phdi->cxy = lpItem->cxy;
1073
1074 if (phdi->mask & HDI_IMAGE) phdi->iImage = lpItem->iImage;
1075
1076 if (phdi->mask & HDI_LPARAM) phdi->lParam = lpItem->lParam;
1077
1078 if (phdi->mask & HDI_ORDER) phdi->iOrder = lpItem->iOrder;
1079
1080 if (phdi->mask & HDI_TEXT)
1081 {
1082 if (lpItem->pszText != LPSTR_TEXTCALLBACKW)
1083 {
1084 if (lpItem->pszText)
1085 {
1086 if (unicode)
1087 lstrcpynW (phdi->pszText,lpItem->pszText,phdi->cchTextMax);
1088 else
1089 lstrcpynWtoA((LPSTR)phdi->pszText,lpItem->pszText,phdi->cchTextMax);
1090 } else phdi->pszText = NULL;
1091 } else
1092 {
1093 phdi->pszText = unicode ? LPSTR_TEXTCALLBACKW:(LPWSTR)LPSTR_TEXTCALLBACKA;
1094 }
1095 }
1096
1097 return TRUE;
1098}
1099
1100static LRESULT
1101HEADER_GetItemCount (HWND hwnd)
1102{
1103 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1104
1105 return infoPtr->uNumItem;
1106}
1107
1108
1109LRESULT HEADER_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1110{
1111 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1112 INT iItem = (INT)wParam;
1113 LPRECT lpRect = (LPRECT)lParam;
1114
1115 if (!lpRect || (iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return FALSE;
1116
1117 lpRect->left = infoPtr->items[iItem].rect.left;
1118 lpRect->right = infoPtr->items[iItem].rect.right;
1119 lpRect->top = infoPtr->items[iItem].rect.top;
1120 lpRect->bottom = infoPtr->items[iItem].rect.bottom;
1121
1122 return TRUE;
1123}
1124
1125//useful function for ListView control
1126
1127DWORD HEADER_GetExpandedColumnTextWidth(HWND hwnd,INT iItem)
1128{
1129 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1130 INT width = 0;
1131 HEADER_ITEM *phdi;
1132
1133 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return width;
1134
1135 phdi = &infoPtr->items[iItem];
1136
1137 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS)
1138 width += 4;
1139 else
1140 width += 2;
1141
1142 if (phdi->fmt & HDF_OWNERDRAW)
1143 {
1144 //can't calculate ownerdraw
1145 return infoPtr->items[iItem].rect.right-infoPtr->items[iItem].rect.left;
1146 }
1147
1148 if (phdi->fmt & HDF_BITMAP)
1149 {
1150 if (phdi->hbm)
1151 {
1152 BITMAP bmp;
1153
1154 GetObjectA (phdi->hbm,sizeof(BITMAP),(LPVOID)&bmp);
1155
1156 width += bmp.bmWidth+2*infoPtr->xBmpMargin;
1157 } else width += 2*infoPtr->xBmpMargin;
1158 }
1159
1160 if (phdi->fmt & HDF_IMAGE)
1161 {
1162 INT iImage;
1163 IMAGEINFO info;
1164
1165 if (phdi->iImage == I_IMAGECALLBACK)
1166 iImage = HEADER_CallbackImage(hwnd,infoPtr,phdi,iItem);
1167 else
1168 iImage = phdi->iImage;
1169
1170 if (iImage != I_IMAGENONE)
1171 {
1172 if (ImageList_GetImageInfo(infoPtr->himl,phdi->iImage,&info))
1173 {
1174 width += info.rcImage.right-info.rcImage.left+2*infoPtr->xBmpMargin;
1175 }
1176 }
1177 }
1178
1179 if (phdi->fmt & HDF_STRING)
1180 {
1181 WCHAR* pszText;
1182 BOOL mustFree = FALSE;
1183 HFONT hFont,hOldFont;
1184 SIZE size;
1185 HDC hdc = GetDC(hwnd);
1186
1187 if (phdi->pszText == LPSTR_TEXTCALLBACKW)
1188 pszText = HEADER_CallbackText(hwnd,infoPtr,phdi,iItem,&mustFree);
1189 else
1190 pszText = phdi->pszText;
1191
1192 hFont = infoPtr->hFont ? infoPtr->hFont:GetStockObject(SYSTEM_FONT);
1193 hOldFont = SelectObject(hdc,hFont);
1194
1195 if (GetTextExtentPoint32W(hdc,pszText,lstrlenW(pszText),&size))
1196 width += size.cx+2*TEXT_MARGIN;
1197 if (mustFree) COMCTL32_Free(pszText);
1198 SelectObject(hdc,hOldFont);
1199 ReleaseDC(hwnd,hdc);
1200 }
1201
1202 return width;
1203}
1204
1205static BOOL
1206HEADER_CheckOrderArray(HEADER_INFO* infoPtr,LPINT lpiArray)
1207{
1208 INT x,y;
1209
1210 for (x = 0;x < infoPtr->uNumItem;x++)
1211 {
1212 BOOL found = FALSE;
1213
1214 for (y = 0;y <= x;y++)
1215 if (infoPtr->items[y].iOrder == lpiArray[x]) found = TRUE;
1216 for (y = x+1;y < infoPtr->uNumItem;y++)
1217 {
1218 if (infoPtr->items[x].iOrder == infoPtr->items[y].iOrder || lpiArray[x] == lpiArray[y]) return FALSE;
1219 if (infoPtr->items[y].iOrder == lpiArray[x]) found = TRUE;
1220 }
1221
1222 if (!found) return FALSE;
1223 }
1224
1225 return TRUE;
1226}
1227
1228static LRESULT
1229HEADER_GetOrderArray(HWND hwnd,WPARAM wParam,LPARAM lParam)
1230{
1231 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1232 LPINT lpiArray = (LPINT)lParam;
1233 INT x;
1234
1235 if (wParam != infoPtr->uNumItem || !lpiArray || !HEADER_CheckOrderArray(infoPtr,lpiArray)) return FALSE;
1236
1237 for (x = 0;x < infoPtr->uNumItem;x++) lpiArray[x] = infoPtr->items[x].iOrder;
1238
1239 return TRUE;
1240}
1241
1242static LRESULT
1243HEADER_SetOrderArray(HWND hwnd,WPARAM wParam,LPARAM lParam)
1244{
1245 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1246 LPINT lpiArray = (LPINT)lParam;
1247 HEADER_ITEM* newItems;
1248 INT x,y;
1249
1250 if (wParam != infoPtr->uNumItem || !lpiArray || !HEADER_CheckOrderArray(infoPtr,lpiArray)) return FALSE;
1251 if (infoPtr->uNumItem <= 1) return TRUE;
1252
1253 newItems = (HEADER_ITEM*)COMCTL32_Alloc(infoPtr->uNumItem*sizeof(HEADER_ITEM));
1254 for (x = 0;x < infoPtr->uNumItem;x++)
1255 for (y = 0;y < infoPtr->uNumItem;y++)
1256 if (infoPtr->items[y].iOrder == lpiArray[x]) memcpy(&newItems[x],&infoPtr->items[y],sizeof(HEADER_ITEM));
1257 COMCTL32_Free(infoPtr->items);
1258 infoPtr->items = newItems;
1259
1260 HEADER_SetItemBounds(hwnd,0);
1261 HEADER_Refresh(hwnd);
1262
1263 return TRUE;
1264}
1265
1266static LRESULT
1267HEADER_OrderToIndex(HWND hwnd,WPARAM wParam,LPARAM lParam)
1268{
1269 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1270 INT iOrder = (INT)wParam;
1271 INT x;
1272
1273 for (x = 0;x < infoPtr->uNumItem;x++)
1274 if (infoPtr->items[x].iOrder == iOrder) return x;
1275
1276 return iOrder;
1277}
1278
1279static LRESULT
1280HEADER_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1281{
1282 LPHDHITTESTINFO phti = (LPHDHITTESTINFO)lParam;
1283
1284 HEADER_InternalHitTest (hwnd, &phti->pt, &phti->flags, &phti->iItem);
1285
1286 return phti->iItem;
1287}
1288
1289
1290static LRESULT HEADER_InsertItem(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL unicode)
1291{
1292 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1293 HDITEMW *phdi = (HDITEMW*)lParam;
1294 INT nItem = (INT)wParam;
1295 HEADER_ITEM *lpItem;
1296
1297 if ((phdi == NULL) || (nItem < 0)) return -1;
1298
1299 if (nItem > infoPtr->uNumItem) nItem = infoPtr->uNumItem;
1300
1301 if (infoPtr->uNumItem == 0)
1302 {
1303 infoPtr->items = (HEADER_ITEM*)COMCTL32_Alloc(sizeof(HEADER_ITEM));
1304 infoPtr->uNumItem++;
1305 } else
1306 {
1307 HEADER_ITEM *oldItems = infoPtr->items;
1308
1309 infoPtr->uNumItem++;
1310 infoPtr->items = (HEADER_ITEM*)COMCTL32_Alloc(sizeof(HEADER_ITEM)*infoPtr->uNumItem);
1311 if (nItem == 0)
1312 memcpy (&infoPtr->items[1],&oldItems[0],(infoPtr->uNumItem-1)*sizeof(HEADER_ITEM));
1313 else
1314 {
1315 /* pre insert copy */
1316 memcpy (&infoPtr->items[0],&oldItems[0],nItem*sizeof(HEADER_ITEM));
1317
1318 /* post insert copy */
1319 if (nItem < infoPtr->uNumItem-1)
1320 memcpy (&infoPtr->items[nItem+1],&oldItems[nItem],(infoPtr->uNumItem - nItem)*sizeof(HEADER_ITEM));
1321 }
1322
1323 COMCTL32_Free (oldItems);
1324 }
1325
1326 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1327 lpItem->bDown = FALSE;
1328
1329 lpItem->cxy = ((phdi->mask & HDI_WIDTH) || (phdi->mask & HDI_HEIGHT)) ? phdi->cxy:0;
1330
1331 if (phdi->mask & HDI_TEXT)
1332 {
1333 if (!phdi->pszText) lpItem->pszText = NULL;
1334 else if (unicode)
1335 {
1336 if (phdi->pszText != LPSTR_TEXTCALLBACKW)
1337 {
1338 INT len;
1339
1340 len = lstrlenW(phdi->pszText);
1341 if (len == 0) lpItem->pszText = NULL; else
1342 {
1343 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1344 lstrcpyW(lpItem->pszText,phdi->pszText);
1345 }
1346 } else lpItem->pszText = LPSTR_TEXTCALLBACKW;
1347 } else
1348 {
1349 if ((LPSTR)phdi->pszText != LPSTR_TEXTCALLBACKA)
1350 {
1351 INT len;
1352
1353 len = lstrlenA((LPSTR)phdi->pszText);
1354 if (len == 0) lpItem->pszText = NULL; else
1355 {
1356 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1357 lstrcpyAtoW(lpItem->pszText,(LPSTR)phdi->pszText);
1358 }
1359 } else lpItem->pszText = LPSTR_TEXTCALLBACKW;
1360 }
1361 lpItem->cchTextMax = phdi->cchTextMax;
1362 } else
1363 {
1364 lpItem->pszText = NULL;
1365 lpItem->cchTextMax = 0;
1366 }
1367
1368 lpItem->fmt = (phdi->mask & HDI_FORMAT) ? phdi->fmt:HDF_LEFT;
1369 if (lpItem->fmt == 0) lpItem->fmt = HDF_LEFT;
1370
1371 lpItem->lParam = (phdi->mask & HDI_LPARAM) ? phdi->lParam:0;
1372
1373 lpItem->iImage = (phdi->mask & HDI_IMAGE) ? phdi->iImage:0;
1374
1375 lpItem->iOrder = (phdi->mask & HDI_ORDER) ? phdi->iOrder:-1;
1376
1377 lpItem->hbm = (phdi->mask & HDI_BITMAP) ? phdi->hbm:0;
1378
1379 if (phdi->mask & HDI_FILTER)
1380 {
1381 lpItem->type = phdi->type;
1382 lpItem->pvFilter = phdi->pvFilter;
1383 }
1384
1385 HEADER_SetItemBounds (hwnd,nItem);
1386 HEADER_Refresh(hwnd);
1387
1388 return nItem;
1389}
1390
1391static LRESULT
1392HEADER_Layout (HWND hwnd, WPARAM wParam, LPARAM lParam)
1393{
1394 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1395 LPHDLAYOUT lpLayout = (LPHDLAYOUT)lParam;
1396
1397 if (!lpLayout) return FALSE;
1398
1399 lpLayout->pwpos->hwnd = hwnd;
1400 lpLayout->pwpos->hwndInsertAfter = 0;
1401 lpLayout->pwpos->x = lpLayout->prc->left;
1402 lpLayout->pwpos->y = lpLayout->prc->top;
1403 lpLayout->pwpos->cx = lpLayout->prc->right - lpLayout->prc->left;
1404 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_HIDDEN)
1405 lpLayout->pwpos->cy = 0;
1406 else
1407 lpLayout->pwpos->cy = infoPtr->nHeight;
1408 lpLayout->pwpos->flags = SWP_NOZORDER;
1409
1410// TRACE (header, "Layout x=%d y=%d cx=%d cy=%d\n",
1411// lpLayout->pwpos->x, lpLayout->pwpos->y,
1412// lpLayout->pwpos->cx, lpLayout->pwpos->cy);
1413
1414 return TRUE;
1415}
1416
1417
1418static LRESULT
1419HEADER_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1420{
1421 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1422 HIMAGELIST himlOld;
1423
1424 himlOld = infoPtr->himl;
1425 infoPtr->himl = (HIMAGELIST)lParam;
1426
1427 HEADER_Refresh(hwnd);
1428
1429 return (LRESULT)himlOld;
1430}
1431
1432
1433static LRESULT HEADER_SetItem(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL unicode)
1434{
1435 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1436 HDITEMW *phdi = (HDITEMW*)lParam;
1437 INT nItem = (INT)wParam;
1438 HEADER_ITEM *lpItem;
1439 HDC hdc;
1440
1441 if (phdi == NULL) return FALSE;
1442 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) return FALSE;
1443 if (phdi->mask == 0) return TRUE;
1444
1445 if (HEADER_SendItemChanging(hwnd,nItem)) return FALSE;
1446
1447 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1448
1449 if (phdi->mask & HDI_BITMAP) lpItem->hbm = phdi->hbm;
1450
1451 if (phdi->mask & HDI_FORMAT) lpItem->fmt = phdi->fmt;
1452
1453 if (phdi->mask & HDI_FILTER)
1454 {
1455 lpItem->type = lpItem->type;
1456 lpItem->pvFilter = lpItem->pvFilter;
1457 }
1458
1459 if (phdi->mask & (HDI_WIDTH | HDI_WIDTH)) lpItem->cxy = phdi->cxy;
1460
1461 if (phdi->mask & HDI_IMAGE) lpItem->iImage = phdi->iImage;
1462
1463 if (phdi->mask & HDI_LPARAM) lpItem->lParam = phdi->lParam;
1464
1465 if (phdi->mask & HDI_ORDER) lpItem->iOrder = phdi->iOrder;
1466
1467 if (phdi->mask & HDI_TEXT)
1468 {
1469 if (unicode)
1470 {
1471 if (phdi->pszText != LPSTR_TEXTCALLBACKW)
1472 {
1473 if (lpItem->pszText)
1474 {
1475 COMCTL32_Free(lpItem->pszText);
1476 lpItem->pszText = NULL;
1477 }
1478 if (phdi->pszText)
1479 {
1480 INT len = lstrlenW(phdi->pszText);
1481
1482 if (len)
1483 {
1484 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1485 lstrcpyW(lpItem->pszText,phdi->pszText);
1486 }
1487 }
1488 } else
1489 {
1490 if (lpItem->pszText != LPSTR_TEXTCALLBACKW) COMCTL32_Free(lpItem->pszText);
1491 lpItem->pszText = LPSTR_TEXTCALLBACKW;
1492 }
1493 } else
1494 {
1495 if ((LPSTR)phdi->pszText != LPSTR_TEXTCALLBACKA)
1496 {
1497 if (lpItem->pszText)
1498 {
1499 COMCTL32_Free (lpItem->pszText);
1500 lpItem->pszText = NULL;
1501 }
1502 if (phdi->pszText)
1503 {
1504 INT len = lstrlenA((LPSTR)phdi->pszText);
1505
1506 if (len)
1507 {
1508 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1509 lstrcpyAtoW(lpItem->pszText,(LPSTR)phdi->pszText);
1510 }
1511 }
1512 } else
1513 {
1514 if (lpItem->pszText != LPSTR_TEXTCALLBACKW) COMCTL32_Free(lpItem->pszText);
1515 lpItem->pszText = LPSTR_TEXTCALLBACKW;
1516 }
1517 }
1518 }
1519
1520 HEADER_SendItemChanged(hwnd,nItem);
1521
1522 HEADER_SetItemBounds(hwnd,0);
1523 HEADER_Refresh(hwnd);
1524
1525 return TRUE;
1526}
1527
1528static LRESULT
1529HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1530{
1531 HEADER_INFO *infoPtr;
1532 TEXTMETRICA tm;
1533 HFONT hOldFont;
1534 HDC hdc;
1535
1536 infoPtr = (HEADER_INFO*)initControl(hwnd,sizeof(HEADER_INFO));
1537
1538 infoPtr->uNumItem = 0;
1539 infoPtr->hFont = 0;
1540 infoPtr->items = 0;
1541 infoPtr->hcurArrow = LoadCursorA (0, IDC_ARROWA);
1542 infoPtr->hcurDivider = LoadCursorA (0, IDC_SIZEWEA);
1543 infoPtr->hcurDivopen = LoadCursorA (0, IDC_SIZENSA);
1544 infoPtr->bCaptured = FALSE;
1545 infoPtr->bPressed = FALSE;
1546 infoPtr->bTracking = FALSE;
1547 infoPtr->bDragDrop = FALSE;
1548 infoPtr->bTimer = FALSE;
1549 infoPtr->iMoveItem = 0;
1550 infoPtr->himl = 0;
1551 infoPtr->dragImage = 0;
1552 infoPtr->iHotItem = -1;
1553 infoPtr->xBmpMargin = 3*GetSystemMetrics(SM_CXEDGE);
1554
1555 hdc = GetDC (hwnd);
1556 hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT));
1557 GetTextMetricsA (hdc, &tm);
1558 infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
1559 SelectObject (hdc, hOldFont);
1560 ReleaseDC (hwnd, hdc);
1561
1562 return 0;
1563}
1564
1565
1566static LRESULT
1567HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1568{
1569 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1570 HEADER_ITEM *lpItem;
1571 INT nItem;
1572
1573 if (infoPtr->items) {
1574 lpItem = (HEADER_ITEM*)infoPtr->items;
1575 for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
1576 if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACKW))
1577 COMCTL32_Free (lpItem->pszText);
1578 }
1579 COMCTL32_Free (infoPtr->items);
1580 }
1581
1582 if (infoPtr->himl)
1583 ImageList_Destroy (infoPtr->himl);
1584
1585 doneControl(hwnd);
1586
1587 return 0;
1588}
1589
1590static LRESULT
1591HEADER_EraseBackground(HWND hwnd,WPARAM wParam,LPARAM lParam)
1592{
1593 return TRUE;
1594}
1595
1596static LRESULT
1597HEADER_GetDlgCode(HWND hwnd,WPARAM wParam,LPARAM lParam)
1598{
1599 return DLGC_WANTTAB | DLGC_WANTARROWS;
1600}
1601
1602static LRESULT
1603HEADER_GetFont (HWND hwnd)
1604{
1605 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1606
1607 return (LRESULT)infoPtr->hFont;
1608}
1609
1610
1611static LRESULT
1612HEADER_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
1613{
1614 POINT pt;
1615 UINT flags;
1616 INT nItem;
1617
1618 pt.x = (INT)LOWORD(lParam);
1619 pt.y = (INT)HIWORD(lParam);
1620 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1621
1622 if ((GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS) && (flags == HHT_ONHEADER))
1623 HEADER_SendItemDblClick(hwnd,nItem,0);
1624 else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
1625 HEADER_SendDividerDblClick(hwnd,nItem,0);
1626
1627 return 0;
1628}
1629
1630
1631static LRESULT
1632HEADER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1633{
1634 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1635 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1636 POINT pt;
1637 UINT flags;
1638 INT nItem;
1639 HDC hdc;
1640
1641 pt.x = (SHORT)LOWORD(lParam);
1642 pt.y = (SHORT)HIWORD(lParam);
1643 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1644
1645 if ((dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER))
1646 {
1647 SetCapture (hwnd);
1648 infoPtr->bCaptured = TRUE;
1649 infoPtr->bPressed = TRUE;
1650 infoPtr->iMoveItem = nItem;
1651 infoPtr->dragStart = pt;
1652 infoPtr->iDragItem = nItem;
1653
1654 infoPtr->items[nItem].bDown = TRUE;
1655
1656 /* Send WM_CUSTOMDRAW */
1657 hdc = GetDC (hwnd);
1658 HEADER_RefreshItem (hwnd, hdc, nItem);
1659 ReleaseDC (hwnd, hdc);
1660
1661// TRACE (header, "Pressed item %d!\n", nItem);
1662 } else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
1663 {
1664 if (!(HEADER_SendBeginTrack(hwnd,nItem,0)))
1665 {
1666 SetCapture (hwnd);
1667 infoPtr->bCaptured = TRUE;
1668 infoPtr->bTracking = TRUE;
1669 infoPtr->bTrackOpen = flags == HHT_ONDIVOPEN;
1670 infoPtr->iMoveItem = nItem;
1671 infoPtr->nOldWidth = infoPtr->items[nItem].cxy;
1672 infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
1673
1674 if (!(dwStyle & HDS_FULLDRAG))
1675 {
1676 infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
1677 hdc = GetDC (hwnd);
1678 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1679 ReleaseDC (hwnd, hdc);
1680 }
1681
1682// TRACE (header, "Begin tracking item %d!\n", nItem);
1683 }
1684 }
1685
1686 return 0;
1687}
1688
1689
1690static LRESULT
1691HEADER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1692{
1693 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1694 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1695 POINT pt;
1696 UINT flags;
1697 INT nItem, nWidth;
1698 HDC hdc;
1699
1700 pt.x = (SHORT)LOWORD(lParam);
1701 pt.y = (SHORT)HIWORD(lParam);
1702 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1703
1704 if (infoPtr->bPressed)
1705 {
1706 if (infoPtr->bDragDrop)
1707 {
1708 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1709 infoPtr->bDragDrop = FALSE;
1710 ImageList_Destroy(infoPtr->dragImage);
1711 infoPtr->dragImage = NULL;
1712
1713 if (!HEADER_SendDragNotify(hwnd,HDN_ENDDRAG,infoPtr->iMoveItem,0) && (infoPtr->iDragItem != infoPtr->iMoveItem) && (infoPtr->iDragItem != infoPtr->iMoveItem+1) && (infoPtr->iDragItem != -1))
1714 {
1715 HEADER_ITEM tmpItem = infoPtr->items[infoPtr->iMoveItem];;
1716
1717 //CB: notificatons??
1718
1719 if (infoPtr->iDragItem > infoPtr->iMoveItem)
1720 {
1721 INT x ;
1722
1723 for (x = infoPtr->iMoveItem;x < infoPtr->iDragItem-1;x++)
1724 memcpy(&infoPtr->items[x],&infoPtr->items[x+1],sizeof(HEADER_ITEM));
1725
1726 infoPtr->items[infoPtr->iDragItem-1] = tmpItem;
1727 } else
1728 {
1729 INT x;
1730
1731 for (x = infoPtr->iMoveItem;x > infoPtr->iDragItem;x--)
1732 memcpy(&infoPtr->items[x],&infoPtr->items[x-1],sizeof(HEADER_ITEM));
1733
1734 infoPtr->items[infoPtr->iDragItem] = tmpItem;
1735 }
1736
1737 HEADER_SetItemBounds(hwnd,0);
1738 }
1739 HEADER_Refresh(hwnd);
1740 } else if (PtInRect(&infoPtr->items[infoPtr->iMoveItem].rect,pt))
1741 {
1742 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1743 hdc = GetDC(hwnd);
1744 HEADER_RefreshItem(hwnd,hdc,infoPtr->iMoveItem);
1745 ReleaseDC(hwnd,hdc);
1746
1747 HEADER_SendItemClick(hwnd,infoPtr->iMoveItem,0);
1748 }
1749 infoPtr->bPressed = FALSE;
1750 } else if (infoPtr->bTracking)
1751 {
1752 infoPtr->bTracking = FALSE;
1753
1754 HEADER_SendEndTrack(hwnd,infoPtr->iMoveItem,0);
1755
1756 if (!(dwStyle & HDS_FULLDRAG))
1757 {
1758 hdc = GetDC (hwnd);
1759 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1760 ReleaseDC (hwnd, hdc);
1761 if (HEADER_SendItemChanging(hwnd,infoPtr->iMoveItem))
1762 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1763 else
1764 {
1765 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1766 if (nWidth < MIN_ITEMWIDTH) nWidth = MIN_ITEMWIDTH;
1767
1768 if (infoPtr->nOldWidth != nWidth)
1769 {
1770 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1771
1772 HEADER_SetItemBounds (hwnd,infoPtr->iMoveItem);
1773 HEADER_Refresh(hwnd);
1774 HEADER_SendItemChanged(hwnd,infoPtr->iMoveItem);
1775 }
1776 }
1777 }
1778 }
1779
1780 if (infoPtr->bCaptured)
1781 {
1782 infoPtr->bCaptured = FALSE;
1783 ReleaseCapture();
1784 sendNotify(hwnd,NM_RELEASEDCAPTURE);
1785 }
1786
1787 return 0;
1788}
1789
1790static INT
1791HEADER_DragHitTest(HWND hwnd,HEADER_INFO* infoPtr,POINT pt)
1792{
1793 RECT rect;
1794 INT x,xDrag;
1795
1796 GetClientRect(hwnd,&rect);
1797 if (pt.y < rect.top || pt.y > rect.bottom) return -1;
1798
1799 xDrag = infoPtr->items[infoPtr->iMoveItem].rect.left+pt.x-infoPtr->dragStart.x;
1800
1801 if (xDrag < infoPtr->items[0].rect.left) return 0;
1802
1803 for (x = 0;x < infoPtr->uNumItem;x++)
1804 {
1805 if ((xDrag >= infoPtr->items[x].rect.left) && (xDrag <= infoPtr->items[x].rect.right)) return x;
1806 }
1807
1808 return infoPtr->uNumItem;
1809}
1810
1811static LRESULT
1812HEADER_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
1813{
1814 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1815 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1816 POINT pt;
1817 UINT flags;
1818 INT nItem, nWidth;
1819 HDC hdc;
1820
1821 pt.x = (SHORT)LOWORD(lParam);
1822 pt.y = (SHORT)HIWORD(lParam);
1823 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1824
1825 if ((dwStyle & HDS_BUTTONS) && (dwStyle & HDS_HOTTRACK))
1826 {
1827 INT newItem;
1828
1829 if (infoPtr->bCaptured && infoPtr->bPressed && PtInRect(&infoPtr->items[infoPtr->iMoveItem].rect,pt))
1830 newItem = infoPtr->iMoveItem;
1831 else
1832 {
1833 if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN))
1834 newItem = nItem;
1835 else
1836 newItem = -1;
1837 }
1838 if (newItem != infoPtr->iHotItem)
1839 {
1840 infoPtr->iHotItem = newItem;
1841 HEADER_Refresh(hwnd);
1842 }
1843 if (!infoPtr->bTimer && (infoPtr->iHotItem != -1))
1844 {
1845 infoPtr->bTimer = TRUE;
1846 SetTimer(hwnd,TIMER_ID,TIMER_MS,NULL);
1847 } else if (infoPtr->bTimer && (infoPtr->iHotItem == -1))
1848 {
1849 KillTimer(hwnd,TIMER_ID);
1850 infoPtr->bTimer = FALSE;
1851 }
1852 }
1853
1854 if (infoPtr->bCaptured)
1855 {
1856 if (infoPtr->bPressed)
1857 {
1858 if ((dwStyle & HDS_DRAGDROP) && (infoPtr->uNumItem > 1) && (infoPtr->bDragDrop || !HEADER_SendDragNotify(hwnd,HDN_BEGINDRAG,infoPtr->iMoveItem,0)))
1859 {
1860 if (!infoPtr->bDragDrop)
1861 {
1862 infoPtr->bDragDrop = TRUE;
1863 infoPtr->dragImage = (HIMAGELIST)HEADER_CreateDragImage(hwnd,infoPtr->iMoveItem,0);
1864 }
1865 infoPtr->dragPos = pt;
1866 infoPtr->iDragItem = HEADER_DragHitTest(hwnd,infoPtr,pt);
1867 HEADER_Refresh(hwnd);
1868 } else
1869 {
1870 BOOL newDown;
1871
1872 if (PtInRect(&infoPtr->items[infoPtr->iMoveItem].rect,pt))
1873 newDown = TRUE;
1874 else
1875 newDown = FALSE;
1876
1877 if (newDown != infoPtr->items[infoPtr->iMoveItem].bDown)
1878 {
1879 infoPtr->items[infoPtr->iMoveItem].bDown = newDown;
1880 hdc = GetDC (hwnd);
1881 HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem);
1882 ReleaseDC (hwnd, hdc);
1883 }
1884 }
1885// TRACE (header, "Moving pressed item %d!\n", infoPtr->iMoveItem);
1886 } else if (infoPtr->bTracking)
1887 {
1888 if (dwStyle & HDS_FULLDRAG)
1889 {
1890 if (HEADER_SendItemChanging(hwnd,infoPtr->iMoveItem))
1891 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1892 else
1893 {
1894 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1895 if (nWidth < MIN_ITEMWIDTH) nWidth = MIN_ITEMWIDTH;
1896 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1897 HEADER_SendItemChanged(hwnd,infoPtr->iMoveItem);
1898 }
1899 HEADER_SetItemBounds (hwnd,infoPtr->iMoveItem);
1900 HEADER_Refresh(hwnd);
1901 } else
1902 {
1903 INT lastPos = infoPtr->xOldTrack;
1904
1905 hdc = GetDC (hwnd);
1906 infoPtr->xOldTrack = pt.x + infoPtr->xTrackOffset;
1907 if (infoPtr->xOldTrack < infoPtr->items[infoPtr->iMoveItem].rect.left+MIN_ITEMWIDTH)
1908 infoPtr->xOldTrack = infoPtr->items[infoPtr->iMoveItem].rect.left+MIN_ITEMWIDTH;
1909 infoPtr->items[infoPtr->iMoveItem].cxy =
1910 infoPtr->xOldTrack-infoPtr->items[infoPtr->iMoveItem].rect.left;
1911 if (lastPos != infoPtr->xOldTrack)
1912 {
1913 HEADER_DrawTrackLine(hwnd,hdc,lastPos);
1914 HEADER_DrawTrackLine(hwnd,hdc,infoPtr->xOldTrack);
1915 }
1916 ReleaseDC (hwnd, hdc);
1917 }
1918
1919 HEADER_SendTrack(hwnd,infoPtr->iMoveItem);
1920 }
1921 }
1922
1923 return 0;
1924}
1925
1926static LRESULT
1927HEADER_Size(HWND hwnd,WPARAM wParam,LPARAM lParam)
1928{
1929 HEADER_SetItemBounds(hwnd,0);
1930
1931 return DefWindowProcA(hwnd,WM_SIZE,wParam,lParam);
1932}
1933
1934static LRESULT
1935HEADER_Timer(HWND hwnd,WPARAM wParam,LPARAM lParam)
1936{
1937 POINT point;
1938 RECT rect;
1939
1940 GetCursorPos(&point);
1941 ScreenToClient(hwnd,&point);
1942 GetClientRect(hwnd,&rect);
1943 if (!PtInRect(&rect,point))
1944 {
1945 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1946
1947 infoPtr->iHotItem = -1;
1948 infoPtr->bTimer = FALSE;
1949 HEADER_Refresh(hwnd);
1950
1951 KillTimer(hwnd,TIMER_ID);
1952 }
1953
1954 return 0;
1955}
1956
1957static LRESULT
1958HEADER_KeyDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
1959{
1960 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1961 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1962 HDC hdc;
1963
1964 if ((wParam == VK_ESCAPE) && infoPtr->bCaptured)
1965 {
1966 if (infoPtr->bPressed && infoPtr->bDragDrop)
1967 {
1968 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1969 infoPtr->bPressed = FALSE;
1970 infoPtr->bDragDrop = FALSE;
1971 ImageList_Destroy(infoPtr->dragImage);
1972 infoPtr->dragImage = NULL;
1973
1974 HEADER_SendDragNotify(hwnd,HDN_ENDDRAG,infoPtr->iMoveItem,0);
1975 HEADER_Refresh(hwnd);
1976
1977 } else if (infoPtr->bTracking)
1978 {
1979 infoPtr->bTracking = FALSE;
1980
1981 HEADER_SendEndTrack(hwnd,infoPtr->iMoveItem,0);
1982
1983 if (dwStyle & HDS_FULLDRAG)
1984 {
1985 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1986 HEADER_Refresh(hwnd);
1987 } else
1988 {
1989 hdc = GetDC(hwnd);
1990 HEADER_DrawTrackLine(hwnd,hdc,infoPtr->xOldTrack);
1991 ReleaseDC(hwnd,hdc);
1992 }
1993 }
1994
1995 infoPtr->bCaptured = FALSE;
1996 ReleaseCapture();
1997 sendNotify(hwnd,NM_RELEASEDCAPTURE);
1998
1999 return TRUE;
2000 }
2001
2002 return DefWindowProcA(WM_KEYDOWN,hwnd,wParam,lParam);
2003}
2004
2005static LRESULT
2006HEADER_CaptureChanged(HWND hwnd,WPARAM wParam,LPARAM lParam)
2007{
2008 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
2009 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
2010 HDC hdc;
2011
2012 if (infoPtr->bCaptured && infoPtr->bPressed)
2013 {
2014 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
2015 infoPtr->bPressed = FALSE;
2016 if (infoPtr->bDragDrop)
2017 {
2018 infoPtr->bDragDrop = FALSE;
2019 ImageList_Destroy(infoPtr->dragImage);
2020 infoPtr->dragImage = NULL;
2021
2022 HEADER_SendDragNotify(hwnd,HDN_ENDDRAG,infoPtr->iMoveItem,0);
2023 HEADER_Refresh(hwnd);
2024 } else
2025 {
2026 hdc = GetDC(hwnd);
2027 HEADER_RefreshItem(hwnd,hdc,infoPtr->iMoveItem);
2028 ReleaseDC(hwnd,hdc);
2029 }
2030 } else if (infoPtr->bCaptured && infoPtr->bTracking)
2031 {
2032 infoPtr->bTracking = FALSE;
2033
2034 HEADER_SendEndTrack(hwnd,infoPtr->iMoveItem,0);
2035
2036 if (dwStyle & HDS_FULLDRAG)
2037 {
2038 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
2039 HEADER_Refresh(hwnd);
2040 } else
2041 {
2042 hdc = GetDC(hwnd);
2043 HEADER_DrawTrackLine(hwnd,hdc,infoPtr->xOldTrack);
2044 ReleaseDC(hwnd,hdc);
2045 }
2046 }
2047
2048 infoPtr->bCaptured = FALSE;
2049
2050 return 0;
2051}
2052
2053static LRESULT
2054HEADER_Paint (HWND hwnd, WPARAM wParam)
2055{
2056 HDC hdc;
2057 PAINTSTRUCT ps;
2058
2059 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2060 HEADER_Draw (hwnd, hdc);
2061 if(!wParam)
2062 EndPaint (hwnd, &ps);
2063
2064 return 0;
2065}
2066
2067
2068static LRESULT
2069HEADER_RButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
2070{
2071 sendNotify(hwnd,NM_RCLICK);
2072
2073 return DefWindowProcA(hwnd,WM_RBUTTONUP,wParam,lParam);
2074}
2075
2076
2077static LRESULT
2078HEADER_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2079{
2080 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
2081 POINT pt;
2082 UINT flags;
2083 INT nItem;
2084
2085// TRACE (header, "code=0x%X id=0x%X\n", LOWORD(lParam), HIWORD(lParam));
2086
2087 GetCursorPos (&pt);
2088 ScreenToClient (hwnd, &pt);
2089
2090 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
2091
2092 if (infoPtr->bCaptured)
2093 {
2094 if (infoPtr->bTracking)
2095 {
2096 if (infoPtr->bTrackOpen) SetCursor(infoPtr->hcurDivopen);
2097 else SetCursor(infoPtr->hcurDivider);
2098 } else SetCursor(infoPtr->hcurArrow);
2099
2100 return TRUE;
2101 }
2102
2103 if (flags == HHT_ONDIVIDER)
2104 SetCursor (infoPtr->hcurDivider);
2105 else if (flags == HHT_ONDIVOPEN)
2106 SetCursor (infoPtr->hcurDivopen);
2107 else
2108 SetCursor (infoPtr->hcurArrow);
2109
2110 return TRUE;
2111}
2112
2113
2114static LRESULT
2115HEADER_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2116{
2117 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
2118 TEXTMETRICA tm;
2119 HFONT hFont, hOldFont;
2120 HDC hdc;
2121
2122 infoPtr->hFont = (HFONT)wParam;
2123
2124 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
2125
2126 hdc = GetDC (hwnd);
2127 hOldFont = SelectObject (hdc, hFont);
2128 GetTextMetricsA (hdc, &tm);
2129 infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
2130 SelectObject (hdc, hOldFont);
2131 ReleaseDC (hwnd, hdc);
2132
2133 if (lParam) HEADER_Refresh(hwnd);
2134
2135 return 0;
2136}
2137
2138
2139static LRESULT WINAPI
2140HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2141{
2142 switch (msg)
2143 {
2144 case HDM_CLEARFILTER:
2145 return HEADER_ClearFilter(hwnd,wParam,lParam);
2146
2147 case HDM_CREATEDRAGIMAGE:
2148 return HEADER_CreateDragImage (hwnd,wParam,lParam);
2149
2150 case HDM_DELETEITEM:
2151 return HEADER_DeleteItem (hwnd, wParam);
2152
2153 case HDM_EDITFILTER:
2154 return HEADER_EditFilter(hwnd,wParam,lParam);
2155
2156 case HDM_GETBITMAPMARGIN:
2157 return HEADER_GetBitmapMargin(hwnd,wParam,lParam);
2158
2159 case HDM_GETIMAGELIST:
2160 return HEADER_GetImageList (hwnd);
2161
2162 case HDM_GETITEMA:
2163 return HEADER_GetItem(hwnd,wParam,lParam,FALSE);
2164
2165 case HDM_GETITEMW:
2166 return HEADER_GetItem(hwnd,wParam,lParam,TRUE);
2167
2168 case HDM_GETITEMCOUNT:
2169 return HEADER_GetItemCount (hwnd);
2170
2171 case HDM_GETITEMRECT:
2172 return HEADER_GetItemRect (hwnd, wParam, lParam);
2173
2174 case HDM_GETORDERARRAY:
2175 return HEADER_GetOrderArray(hwnd,wParam,lParam);
2176
2177 case HDM_HITTEST:
2178 return HEADER_HitTest (hwnd, wParam, lParam);
2179
2180 case HDM_INSERTITEMA:
2181 return HEADER_InsertItem(hwnd,wParam,lParam,FALSE);
2182
2183 case HDM_INSERTITEMW:
2184 return HEADER_InsertItem(hwnd,wParam,lParam,TRUE);
2185
2186 case HDM_LAYOUT:
2187 return HEADER_Layout (hwnd, wParam, lParam);
2188
2189 case HDM_ORDERTOINDEX:
2190 return HEADER_OrderToIndex(hwnd,wParam,lParam);
2191
2192 case HDM_SETBITMAPMARGIN:
2193 return HEADER_SetBitmapMargin(hwnd,wParam,lParam);
2194
2195 case HDM_SETFILTERCHANGETIMEOUT:
2196 return HEADER_SetFilterChangeTimeout(hwnd,wParam,lParam);
2197
2198 case HDM_SETHOTDIVIDER:
2199 return HEADER_SetHotDivider(hwnd,wParam,lParam);
2200
2201 case HDM_SETIMAGELIST:
2202 return HEADER_SetImageList (hwnd, wParam, lParam);
2203
2204 case HDM_SETITEMA:
2205 return HEADER_SetItem(hwnd,wParam,lParam,FALSE);
2206
2207 case HDM_SETITEMW:
2208 return HEADER_SetItem(hwnd,wParam,lParam,TRUE);
2209
2210 case HDM_SETORDERARRAY:
2211 return HEADER_SetOrderArray(hwnd,wParam,lParam);
2212
2213 case WM_CAPTURECHANGED:
2214 return HEADER_CaptureChanged(hwnd,wParam,lParam);
2215
2216 case WM_CREATE:
2217 return HEADER_Create (hwnd, wParam, lParam);
2218
2219 case WM_DESTROY:
2220 return HEADER_Destroy (hwnd, wParam, lParam);
2221
2222 case WM_ERASEBKGND:
2223 return HEADER_EraseBackground(hwnd,wParam,lParam);
2224
2225 case WM_GETDLGCODE:
2226 return HEADER_GetDlgCode(hwnd,wParam,lParam);
2227
2228 case WM_GETFONT:
2229 return HEADER_GetFont (hwnd);
2230
2231 case WM_KEYDOWN:
2232 return HEADER_KeyDown(hwnd,wParam,lParam);
2233
2234 case WM_LBUTTONDBLCLK:
2235 return HEADER_LButtonDblClk (hwnd, wParam, lParam);
2236
2237 case WM_LBUTTONDOWN:
2238 return HEADER_LButtonDown (hwnd, wParam, lParam);
2239
2240 case WM_LBUTTONUP:
2241 return HEADER_LButtonUp (hwnd, wParam, lParam);
2242
2243 case WM_MOUSEMOVE:
2244 return HEADER_MouseMove (hwnd, wParam, lParam);
2245
2246 case WM_PAINT:
2247 return HEADER_Paint(hwnd,wParam);
2248
2249 case WM_RBUTTONUP:
2250 return HEADER_RButtonUp (hwnd, wParam, lParam);
2251
2252 case WM_SETCURSOR:
2253 return HEADER_SetCursor (hwnd, wParam, lParam);
2254
2255 case WM_SETFONT:
2256 return HEADER_SetFont (hwnd, wParam, lParam);
2257
2258 case WM_SIZE:
2259 return HEADER_Size(hwnd,wParam,lParam);
2260
2261 case WM_TIMER:
2262 return HEADER_Timer(hwnd,wParam,lParam);
2263
2264 default:
2265// if (msg >= WM_USER)
2266// ERR (header, "unknown msg %04x wp=%04x lp=%08lx\n",
2267// msg, wParam, lParam );
2268 return defComCtl32ProcA (hwnd, msg, wParam, lParam);
2269 }
2270 return 0;
2271}
2272
2273
2274VOID
2275HEADER_Register (VOID)
2276{
2277 WNDCLASSA wndClass;
2278
2279 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2280 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
2281 wndClass.lpfnWndProc = (WNDPROC)HEADER_WindowProc;
2282 wndClass.cbClsExtra = 0;
2283 wndClass.cbWndExtra = sizeof(HEADER_INFO *);
2284 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
2285 wndClass.lpszClassName = WC_HEADERA;
2286
2287 RegisterClassA (&wndClass);
2288}
2289
2290
2291VOID
2292HEADER_Unregister (VOID)
2293{
2294 UnregisterClassA (WC_HEADERA, (HINSTANCE)NULL);
2295}
2296
Note: See TracBrowser for help on using the repository browser.