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

Last change on this file since 2895 was 2895, checked in by cbratschi, 26 years ago

unicode and other changes

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