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

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

bug fixes and improvements

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