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

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

Corel 20000317 merge, ccbase finished, bug fixes

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