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

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

* empty log message *

File size: 58.1 KB
Line 
1/* $Id: header.cpp,v 1.9 2000-04-17 17:04:11 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 20000317 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
963static LRESULT
964HEADER_DeleteItem (HWND hwnd, WPARAM wParam)
965{
966 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
967 INT iItem = (INT)wParam;
968 HDC hdc;
969
970 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return FALSE;
971
972 if (infoPtr->uNumItem == 1)
973 {
974 //clear
975 if (infoPtr->items[0].pszText) COMCTL32_Free(infoPtr->items[0].pszText);
976 COMCTL32_Free (infoPtr->items);
977 infoPtr->items = 0;
978 infoPtr->uNumItem = 0;
979
980 InvalidateRect(hwnd,NULL,TRUE);
981 } else
982 {
983 HEADER_ITEM *oldItems = infoPtr->items;
984
985 if (infoPtr->items[iItem].pszText) COMCTL32_Free(infoPtr->items[iItem].pszText);
986
987 infoPtr->uNumItem--;
988 infoPtr->items = (HEADER_ITEM*)COMCTL32_Alloc (sizeof (HEADER_ITEM) * infoPtr->uNumItem);
989 /* pre delete copy */
990 if (iItem > 0)
991 memcpy (&infoPtr->items[0], &oldItems[0],iItem*sizeof(HEADER_ITEM));
992
993 /* post delete copy */
994 if (iItem < infoPtr->uNumItem)
995 memcpy (&infoPtr->items[iItem],&oldItems[iItem+1],(infoPtr->uNumItem-iItem)*sizeof(HEADER_ITEM));
996
997 COMCTL32_Free(oldItems);
998
999 if (iItem < infoPtr->uNumItem) HEADER_SetItemBounds(hwnd,iItem);
1000
1001 HEADER_Refresh(hwnd);
1002
1003 }
1004
1005 return TRUE;
1006}
1007
1008static LRESULT
1009HEADER_GetBitmapMargin(HWND hwnd,WPARAM wParam,LPARAM lParam)
1010{
1011 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1012
1013 return infoPtr->xBmpMargin;
1014}
1015
1016static LRESULT
1017HEADER_SetBitmapMargin(HWND hwnd,WPARAM wParam,LPARAM lParam)
1018{
1019 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1020 INT oldMargin = infoPtr->xBmpMargin;
1021
1022 if (infoPtr->xBmpMargin != (INT)wParam)
1023 {
1024 infoPtr->xBmpMargin = (INT)wParam;
1025 HEADER_Refresh(hwnd);
1026 }
1027
1028 return oldMargin;
1029}
1030
1031static LRESULT
1032HEADER_GetImageList (HWND hwnd)
1033{
1034 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1035
1036 return (LRESULT)infoPtr->himl;
1037}
1038
1039
1040static LRESULT HEADER_GetItem(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL unicode)
1041{
1042 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1043 HDITEMW *phdi = (HDITEMW*)lParam;
1044 INT nItem = (INT)wParam;
1045 HEADER_ITEM *lpItem;
1046
1047 if (!phdi) return FALSE;
1048 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) return FALSE;
1049
1050 if (phdi->mask == 0) return TRUE;
1051
1052 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1053
1054 if (phdi->mask & HDI_BITMAP) phdi->hbm = lpItem->hbm;
1055
1056 if (phdi->mask & HDI_FORMAT) phdi->fmt = lpItem->fmt;
1057
1058 if (phdi->mask & HDI_FILTER)
1059 {
1060 phdi->type = lpItem->type;
1061 phdi->pvFilter = lpItem->pvFilter;
1062 }
1063
1064 if (phdi->mask & (HDI_WIDTH | HDI_HEIGHT)) phdi->cxy = lpItem->cxy;
1065
1066 if (phdi->mask & HDI_IMAGE) phdi->iImage = lpItem->iImage;
1067
1068 if (phdi->mask & HDI_LPARAM) phdi->lParam = lpItem->lParam;
1069
1070 if (phdi->mask & HDI_ORDER) phdi->iOrder = lpItem->iOrder;
1071
1072 if (phdi->mask & HDI_TEXT)
1073 {
1074 if (lpItem->pszText != LPSTR_TEXTCALLBACKW)
1075 {
1076 if (lpItem->pszText)
1077 {
1078 if (unicode)
1079 lstrcpynW (phdi->pszText,lpItem->pszText,phdi->cchTextMax);
1080 else
1081 lstrcpynWtoA((LPSTR)phdi->pszText,lpItem->pszText,phdi->cchTextMax);
1082 } else phdi->pszText = NULL;
1083 } else
1084 {
1085 phdi->pszText = unicode ? LPSTR_TEXTCALLBACKW:(LPWSTR)LPSTR_TEXTCALLBACKA;
1086 }
1087 }
1088
1089 return TRUE;
1090}
1091
1092static LRESULT
1093HEADER_GetItemCount (HWND hwnd)
1094{
1095 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1096
1097 return infoPtr->uNumItem;
1098}
1099
1100
1101LRESULT HEADER_GetItemRect (HWND hwnd, WPARAM wParam, LPARAM lParam)
1102{
1103 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1104 INT iItem = (INT)wParam;
1105 LPRECT lpRect = (LPRECT)lParam;
1106
1107 if (!lpRect || (iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return FALSE;
1108
1109 lpRect->left = infoPtr->items[iItem].rect.left;
1110 lpRect->right = infoPtr->items[iItem].rect.right;
1111 lpRect->top = infoPtr->items[iItem].rect.top;
1112 lpRect->bottom = infoPtr->items[iItem].rect.bottom;
1113
1114 return TRUE;
1115}
1116
1117//useful function for ListView control
1118
1119DWORD HEADER_GetExpandedColumnTextWidth(HWND hwnd,INT iItem)
1120{
1121 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1122 INT width = 0;
1123 HEADER_ITEM *phdi;
1124
1125 if ((iItem < 0) || (iItem >= (INT)infoPtr->uNumItem)) return width;
1126
1127 phdi = &infoPtr->items[iItem];
1128
1129 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS)
1130 width += 4;
1131 else
1132 width += 2;
1133
1134 if (phdi->fmt & HDF_OWNERDRAW)
1135 {
1136 //can't calculate ownerdraw
1137 return infoPtr->items[iItem].rect.right-infoPtr->items[iItem].rect.left;
1138 }
1139
1140 if (phdi->fmt & HDF_BITMAP)
1141 {
1142 if (phdi->hbm)
1143 {
1144 BITMAP bmp;
1145
1146 GetObjectA (phdi->hbm,sizeof(BITMAP),(LPVOID)&bmp);
1147
1148 width += bmp.bmWidth+2*infoPtr->xBmpMargin;
1149 } else width += 2*infoPtr->xBmpMargin;
1150 }
1151
1152 if (phdi->fmt & HDF_IMAGE)
1153 {
1154 INT iImage;
1155 IMAGEINFO info;
1156
1157 if (phdi->iImage == I_IMAGECALLBACK)
1158 iImage = HEADER_CallbackImage(hwnd,infoPtr,phdi,iItem);
1159 else
1160 iImage = phdi->iImage;
1161
1162 if (iImage != I_IMAGENONE)
1163 {
1164 if (ImageList_GetImageInfo(infoPtr->himl,phdi->iImage,&info))
1165 {
1166 width += info.rcImage.right-info.rcImage.left+2*infoPtr->xBmpMargin;
1167 }
1168 }
1169 }
1170
1171 if (phdi->fmt & HDF_STRING)
1172 {
1173 WCHAR* pszText;
1174 BOOL mustFree = FALSE;
1175 HFONT hFont,hOldFont;
1176 SIZE size;
1177 HDC hdc = GetDC(hwnd);
1178
1179 if (phdi->pszText == LPSTR_TEXTCALLBACKW)
1180 pszText = HEADER_CallbackText(hwnd,infoPtr,phdi,iItem,&mustFree);
1181 else
1182 pszText = phdi->pszText;
1183
1184 hFont = infoPtr->hFont ? infoPtr->hFont:GetStockObject(SYSTEM_FONT);
1185 hOldFont = SelectObject(hdc,hFont);
1186
1187 if (GetTextExtentPoint32W(hdc,pszText,lstrlenW(pszText),&size))
1188 width += size.cx+2*TEXT_MARGIN;
1189 if (mustFree) COMCTL32_Free(pszText);
1190 SelectObject(hdc,hOldFont);
1191 ReleaseDC(hwnd,hdc);
1192 }
1193
1194 return width;
1195}
1196
1197static BOOL
1198HEADER_CheckOrderArray(HEADER_INFO* infoPtr,LPINT lpiArray)
1199{
1200 INT x,y;
1201
1202 for (x = 0;x < infoPtr->uNumItem;x++)
1203 {
1204 BOOL found = FALSE;
1205
1206 for (y = 0;y <= x;y++)
1207 if (infoPtr->items[y].iOrder == lpiArray[x]) found = TRUE;
1208 for (y = x+1;y < infoPtr->uNumItem;y++)
1209 {
1210 if (infoPtr->items[x].iOrder == infoPtr->items[y].iOrder || lpiArray[x] == lpiArray[y]) return FALSE;
1211 if (infoPtr->items[y].iOrder == lpiArray[x]) found = TRUE;
1212 }
1213
1214 if (!found) return FALSE;
1215 }
1216
1217 return TRUE;
1218}
1219
1220static LRESULT
1221HEADER_GetOrderArray(HWND hwnd,WPARAM wParam,LPARAM lParam)
1222{
1223 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1224 LPINT lpiArray = (LPINT)lParam;
1225 INT x;
1226
1227 if (wParam != infoPtr->uNumItem || !lpiArray || !HEADER_CheckOrderArray(infoPtr,lpiArray)) return FALSE;
1228
1229 for (x = 0;x < infoPtr->uNumItem;x++) lpiArray[x] = infoPtr->items[x].iOrder;
1230
1231 return TRUE;
1232}
1233
1234static LRESULT
1235HEADER_SetOrderArray(HWND hwnd,WPARAM wParam,LPARAM lParam)
1236{
1237 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1238 LPINT lpiArray = (LPINT)lParam;
1239 HEADER_ITEM* newItems;
1240 INT x,y;
1241
1242 if (wParam != infoPtr->uNumItem || !lpiArray || !HEADER_CheckOrderArray(infoPtr,lpiArray)) return FALSE;
1243 if (infoPtr->uNumItem <= 1) return TRUE;
1244
1245 newItems = (HEADER_ITEM*)COMCTL32_Alloc(infoPtr->uNumItem*sizeof(HEADER_ITEM));
1246 for (x = 0;x < infoPtr->uNumItem;x++)
1247 for (y = 0;y < infoPtr->uNumItem;y++)
1248 if (infoPtr->items[y].iOrder == lpiArray[x]) memcpy(&newItems[x],&infoPtr->items[y],sizeof(HEADER_ITEM));
1249 COMCTL32_Free(infoPtr->items);
1250 infoPtr->items = newItems;
1251
1252 HEADER_SetItemBounds(hwnd,0);
1253 HEADER_Refresh(hwnd);
1254
1255 return TRUE;
1256}
1257
1258static LRESULT
1259HEADER_OrderToIndex(HWND hwnd,WPARAM wParam,LPARAM lParam)
1260{
1261 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1262 INT iOrder = (INT)wParam;
1263 INT x;
1264
1265 for (x = 0;x < infoPtr->uNumItem;x++)
1266 if (infoPtr->items[x].iOrder == iOrder) return x;
1267
1268 return iOrder;
1269}
1270
1271static LRESULT
1272HEADER_HitTest (HWND hwnd, WPARAM wParam, LPARAM lParam)
1273{
1274 LPHDHITTESTINFO phti = (LPHDHITTESTINFO)lParam;
1275
1276 HEADER_InternalHitTest (hwnd, &phti->pt, &phti->flags, &phti->iItem);
1277
1278 return phti->iItem;
1279}
1280
1281
1282static LRESULT HEADER_InsertItem(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL unicode)
1283{
1284 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1285 HDITEMW *phdi = (HDITEMW*)lParam;
1286 INT nItem = (INT)wParam;
1287 HEADER_ITEM *lpItem;
1288
1289 if ((phdi == NULL) || (nItem < 0)) return -1;
1290
1291 if (nItem > infoPtr->uNumItem) nItem = infoPtr->uNumItem;
1292
1293 if (infoPtr->uNumItem == 0)
1294 {
1295 infoPtr->items = (HEADER_ITEM*)COMCTL32_Alloc(sizeof(HEADER_ITEM));
1296 infoPtr->uNumItem++;
1297 } else
1298 {
1299 HEADER_ITEM *oldItems = infoPtr->items;
1300
1301 infoPtr->uNumItem++;
1302 infoPtr->items = (HEADER_ITEM*)COMCTL32_Alloc(sizeof(HEADER_ITEM)*infoPtr->uNumItem);
1303 if (nItem == 0)
1304 memcpy (&infoPtr->items[1],&oldItems[0],(infoPtr->uNumItem-1)*sizeof(HEADER_ITEM));
1305 else
1306 {
1307 /* pre insert copy */
1308 memcpy (&infoPtr->items[0],&oldItems[0],nItem*sizeof(HEADER_ITEM));
1309
1310 /* post insert copy */
1311 if (nItem < infoPtr->uNumItem-1)
1312 memcpy (&infoPtr->items[nItem+1],&oldItems[nItem],(infoPtr->uNumItem - nItem)*sizeof(HEADER_ITEM));
1313 }
1314
1315 COMCTL32_Free (oldItems);
1316 }
1317
1318 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1319 lpItem->bDown = FALSE;
1320
1321 lpItem->cxy = ((phdi->mask & HDI_WIDTH) || (phdi->mask & HDI_HEIGHT)) ? phdi->cxy:0;
1322
1323 if (phdi->mask & HDI_TEXT)
1324 {
1325 if (!phdi->pszText) lpItem->pszText = NULL;
1326 else if (unicode)
1327 {
1328 if (phdi->pszText != LPSTR_TEXTCALLBACKW)
1329 {
1330 INT len;
1331
1332 len = lstrlenW(phdi->pszText);
1333 if (len == 0) lpItem->pszText = NULL; else
1334 {
1335 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1336 lstrcpyW(lpItem->pszText,phdi->pszText);
1337 }
1338 } else lpItem->pszText = LPSTR_TEXTCALLBACKW;
1339 } else
1340 {
1341 if ((LPSTR)phdi->pszText != LPSTR_TEXTCALLBACKA)
1342 {
1343 INT len;
1344
1345 len = lstrlenA((LPSTR)phdi->pszText);
1346 if (len == 0) lpItem->pszText = NULL; else
1347 {
1348 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1349 lstrcpyAtoW(lpItem->pszText,(LPSTR)phdi->pszText);
1350 }
1351 } else lpItem->pszText = LPSTR_TEXTCALLBACKW;
1352 }
1353 lpItem->cchTextMax = phdi->cchTextMax;
1354 } else
1355 {
1356 lpItem->pszText = NULL;
1357 lpItem->cchTextMax = 0;
1358 }
1359
1360 lpItem->fmt = (phdi->mask & HDI_FORMAT) ? phdi->fmt:HDF_LEFT;
1361 if (lpItem->fmt == 0) lpItem->fmt = HDF_LEFT;
1362
1363 lpItem->lParam = (phdi->mask & HDI_LPARAM) ? phdi->lParam:0;
1364
1365 lpItem->iImage = (phdi->mask & HDI_IMAGE) ? phdi->iImage:0;
1366
1367 lpItem->iOrder = (phdi->mask & HDI_ORDER) ? phdi->iOrder:-1;
1368
1369 lpItem->hbm = (phdi->mask & HDI_BITMAP) ? phdi->hbm:0;
1370
1371 if (phdi->mask & HDI_FILTER)
1372 {
1373 lpItem->type = phdi->type;
1374 lpItem->pvFilter = phdi->pvFilter;
1375 }
1376
1377 HEADER_SetItemBounds (hwnd,nItem);
1378 HEADER_Refresh(hwnd);
1379
1380 return nItem;
1381}
1382
1383static LRESULT
1384HEADER_Layout (HWND hwnd, WPARAM wParam, LPARAM lParam)
1385{
1386 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1387 LPHDLAYOUT lpLayout = (LPHDLAYOUT)lParam;
1388
1389 if (!lpLayout) return FALSE;
1390
1391 lpLayout->pwpos->hwnd = hwnd;
1392 lpLayout->pwpos->hwndInsertAfter = 0;
1393 lpLayout->pwpos->x = lpLayout->prc->left;
1394 lpLayout->pwpos->y = lpLayout->prc->top;
1395 lpLayout->pwpos->cx = lpLayout->prc->right - lpLayout->prc->left;
1396 if (GetWindowLongA (hwnd, GWL_STYLE) & HDS_HIDDEN)
1397 lpLayout->pwpos->cy = 0;
1398 else
1399 lpLayout->pwpos->cy = infoPtr->nHeight;
1400 lpLayout->pwpos->flags = SWP_NOZORDER;
1401
1402 return TRUE;
1403}
1404
1405
1406static LRESULT
1407HEADER_SetImageList (HWND hwnd, WPARAM wParam, LPARAM lParam)
1408{
1409 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1410 HIMAGELIST himlOld;
1411
1412 himlOld = infoPtr->himl;
1413 infoPtr->himl = (HIMAGELIST)lParam;
1414
1415 HEADER_Refresh(hwnd);
1416
1417 return (LRESULT)himlOld;
1418}
1419
1420
1421static LRESULT HEADER_SetItem(HWND hwnd,WPARAM wParam,LPARAM lParam,BOOL unicode)
1422{
1423 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1424 HDITEMW *phdi = (HDITEMW*)lParam;
1425 INT nItem = (INT)wParam;
1426 HEADER_ITEM *lpItem;
1427 HDC hdc;
1428
1429 if (phdi == NULL) return FALSE;
1430 if ((nItem < 0) || (nItem >= (INT)infoPtr->uNumItem)) return FALSE;
1431 if (phdi->mask == 0) return TRUE;
1432
1433 if (HEADER_SendItemChanging(hwnd,nItem)) return FALSE;
1434
1435 lpItem = (HEADER_ITEM*)&infoPtr->items[nItem];
1436
1437 if (phdi->mask & HDI_BITMAP) lpItem->hbm = phdi->hbm;
1438
1439 if (phdi->mask & HDI_FORMAT) lpItem->fmt = phdi->fmt;
1440
1441 if (phdi->mask & HDI_FILTER)
1442 {
1443 lpItem->type = lpItem->type;
1444 lpItem->pvFilter = lpItem->pvFilter;
1445 }
1446
1447 if (phdi->mask & (HDI_WIDTH | HDI_WIDTH)) lpItem->cxy = phdi->cxy;
1448
1449 if (phdi->mask & HDI_IMAGE) lpItem->iImage = phdi->iImage;
1450
1451 if (phdi->mask & HDI_LPARAM) lpItem->lParam = phdi->lParam;
1452
1453 if (phdi->mask & HDI_ORDER) lpItem->iOrder = phdi->iOrder;
1454
1455 if (phdi->mask & HDI_TEXT)
1456 {
1457 if (unicode)
1458 {
1459 if (phdi->pszText != LPSTR_TEXTCALLBACKW)
1460 {
1461 if (lpItem->pszText)
1462 {
1463 COMCTL32_Free(lpItem->pszText);
1464 lpItem->pszText = NULL;
1465 }
1466 if (phdi->pszText)
1467 {
1468 INT len = lstrlenW(phdi->pszText);
1469
1470 if (len)
1471 {
1472 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1473 lstrcpyW(lpItem->pszText,phdi->pszText);
1474 }
1475 }
1476 } else
1477 {
1478 if (lpItem->pszText != LPSTR_TEXTCALLBACKW) COMCTL32_Free(lpItem->pszText);
1479 lpItem->pszText = LPSTR_TEXTCALLBACKW;
1480 }
1481 } else
1482 {
1483 if ((LPSTR)phdi->pszText != LPSTR_TEXTCALLBACKA)
1484 {
1485 if (lpItem->pszText)
1486 {
1487 COMCTL32_Free (lpItem->pszText);
1488 lpItem->pszText = NULL;
1489 }
1490 if (phdi->pszText)
1491 {
1492 INT len = lstrlenA((LPSTR)phdi->pszText);
1493
1494 if (len)
1495 {
1496 lpItem->pszText = (WCHAR*)COMCTL32_Alloc((len+1)*sizeof(WCHAR));
1497 lstrcpyAtoW(lpItem->pszText,(LPSTR)phdi->pszText);
1498 }
1499 }
1500 } else
1501 {
1502 if (lpItem->pszText != LPSTR_TEXTCALLBACKW) COMCTL32_Free(lpItem->pszText);
1503 lpItem->pszText = LPSTR_TEXTCALLBACKW;
1504 }
1505 }
1506 }
1507
1508 HEADER_SendItemChanged(hwnd,nItem);
1509
1510 HEADER_SetItemBounds(hwnd,0);
1511 HEADER_Refresh(hwnd);
1512
1513 return TRUE;
1514}
1515
1516static LRESULT
1517HEADER_Create (HWND hwnd, WPARAM wParam, LPARAM lParam)
1518{
1519 HEADER_INFO *infoPtr;
1520 TEXTMETRICA tm;
1521 HFONT hOldFont;
1522 HDC hdc;
1523
1524 infoPtr = (HEADER_INFO*)initControl(hwnd,sizeof(HEADER_INFO));
1525
1526 infoPtr->uNumItem = 0;
1527 infoPtr->hFont = 0;
1528 infoPtr->items = 0;
1529 infoPtr->hcurArrow = LoadCursorA(0,IDC_ARROWA);
1530 infoPtr->hcurDivider = LoadCursorA(COMCTL32_hModule,MAKEINTRESOURCEA(IDC_COMCTL32_DRAGHLINE));
1531 infoPtr->hcurDivopen = LoadCursorA(COMCTL32_hModule,MAKEINTRESOURCEA(IDC_COMCTL32_SPLITHLINE));
1532 infoPtr->bCaptured = FALSE;
1533 infoPtr->bPressed = FALSE;
1534 infoPtr->bTracking = FALSE;
1535 infoPtr->bDragDrop = FALSE;
1536 infoPtr->bTimer = FALSE;
1537 infoPtr->iMoveItem = 0;
1538 infoPtr->himl = 0;
1539 infoPtr->dragImage = 0;
1540 infoPtr->iHotItem = -1;
1541 infoPtr->xBmpMargin = 3*GetSystemMetrics(SM_CXEDGE);
1542
1543 hdc = GetDC (hwnd);
1544 hOldFont = SelectObject (hdc, GetStockObject (SYSTEM_FONT));
1545 GetTextMetricsA (hdc, &tm);
1546 infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
1547 SelectObject (hdc, hOldFont);
1548 ReleaseDC (hwnd, hdc);
1549
1550 return 0;
1551}
1552
1553
1554static LRESULT
1555HEADER_Destroy (HWND hwnd, WPARAM wParam, LPARAM lParam)
1556{
1557 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1558 HEADER_ITEM *lpItem;
1559 INT nItem;
1560
1561 if (infoPtr->items) {
1562 lpItem = (HEADER_ITEM*)infoPtr->items;
1563 for (nItem = 0; nItem < infoPtr->uNumItem; nItem++, lpItem++) {
1564 if ((lpItem->pszText) && (lpItem->pszText != LPSTR_TEXTCALLBACKW))
1565 COMCTL32_Free (lpItem->pszText);
1566 }
1567 COMCTL32_Free (infoPtr->items);
1568 }
1569
1570 if (infoPtr->himl)
1571 ImageList_Destroy (infoPtr->himl);
1572
1573 doneControl(hwnd);
1574
1575 return 0;
1576}
1577
1578static LRESULT
1579HEADER_EraseBackground(HWND hwnd,WPARAM wParam,LPARAM lParam)
1580{
1581 return TRUE;
1582}
1583
1584static LRESULT
1585HEADER_GetDlgCode(HWND hwnd,WPARAM wParam,LPARAM lParam)
1586{
1587 return DLGC_WANTTAB | DLGC_WANTARROWS;
1588}
1589
1590static LRESULT
1591HEADER_GetFont (HWND hwnd)
1592{
1593 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1594
1595 return (LRESULT)infoPtr->hFont;
1596}
1597
1598
1599static LRESULT
1600HEADER_LButtonDblClk (HWND hwnd, WPARAM wParam, LPARAM lParam)
1601{
1602 POINT pt;
1603 UINT flags;
1604 INT nItem;
1605
1606 pt.x = (INT)LOWORD(lParam);
1607 pt.y = (INT)HIWORD(lParam);
1608 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1609
1610 if ((GetWindowLongA (hwnd, GWL_STYLE) & HDS_BUTTONS) && (flags == HHT_ONHEADER))
1611 HEADER_SendItemDblClick(hwnd,nItem,0);
1612 else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
1613 HEADER_SendDividerDblClick(hwnd,nItem,0);
1614
1615 return 0;
1616}
1617
1618
1619static LRESULT
1620HEADER_LButtonDown (HWND hwnd, WPARAM wParam, LPARAM lParam)
1621{
1622 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1623 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1624 POINT pt;
1625 UINT flags;
1626 INT nItem;
1627 HDC hdc;
1628
1629 pt.x = (SHORT)LOWORD(lParam);
1630 pt.y = (SHORT)HIWORD(lParam);
1631 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1632
1633 if ((dwStyle & HDS_BUTTONS) && (flags == HHT_ONHEADER))
1634 {
1635 SetCapture (hwnd);
1636 infoPtr->bCaptured = TRUE;
1637 infoPtr->bPressed = TRUE;
1638 infoPtr->iMoveItem = nItem;
1639 infoPtr->dragStart = pt;
1640 infoPtr->iDragItem = nItem;
1641
1642 infoPtr->items[nItem].bDown = TRUE;
1643
1644 /* Send WM_CUSTOMDRAW */
1645 hdc = GetDC (hwnd);
1646 HEADER_RefreshItem (hwnd, hdc, nItem);
1647 ReleaseDC (hwnd, hdc);
1648
1649 } else if ((flags == HHT_ONDIVIDER) || (flags == HHT_ONDIVOPEN))
1650 {
1651 if (!(HEADER_SendBeginTrack(hwnd,nItem,0)))
1652 {
1653 SetCapture (hwnd);
1654 infoPtr->bCaptured = TRUE;
1655 infoPtr->bTracking = TRUE;
1656 infoPtr->bTrackOpen = flags == HHT_ONDIVOPEN;
1657 infoPtr->iMoveItem = nItem;
1658 infoPtr->nOldWidth = infoPtr->items[nItem].cxy;
1659 infoPtr->xTrackOffset = infoPtr->items[nItem].rect.right - pt.x;
1660
1661 if (!(dwStyle & HDS_FULLDRAG))
1662 {
1663 infoPtr->xOldTrack = infoPtr->items[nItem].rect.right;
1664 hdc = GetDC (hwnd);
1665 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1666 ReleaseDC (hwnd, hdc);
1667 }
1668
1669 }
1670 }
1671
1672 return 0;
1673}
1674
1675
1676static LRESULT
1677HEADER_LButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
1678{
1679 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1680 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1681 POINT pt;
1682 UINT flags;
1683 INT nItem, nWidth;
1684 HDC hdc;
1685
1686 pt.x = (SHORT)LOWORD(lParam);
1687 pt.y = (SHORT)HIWORD(lParam);
1688 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1689
1690 if (infoPtr->bPressed)
1691 {
1692 if (infoPtr->bDragDrop)
1693 {
1694 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1695 infoPtr->bDragDrop = FALSE;
1696 ImageList_Destroy(infoPtr->dragImage);
1697 infoPtr->dragImage = NULL;
1698
1699 if (!HEADER_SendDragNotify(hwnd,HDN_ENDDRAG,infoPtr->iMoveItem,0) && (infoPtr->iDragItem != infoPtr->iMoveItem) && (infoPtr->iDragItem != infoPtr->iMoveItem+1) && (infoPtr->iDragItem != -1))
1700 {
1701 HEADER_ITEM tmpItem = infoPtr->items[infoPtr->iMoveItem];;
1702
1703 //CB: notificatons??
1704
1705 if (infoPtr->iDragItem > infoPtr->iMoveItem)
1706 {
1707 INT x ;
1708
1709 for (x = infoPtr->iMoveItem;x < infoPtr->iDragItem-1;x++)
1710 memcpy(&infoPtr->items[x],&infoPtr->items[x+1],sizeof(HEADER_ITEM));
1711
1712 infoPtr->items[infoPtr->iDragItem-1] = tmpItem;
1713 } else
1714 {
1715 INT x;
1716
1717 for (x = infoPtr->iMoveItem;x > infoPtr->iDragItem;x--)
1718 memcpy(&infoPtr->items[x],&infoPtr->items[x-1],sizeof(HEADER_ITEM));
1719
1720 infoPtr->items[infoPtr->iDragItem] = tmpItem;
1721 }
1722
1723 HEADER_SetItemBounds(hwnd,0);
1724 }
1725 HEADER_Refresh(hwnd);
1726 } else if (PtInRect(&infoPtr->items[infoPtr->iMoveItem].rect,pt))
1727 {
1728 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1729 hdc = GetDC(hwnd);
1730 HEADER_RefreshItem(hwnd,hdc,infoPtr->iMoveItem);
1731 ReleaseDC(hwnd,hdc);
1732
1733 HEADER_SendItemClick(hwnd,infoPtr->iMoveItem,0);
1734 }
1735 infoPtr->bPressed = FALSE;
1736 } else if (infoPtr->bTracking)
1737 {
1738 infoPtr->bTracking = FALSE;
1739
1740 HEADER_SendEndTrack(hwnd,infoPtr->iMoveItem,0);
1741
1742 if (!(dwStyle & HDS_FULLDRAG))
1743 {
1744 hdc = GetDC (hwnd);
1745 HEADER_DrawTrackLine (hwnd, hdc, infoPtr->xOldTrack);
1746 ReleaseDC (hwnd, hdc);
1747 if (HEADER_SendItemChanging(hwnd,infoPtr->iMoveItem))
1748 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1749 else
1750 {
1751 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1752 if (nWidth < MIN_ITEMWIDTH) nWidth = MIN_ITEMWIDTH;
1753
1754 if (infoPtr->nOldWidth != nWidth)
1755 {
1756 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1757
1758 HEADER_SetItemBounds (hwnd,infoPtr->iMoveItem);
1759 HEADER_Refresh(hwnd);
1760 HEADER_SendItemChanged(hwnd,infoPtr->iMoveItem);
1761 }
1762 }
1763 }
1764 }
1765
1766 if (infoPtr->bCaptured)
1767 {
1768 infoPtr->bCaptured = FALSE;
1769 ReleaseCapture();
1770 sendNotify(hwnd,NM_RELEASEDCAPTURE);
1771 }
1772
1773 return 0;
1774}
1775
1776static INT
1777HEADER_DragHitTest(HWND hwnd,HEADER_INFO* infoPtr,POINT pt)
1778{
1779 RECT rect;
1780 INT x,xDrag;
1781
1782 GetClientRect(hwnd,&rect);
1783 if (pt.y < rect.top || pt.y > rect.bottom) return -1;
1784
1785 xDrag = infoPtr->items[infoPtr->iMoveItem].rect.left+pt.x-infoPtr->dragStart.x;
1786
1787 if (xDrag < infoPtr->items[0].rect.left) return 0;
1788
1789 for (x = 0;x < infoPtr->uNumItem;x++)
1790 {
1791 if ((xDrag >= infoPtr->items[x].rect.left) && (xDrag <= infoPtr->items[x].rect.right)) return x;
1792 }
1793
1794 return infoPtr->uNumItem;
1795}
1796
1797static LRESULT
1798HEADER_MouseMove (HWND hwnd, WPARAM wParam, LPARAM lParam)
1799{
1800 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
1801 DWORD dwStyle = GetWindowLongA (hwnd, GWL_STYLE);
1802 POINT pt;
1803 UINT flags;
1804 INT nItem, nWidth;
1805 HDC hdc;
1806
1807 pt.x = (SHORT)LOWORD(lParam);
1808 pt.y = (SHORT)HIWORD(lParam);
1809 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
1810
1811 if ((dwStyle & HDS_BUTTONS) && (dwStyle & HDS_HOTTRACK))
1812 {
1813 INT newItem;
1814
1815 if (infoPtr->bCaptured && infoPtr->bPressed && PtInRect(&infoPtr->items[infoPtr->iMoveItem].rect,pt))
1816 newItem = infoPtr->iMoveItem;
1817 else
1818 {
1819 if (flags & (HHT_ONHEADER | HHT_ONDIVIDER | HHT_ONDIVOPEN))
1820 newItem = nItem;
1821 else
1822 newItem = -1;
1823 }
1824 if (newItem != infoPtr->iHotItem)
1825 {
1826 infoPtr->iHotItem = newItem;
1827 HEADER_Refresh(hwnd);
1828 }
1829 if (!infoPtr->bTimer && (infoPtr->iHotItem != -1))
1830 {
1831 infoPtr->bTimer = TRUE;
1832 SetTimer(hwnd,TIMER_ID,TIMER_MS,NULL);
1833 } else if (infoPtr->bTimer && (infoPtr->iHotItem == -1))
1834 {
1835 KillTimer(hwnd,TIMER_ID);
1836 infoPtr->bTimer = FALSE;
1837 }
1838 }
1839
1840 if (infoPtr->bCaptured)
1841 {
1842 if (infoPtr->bPressed)
1843 {
1844 if ((dwStyle & HDS_DRAGDROP) && (infoPtr->uNumItem > 1) && (infoPtr->bDragDrop || !HEADER_SendDragNotify(hwnd,HDN_BEGINDRAG,infoPtr->iMoveItem,0)))
1845 {
1846 if (!infoPtr->bDragDrop)
1847 {
1848 infoPtr->bDragDrop = TRUE;
1849 infoPtr->dragImage = (HIMAGELIST)HEADER_CreateDragImage(hwnd,infoPtr->iMoveItem,0);
1850 }
1851 infoPtr->dragPos = pt;
1852 infoPtr->iDragItem = HEADER_DragHitTest(hwnd,infoPtr,pt);
1853 HEADER_Refresh(hwnd);
1854 } else
1855 {
1856 BOOL newDown;
1857
1858 if (PtInRect(&infoPtr->items[infoPtr->iMoveItem].rect,pt))
1859 newDown = TRUE;
1860 else
1861 newDown = FALSE;
1862
1863 if (newDown != infoPtr->items[infoPtr->iMoveItem].bDown)
1864 {
1865 infoPtr->items[infoPtr->iMoveItem].bDown = newDown;
1866 hdc = GetDC (hwnd);
1867 HEADER_RefreshItem (hwnd, hdc, infoPtr->iMoveItem);
1868 ReleaseDC (hwnd, hdc);
1869 }
1870 }
1871 } else if (infoPtr->bTracking)
1872 {
1873 if (dwStyle & HDS_FULLDRAG)
1874 {
1875 if (HEADER_SendItemChanging(hwnd,infoPtr->iMoveItem))
1876 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1877 else
1878 {
1879 nWidth = pt.x - infoPtr->items[infoPtr->iMoveItem].rect.left + infoPtr->xTrackOffset;
1880 if (nWidth < MIN_ITEMWIDTH) nWidth = MIN_ITEMWIDTH;
1881 infoPtr->items[infoPtr->iMoveItem].cxy = nWidth;
1882 HEADER_SendItemChanged(hwnd,infoPtr->iMoveItem);
1883 }
1884 HEADER_SetItemBounds (hwnd,infoPtr->iMoveItem);
1885 HEADER_Refresh(hwnd);
1886 } else
1887 {
1888 INT lastPos = infoPtr->xOldTrack;
1889
1890 hdc = GetDC (hwnd);
1891 infoPtr->xOldTrack = pt.x + infoPtr->xTrackOffset;
1892 if (infoPtr->xOldTrack < infoPtr->items[infoPtr->iMoveItem].rect.left+MIN_ITEMWIDTH)
1893 infoPtr->xOldTrack = infoPtr->items[infoPtr->iMoveItem].rect.left+MIN_ITEMWIDTH;
1894 infoPtr->items[infoPtr->iMoveItem].cxy =
1895 infoPtr->xOldTrack-infoPtr->items[infoPtr->iMoveItem].rect.left;
1896 if (lastPos != infoPtr->xOldTrack)
1897 {
1898 HEADER_DrawTrackLine(hwnd,hdc,lastPos);
1899 HEADER_DrawTrackLine(hwnd,hdc,infoPtr->xOldTrack);
1900 }
1901 ReleaseDC (hwnd, hdc);
1902 }
1903
1904 HEADER_SendTrack(hwnd,infoPtr->iMoveItem);
1905 }
1906 }
1907
1908 return 0;
1909}
1910
1911static LRESULT
1912HEADER_Size(HWND hwnd,WPARAM wParam,LPARAM lParam)
1913{
1914 HEADER_SetItemBounds(hwnd,0);
1915
1916 return DefWindowProcA(hwnd,WM_SIZE,wParam,lParam);
1917}
1918
1919static LRESULT
1920HEADER_Timer(HWND hwnd,WPARAM wParam,LPARAM lParam)
1921{
1922 POINT point;
1923 RECT rect;
1924
1925 GetCursorPos(&point);
1926 ScreenToClient(hwnd,&point);
1927 GetClientRect(hwnd,&rect);
1928 if (!PtInRect(&rect,point))
1929 {
1930 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1931
1932 infoPtr->iHotItem = -1;
1933 infoPtr->bTimer = FALSE;
1934 HEADER_Refresh(hwnd);
1935
1936 KillTimer(hwnd,TIMER_ID);
1937 }
1938
1939 return 0;
1940}
1941
1942static LRESULT
1943HEADER_KeyDown(HWND hwnd,WPARAM wParam,LPARAM lParam)
1944{
1945 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1946 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1947 HDC hdc;
1948
1949 if ((wParam == VK_ESCAPE) && infoPtr->bCaptured)
1950 {
1951 if (infoPtr->bPressed && infoPtr->bDragDrop)
1952 {
1953 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
1954 infoPtr->bPressed = FALSE;
1955 infoPtr->bDragDrop = FALSE;
1956 ImageList_Destroy(infoPtr->dragImage);
1957 infoPtr->dragImage = NULL;
1958
1959 HEADER_SendDragNotify(hwnd,HDN_ENDDRAG,infoPtr->iMoveItem,0);
1960 HEADER_Refresh(hwnd);
1961
1962 } else if (infoPtr->bTracking)
1963 {
1964 infoPtr->bTracking = FALSE;
1965
1966 HEADER_SendEndTrack(hwnd,infoPtr->iMoveItem,0);
1967
1968 if (dwStyle & HDS_FULLDRAG)
1969 {
1970 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
1971 HEADER_Refresh(hwnd);
1972 } else
1973 {
1974 hdc = GetDC(hwnd);
1975 HEADER_DrawTrackLine(hwnd,hdc,infoPtr->xOldTrack);
1976 ReleaseDC(hwnd,hdc);
1977 }
1978 }
1979
1980 infoPtr->bCaptured = FALSE;
1981 ReleaseCapture();
1982 sendNotify(hwnd,NM_RELEASEDCAPTURE);
1983
1984 return TRUE;
1985 }
1986
1987 return DefWindowProcA(WM_KEYDOWN,hwnd,wParam,lParam);
1988}
1989
1990static LRESULT
1991HEADER_CaptureChanged(HWND hwnd,WPARAM wParam,LPARAM lParam)
1992{
1993 HEADER_INFO *infoPtr = HEADER_GetInfoPtr(hwnd);
1994 DWORD dwStyle = GetWindowLongA(hwnd,GWL_STYLE);
1995 HDC hdc;
1996
1997 if (infoPtr->bCaptured && infoPtr->bPressed)
1998 {
1999 infoPtr->items[infoPtr->iMoveItem].bDown = FALSE;
2000 infoPtr->bPressed = FALSE;
2001 if (infoPtr->bDragDrop)
2002 {
2003 infoPtr->bDragDrop = FALSE;
2004 ImageList_Destroy(infoPtr->dragImage);
2005 infoPtr->dragImage = NULL;
2006
2007 HEADER_SendDragNotify(hwnd,HDN_ENDDRAG,infoPtr->iMoveItem,0);
2008 HEADER_Refresh(hwnd);
2009 } else
2010 {
2011 hdc = GetDC(hwnd);
2012 HEADER_RefreshItem(hwnd,hdc,infoPtr->iMoveItem);
2013 ReleaseDC(hwnd,hdc);
2014 }
2015 } else if (infoPtr->bCaptured && infoPtr->bTracking)
2016 {
2017 infoPtr->bTracking = FALSE;
2018
2019 HEADER_SendEndTrack(hwnd,infoPtr->iMoveItem,0);
2020
2021 if (dwStyle & HDS_FULLDRAG)
2022 {
2023 infoPtr->items[infoPtr->iMoveItem].cxy = infoPtr->nOldWidth;
2024 HEADER_Refresh(hwnd);
2025 } else
2026 {
2027 hdc = GetDC(hwnd);
2028 HEADER_DrawTrackLine(hwnd,hdc,infoPtr->xOldTrack);
2029 ReleaseDC(hwnd,hdc);
2030 }
2031 }
2032
2033 infoPtr->bCaptured = FALSE;
2034
2035 return 0;
2036}
2037
2038static LRESULT
2039HEADER_Paint (HWND hwnd, WPARAM wParam)
2040{
2041 HDC hdc;
2042 PAINTSTRUCT ps;
2043
2044 hdc = wParam==0 ? BeginPaint (hwnd, &ps) : (HDC)wParam;
2045 HEADER_Draw (hwnd, hdc);
2046 if(!wParam)
2047 EndPaint (hwnd, &ps);
2048
2049 return 0;
2050}
2051
2052
2053static LRESULT
2054HEADER_RButtonUp (HWND hwnd, WPARAM wParam, LPARAM lParam)
2055{
2056 sendNotify(hwnd,NM_RCLICK);
2057
2058 return DefWindowProcA(hwnd,WM_RBUTTONUP,wParam,lParam);
2059}
2060
2061
2062static LRESULT
2063HEADER_SetCursor (HWND hwnd, WPARAM wParam, LPARAM lParam)
2064{
2065 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
2066 POINT pt;
2067 UINT flags;
2068 INT nItem;
2069
2070 GetCursorPos (&pt);
2071 ScreenToClient (hwnd, &pt);
2072
2073 HEADER_InternalHitTest (hwnd, &pt, &flags, &nItem);
2074
2075 if (infoPtr->bCaptured)
2076 {
2077 if (infoPtr->bTracking)
2078 {
2079 if (infoPtr->bTrackOpen) SetCursor(infoPtr->hcurDivopen);
2080 else SetCursor(infoPtr->hcurDivider);
2081 } else SetCursor(infoPtr->hcurArrow);
2082
2083 return TRUE;
2084 }
2085
2086 if (flags == HHT_ONDIVIDER)
2087 SetCursor (infoPtr->hcurDivider);
2088 else if (flags == HHT_ONDIVOPEN)
2089 SetCursor (infoPtr->hcurDivopen);
2090 else
2091 SetCursor (infoPtr->hcurArrow);
2092
2093 return TRUE;
2094}
2095
2096
2097static LRESULT
2098HEADER_SetFont (HWND hwnd, WPARAM wParam, LPARAM lParam)
2099{
2100 HEADER_INFO *infoPtr = HEADER_GetInfoPtr (hwnd);
2101 TEXTMETRICA tm;
2102 HFONT hFont, hOldFont;
2103 HDC hdc;
2104
2105 infoPtr->hFont = (HFONT)wParam;
2106
2107 hFont = infoPtr->hFont ? infoPtr->hFont : GetStockObject (SYSTEM_FONT);
2108
2109 hdc = GetDC (hwnd);
2110 hOldFont = SelectObject (hdc, hFont);
2111 GetTextMetricsA (hdc, &tm);
2112 infoPtr->nHeight = tm.tmHeight + VERT_BORDER;
2113 SelectObject (hdc, hOldFont);
2114 ReleaseDC (hwnd, hdc);
2115
2116 if (lParam) HEADER_Refresh(hwnd);
2117
2118 return 0;
2119}
2120
2121
2122static LRESULT WINAPI
2123HEADER_WindowProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
2124{
2125 switch (msg)
2126 {
2127 case HDM_CLEARFILTER:
2128 return HEADER_ClearFilter(hwnd,wParam,lParam);
2129
2130 case HDM_CREATEDRAGIMAGE:
2131 return HEADER_CreateDragImage (hwnd,wParam,lParam);
2132
2133 case HDM_DELETEITEM:
2134 return HEADER_DeleteItem (hwnd, wParam);
2135
2136 case HDM_EDITFILTER:
2137 return HEADER_EditFilter(hwnd,wParam,lParam);
2138
2139 case HDM_GETBITMAPMARGIN:
2140 return HEADER_GetBitmapMargin(hwnd,wParam,lParam);
2141
2142 case HDM_GETIMAGELIST:
2143 return HEADER_GetImageList (hwnd);
2144
2145 case HDM_GETITEMA:
2146 return HEADER_GetItem(hwnd,wParam,lParam,FALSE);
2147
2148 case HDM_GETITEMW:
2149 return HEADER_GetItem(hwnd,wParam,lParam,TRUE);
2150
2151 case HDM_GETITEMCOUNT:
2152 return HEADER_GetItemCount (hwnd);
2153
2154 case HDM_GETITEMRECT:
2155 return HEADER_GetItemRect (hwnd, wParam, lParam);
2156
2157 case HDM_GETORDERARRAY:
2158 return HEADER_GetOrderArray(hwnd,wParam,lParam);
2159
2160 case HDM_HITTEST:
2161 return HEADER_HitTest (hwnd, wParam, lParam);
2162
2163 case HDM_INSERTITEMA:
2164 return HEADER_InsertItem(hwnd,wParam,lParam,FALSE);
2165
2166 case HDM_INSERTITEMW:
2167 return HEADER_InsertItem(hwnd,wParam,lParam,TRUE);
2168
2169 case HDM_LAYOUT:
2170 return HEADER_Layout (hwnd, wParam, lParam);
2171
2172 case HDM_ORDERTOINDEX:
2173 return HEADER_OrderToIndex(hwnd,wParam,lParam);
2174
2175 case HDM_SETBITMAPMARGIN:
2176 return HEADER_SetBitmapMargin(hwnd,wParam,lParam);
2177
2178 case HDM_SETFILTERCHANGETIMEOUT:
2179 return HEADER_SetFilterChangeTimeout(hwnd,wParam,lParam);
2180
2181 case HDM_SETHOTDIVIDER:
2182 return HEADER_SetHotDivider(hwnd,wParam,lParam);
2183
2184 case HDM_SETIMAGELIST:
2185 return HEADER_SetImageList (hwnd, wParam, lParam);
2186
2187 case HDM_SETITEMA:
2188 return HEADER_SetItem(hwnd,wParam,lParam,FALSE);
2189
2190 case HDM_SETITEMW:
2191 return HEADER_SetItem(hwnd,wParam,lParam,TRUE);
2192
2193 case HDM_SETORDERARRAY:
2194 return HEADER_SetOrderArray(hwnd,wParam,lParam);
2195
2196 case WM_CAPTURECHANGED:
2197 return HEADER_CaptureChanged(hwnd,wParam,lParam);
2198
2199 case WM_CREATE:
2200 return HEADER_Create (hwnd, wParam, lParam);
2201
2202 case WM_DESTROY:
2203 return HEADER_Destroy (hwnd, wParam, lParam);
2204
2205 case WM_ERASEBKGND:
2206 return HEADER_EraseBackground(hwnd,wParam,lParam);
2207
2208 case WM_GETDLGCODE:
2209 return HEADER_GetDlgCode(hwnd,wParam,lParam);
2210
2211 case WM_GETFONT:
2212 return HEADER_GetFont (hwnd);
2213
2214 case WM_KEYDOWN:
2215 return HEADER_KeyDown(hwnd,wParam,lParam);
2216
2217 case WM_LBUTTONDBLCLK:
2218 return HEADER_LButtonDblClk (hwnd, wParam, lParam);
2219
2220 case WM_LBUTTONDOWN:
2221 return HEADER_LButtonDown (hwnd, wParam, lParam);
2222
2223 case WM_LBUTTONUP:
2224 return HEADER_LButtonUp (hwnd, wParam, lParam);
2225
2226 case WM_MOUSEMOVE:
2227 return HEADER_MouseMove (hwnd, wParam, lParam);
2228
2229 case WM_PAINT:
2230 return HEADER_Paint(hwnd,wParam);
2231
2232 case WM_RBUTTONUP:
2233 return HEADER_RButtonUp (hwnd, wParam, lParam);
2234
2235 case WM_SETCURSOR:
2236 return HEADER_SetCursor (hwnd, wParam, lParam);
2237
2238 case WM_SETFONT:
2239 return HEADER_SetFont (hwnd, wParam, lParam);
2240
2241 case WM_SIZE:
2242 return HEADER_Size(hwnd,wParam,lParam);
2243
2244 case WM_TIMER:
2245 return HEADER_Timer(hwnd,wParam,lParam);
2246
2247 default:
2248 //if (msg >= WM_USER)
2249 // ERR (header, "unknown msg %04x wp=%04x lp=%08lx\n",
2250 // msg, wParam, lParam );
2251 return defComCtl32ProcA (hwnd, msg, wParam, lParam);
2252 }
2253 return 0;
2254}
2255
2256
2257VOID
2258HEADER_Register (VOID)
2259{
2260 WNDCLASSA wndClass;
2261
2262 ZeroMemory (&wndClass, sizeof(WNDCLASSA));
2263 wndClass.style = CS_GLOBALCLASS | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
2264 wndClass.lpfnWndProc = (WNDPROC)HEADER_WindowProc;
2265 wndClass.cbClsExtra = 0;
2266 wndClass.cbWndExtra = sizeof(HEADER_INFO *);
2267 wndClass.hCursor = LoadCursorA (0, IDC_ARROWA);
2268 wndClass.lpszClassName = WC_HEADERA;
2269
2270 RegisterClassA (&wndClass);
2271}
2272
2273
2274VOID
2275HEADER_Unregister (VOID)
2276{
2277 UnregisterClassA (WC_HEADERA, (HINSTANCE)NULL);
2278}
2279
Note: See TracBrowser for help on using the repository browser.