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

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

new listview messages and styles, new resources

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