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

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

merged with Corel WINE 20000513, added new DPA_* functions

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