From: Huw Davies Subject: [PATCH 2/2] comctl32: Add support for the sort arrows. Message-Id: <1476889707-75429-2-git-send-email-huw@codeweavers.com> Date: Wed, 19 Oct 2016 16:08:27 +0100 Signed-off-by: Huw Davies --- dlls/comctl32/header.c | 98 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 19 deletions(-) diff --git a/dlls/comctl32/header.c b/dlls/comctl32/header.c index 224ff9e..0206e3c 100644 --- a/dlls/comctl32/header.c +++ b/dlls/comctl32/header.c @@ -326,6 +326,48 @@ HEADER_DrawItemFrame(HEADER_INFO *infoPtr, HDC hdc, RECT *r, const HEADER_ITEM * } } +/* Create a region for the sort arrow with its bounding rect's top-left + co-ord x,y and its height h. */ +static HRGN create_sort_arrow( INT x, INT y, INT h, BOOL is_up ) +{ + char buffer[256]; + RGNDATA *data = (RGNDATA *)buffer; + DWORD size = FIELD_OFFSET(RGNDATA, Buffer[h * sizeof(RECT)]); + INT i, yinc = 1; + HRGN rgn; + + if (size > sizeof(buffer)) + { + data = HeapAlloc( GetProcessHeap(), 0, size ); + if (!data) return NULL; + } + data->rdh.dwSize = sizeof(data->rdh); + data->rdh.iType = RDH_RECTANGLES; + data->rdh.nCount = 0; + data->rdh.nRgnSize = h * sizeof(RECT); + + if (!is_up) + { + y += h - 1; + yinc = -1; + } + + x += h - 1; /* set x to the centre */ + + for (i = 0; i < h; i++, y += yinc) + { + RECT *rect = (RECT *)data->Buffer + data->rdh.nCount; + rect->left = x - i; + rect->top = y; + rect->right = x + i + 1; + rect->bottom = y + 1; + data->rdh.nCount++; + } + rgn = ExtCreateRegion( NULL, size, data ); + if (data != (RGNDATA *)buffer) HeapFree( GetProcessHeap(), 0, data ); + return rgn; +} + static INT HEADER_DrawItem (HEADER_INFO *infoPtr, HDC hdc, INT iItem, BOOL bHotTrack, LRESULT lCDFlags) { @@ -413,10 +455,11 @@ HEADER_DrawItem (HEADER_INFO *infoPtr, HDC hdc, INT iItem, BOOL bHotTrack, LRESU INT cx, tx, ix, bx; UINT cw, tw, iw, bw; INT img_cx, img_cy; + INT sort_w, sort_x, sort_h; BITMAP bmp; HEADER_PrepareCallbackItems(infoPtr, iItem, HDI_TEXT|HDI_IMAGE); - cw = iw = bw = 0; + cw = iw = bw = sort_w = 0; rw = r.right - r.left; rh = r.bottom - r.top; @@ -435,23 +478,28 @@ HEADER_DrawItem (HEADER_INFO *infoPtr, HDC hdc, INT iItem, BOOL bHotTrack, LRESU cw = textRect.right - textRect.left + 2 * infoPtr->iMargin; } - if ((phdi->fmt & HDF_IMAGE) && ImageList_GetIconSize( infoPtr->himl, &img_cx, &img_cy )) { - iw = img_cx + 2 * infoPtr->iMargin; - x = &ix; - w = &iw; - } - - if ((phdi->fmt & HDF_BITMAP) && (phdi->hbm)) { - GetObjectW (phdi->hbm, sizeof(BITMAP), &bmp); - bw = bmp.bmWidth + 2 * infoPtr->iMargin; - if (!iw) { - x = &bx; - w = &bw; - } - } + if (phdi->fmt & (HDF_SORTUP | HDF_SORTDOWN)) { + sort_h = MulDiv( infoPtr->nHeight - VERT_BORDER, 4, 13 ); + sort_w = 2 * sort_h - 1 + infoPtr->iMargin * 2; + cw += sort_w; + } else { /* sort arrows take precedent over images/bitmaps */ + if ((phdi->fmt & HDF_IMAGE) && ImageList_GetIconSize( infoPtr->himl, &img_cx, &img_cy )) { + iw = img_cx + 2 * infoPtr->iMargin; + x = &ix; + w = &iw; + } - if (bw || iw) - cw += *w; + if ((phdi->fmt & HDF_BITMAP) && (phdi->hbm)) { + GetObjectW (phdi->hbm, sizeof(BITMAP), &bmp); + bw = bmp.bmWidth + 2 * infoPtr->iMargin; + if (!iw) { + x = &bx; + w = &bw; + } + } + if (bw || iw) + cw += *w; + } /* align cx using the unclipped cw */ if ((phdi->fmt & HDF_JUSTIFYMASK) == HDF_LEFT) @@ -470,7 +518,10 @@ HEADER_DrawItem (HEADER_INFO *infoPtr, HDC hdc, INT iItem, BOOL bHotTrack, LRESU tx = cx + infoPtr->iMargin; /* since cw might have changed we have to recalculate tw */ tw = cw - infoPtr->iMargin * 2; - + + tw -= sort_w; + sort_x = cx + tw + infoPtr->iMargin * 3; + if (iw || bw) { tw -= *w; if (phdi->fmt & HDF_BITMAP_ON_RIGHT) { @@ -494,11 +545,20 @@ HEADER_DrawItem (HEADER_INFO *infoPtr, HDC hdc, INT iItem, BOOL bHotTrack, LRESU bx = cx + cw + infoPtr->iMargin; } - if (iw || bw) { + if (sort_w || iw || bw) { HDC hClipDC = GetDC(infoPtr->hwndSelf); HRGN hClipRgn = CreateRectRgn(r.left, r.top, r.right, r.bottom); SelectClipRgn(hClipDC, hClipRgn); + if (sort_w) { + HRGN arrow = create_sort_arrow( sort_x, r.top + (rh - sort_h) / 2, + sort_h, phdi->fmt & HDF_SORTUP ); + if (arrow) { + FillRgn( hClipDC, arrow, GetSysColorBrush( COLOR_GRAYTEXT ) ); + DeleteObject( arrow ); + } + } + if (bw) { HDC hdcBitmap = CreateCompatibleDC (hClipDC); SelectObject (hdcBitmap, phdi->hbm); -- 2.8.2