From 036dcf167ecd78ced51ae0f6a5332426093a5b2b Mon Sep 17 00:00:00 2001 From: Vitaliy Margolen Date: Tue, 2 Dec 2003 03:31:44 +0000 Subject: [PATCH] - Fix drawing of HotTracked tabs & buttons. - More tab size fixes in different styles. - Don't use new padding until style changes. - Fix left alignment of labels &| icons. - Don't draw over UpDown control. - Fully erase tabs when scrolling. - More tests. --- dlls/comctl32/tab.c | 382 +++++++++++++++++++++----------------- dlls/comctl32/tests/tab.c | 92 ++++++--- 2 files changed, 275 insertions(+), 199 deletions(-) diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c index ea7410457e8..59ad29a765e 100644 --- a/dlls/comctl32/tab.c +++ b/dlls/comctl32/tab.c @@ -4,6 +4,7 @@ * Copyright 1998 Anders Carlsson * Copyright 1999 Alex Priem * Copyright 1999 Francis Beaudet + * Copyright 2003 Vitaliy Margolen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -67,6 +68,8 @@ typedef struct INT tabMinWidth; /* minimum width of items */ USHORT uHItemPadding; /* amount of horizontal padding, in pixels */ USHORT uVItemPadding; /* amount of vertical padding, in pixels */ + USHORT uHItemPadding_s; /* Set amount of horizontal padding, in pixels */ + USHORT uVItemPadding_s; /* Set amount of vertical padding, in pixels */ HFONT hFont; /* handle to the current font */ HCURSOR hcurArrow; /* handle to the current cursor */ HIMAGELIST himl; /* handle to a image list (may be 0) */ @@ -272,8 +275,8 @@ TAB_SetPadding (HWND hwnd, WPARAM wParam, LPARAM lParam) TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); if (infoPtr == NULL) return 0; - infoPtr->uHItemPadding=LOWORD(lParam); - infoPtr->uVItemPadding=HIWORD(lParam); + infoPtr->uHItemPadding_s=LOWORD(lParam); + infoPtr->uVItemPadding_s=HIWORD(lParam); return 0; } @@ -318,14 +321,13 @@ static BOOL TAB_InternalGetItemRect( if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) { itemRect->bottom = clientRect.bottom - - SELECTED_TAB_OFFSET - itemRect->top * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : 0); + ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); itemRect->top = clientRect.bottom - infoPtr->tabHeight - itemRect->top * (infoPtr->tabHeight - 2) - - ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : 0); + ((lStyle & TCS_BUTTONS) ? itemRect->top * BUTTON_SPACINGY : SELECTED_TAB_OFFSET); } else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) { @@ -402,7 +404,6 @@ static BOOL TAB_InternalGetItemRect( /* If it also a bit higher. */ if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) { - selectedRect->top -= 2; /* the border is thicker on the bottom */ selectedRect->bottom += SELECTED_TAB_OFFSET; } else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) @@ -418,7 +419,7 @@ static BOOL TAB_InternalGetItemRect( else { selectedRect->top -= SELECTED_TAB_OFFSET; - selectedRect->bottom += 1; + selectedRect->bottom -= 1; } } @@ -649,9 +650,12 @@ static void TAB_DrawLoneItemInterior(HWND hwnd, TAB_INFO* infoPtr, int iItem) { HDC hdc = GetDC(hwnd); - HFONT hOldFont = SelectObject(hdc, infoPtr->hFont); + RECT r, rC; + + GetWindowRect(hwnd, &rC); + GetWindowRect(infoPtr->hwndUpDown, &r); + ExcludeClipRect(hdc, r.left - rC.left, r.top - rC.top, r.right - rC.left, r.bottom - rC.top); TAB_DrawItemInterior(hwnd, hdc, iItem, NULL); - SelectObject(hdc, hOldFont); ReleaseDC(hwnd, hdc); } @@ -1100,6 +1104,10 @@ static void TAB_SetItemBounds (HWND hwnd) clientRect.right = iTemp; } + /* Now use hPadding and vPadding */ + infoPtr->uHItemPadding = infoPtr->uHItemPadding_s; + infoPtr->uVItemPadding = infoPtr->uVItemPadding_s; + /* The leftmost item will be "0" aligned */ curItemLeftPos = 0; curItemRowCount = infoPtr->uNumItem ? 1 : 0; @@ -1416,6 +1424,69 @@ static void TAB_SetItemBounds (HWND hwnd) ReleaseDC (hwnd, hdc); } + +static void +TAB_EraseTabInterior + ( + HWND hwnd, + HDC hdc, + INT iItem, + RECT* drawRect + ) +{ + TAB_INFO *infoPtr = TAB_GetInfoPtr(hwnd); + LONG lStyle = GetWindowLongA(hwnd, GWL_STYLE); + HBRUSH hbr = CreateSolidBrush (comctl32_color.clrBtnFace); + BOOL deleteBrush = TRUE; + RECT rTemp = *drawRect; + + InflateRect(&rTemp, -2, -2); + if (lStyle & TCS_BUTTONS) + { + if (iItem == infoPtr->iSelected) + { + /* Background color */ + if (!(lStyle & TCS_OWNERDRAWFIXED)) + { + DeleteObject(hbr); + hbr = GetSysColorBrush(COLOR_SCROLLBAR); + + SetTextColor(hdc, comctl32_color.clr3dFace); + SetBkColor(hdc, comctl32_color.clr3dHilight); + + /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT + * we better use 0x55aa bitmap brush to make scrollbar's background + * look different from the window background. + */ + if (comctl32_color.clr3dHilight == comctl32_color.clrWindow) + hbr = COMCTL32_hPattern55AABrush; + + deleteBrush = FALSE; + } + FillRect(hdc, &rTemp, hbr); + } + else /* ! selected */ + { + if (lStyle & TCS_FLATBUTTONS) + { + FillRect(hdc, drawRect, hbr); + if (iItem == infoPtr->iHotTracked) + DrawEdge(hdc, drawRect, EDGE_RAISED, BF_SOFT|BF_RECT); + } + else + FillRect(hdc, &rTemp, hbr); + } + + } + else /* !TCS_BUTTONS */ + { + FillRect(hdc, &rTemp, hbr); + } + + /* Cleanup */ + if (deleteBrush) DeleteObject(hbr); +} + /****************************************************************************** * TAB_DrawItemInterior * @@ -1439,7 +1510,8 @@ TAB_DrawItemInterior HPEN htextPen; HPEN holdPen; INT oldBkMode; - + HFONT hOldFont; + if (drawRect == NULL) { BOOL isVisible; @@ -1469,32 +1541,77 @@ TAB_DrawItemInterior *drawRect = itemRect; if (iItem == infoPtr->iSelected) { - drawRect->right--; - drawRect->bottom--; + OffsetRect(drawRect, 1, 1); } } else { if (iItem == infoPtr->iSelected) + { *drawRect = selectedRect; + if (lStyle & TCS_BOTTOM) + { + if (lStyle & TCS_VERTICAL) + { + drawRect->left++; + } + else + { + drawRect->top += 3; + drawRect->left += 1; + } + } + } else *drawRect = itemRect; - drawRect->right--; - drawRect->bottom--; + + + if (lStyle & TCS_BOTTOM && !(lStyle & TCS_VERTICAL)) + { + drawRect->top--; + drawRect->bottom--; + } } } + TRACE("drawRect=(%ld,%ld)-(%ld,%ld)\n", + drawRect->left, drawRect->top, drawRect->right, drawRect->bottom); + + /* Clear interior */ + TAB_EraseTabInterior (hwnd, hdc, iItem, drawRect); + + /* Draw the focus rectangle */ + if (!(lStyle & TCS_FOCUSNEVER) && + (GetFocus() == hwnd) && + (iItem == infoPtr->uFocus) ) + { + RECT rFocus = *drawRect; + InflateRect(&rFocus, -3, -3); + if (lStyle & TCS_BOTTOM && !(lStyle & TCS_VERTICAL)) + rFocus.top -= 3; + if (lStyle & TCS_BUTTONS) + { + rFocus.left -= 3; + rFocus.top -= 3; + } + + DrawFocusRect(hdc, &rFocus); + } /* * Text pen */ htextPen = CreatePen( PS_SOLID, 1, GetSysColor(COLOR_BTNTEXT) ); - holdPen = SelectObject(hdc, htextPen); + holdPen = SelectObject(hdc, htextPen); + hOldFont = SelectObject(hdc, infoPtr->hFont); + /* + * Setup for text output + */ oldBkMode = SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, ( (iItem == infoPtr->iHotTracked) | (infoPtr->items[iItem].dwState & TCIS_HIGHLIGHTED)) ? + SetTextColor(hdc, (((iItem == infoPtr->iHotTracked) && !(lStyle & TCS_FLATBUTTONS)) | + (infoPtr->items[iItem].dwState & TCIS_HIGHLIGHTED)) ? comctl32_color.clrHighlight : comctl32_color.clrBtnText); - /* * if owner draw, tell the owner to draw */ @@ -1523,6 +1640,7 @@ TAB_DrawItemInterior dis.hwndItem = hwnd; /* */ dis.hDC = hdc; CopyRect(&dis.rcItem,drawRect); + InflateRect(&dis.rcItem, -2, -2); dis.itemData = infoPtr->items[iItem].lParam; /* @@ -1532,31 +1650,13 @@ TAB_DrawItemInterior } else { - INT cx; - INT cy; - UINT uHorizAlign; RECT rcTemp; RECT rcImage; - LOGFONTA logfont; - HFONT hFont = 0; - HFONT hOldFont = 0; /* stop uninitialized warning */ - - INT nEscapement = 0; /* stop uninitialized warning */ - INT nOrientation = 0; /* stop uninitialized warning */ - INT iPointSize; /* used to center the icon and text in the tab */ RECT rcText; INT center_offset_h, center_offset_v; - /* - * Deflate the rectangle to acount for the padding - */ - if(lStyle & TCS_VERTICAL) - InflateRect(drawRect, -infoPtr->uVItemPadding, -infoPtr->uHItemPadding); - else - InflateRect(drawRect, -infoPtr->uHItemPadding, -infoPtr->uVItemPadding); - /* set rcImage to drawRect, we will use top & left in our ImageList_Draw call */ rcImage = *drawRect; @@ -1564,17 +1664,9 @@ TAB_DrawItemInterior rcText.left = rcText.top = rcText.right = rcText.bottom = 0; - /* - * Setup for text output - */ - oldBkMode = SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, ((iItem == infoPtr->iHotTracked) | (infoPtr->items[iItem].dwState & TCIS_HIGHLIGHTED))? - comctl32_color.clrHighlight : comctl32_color.clrBtnText); - /* get the rectangle that the text fits in */ DrawTextW(hdc, infoPtr->items[iItem].pszText, -1, &rcText, DT_CALCRECT); - rcText.right += 4; /* * If not owner draw, then do the drawing ourselves. * @@ -1582,6 +1674,9 @@ TAB_DrawItemInterior */ if (infoPtr->himl && (infoPtr->items[iItem].mask & TCIF_IMAGE)) { + INT cx; + INT cy; + ImageList_GetIconSize(infoPtr->himl, &cx, &cy); if(lStyle & TCS_VERTICAL) @@ -1595,36 +1690,37 @@ TAB_DrawItemInterior center_offset_v = ((drawRect->bottom - drawRect->top) - (cy + infoPtr->uVItemPadding)) / 2; } - if ((lStyle & TCS_FIXEDWIDTH && - lStyle & (TCS_FORCELABELLEFT | TCS_FORCEICONLEFT)) || - (center_offset_h < 0)) - center_offset_h = 0; + if (lStyle & TCS_FIXEDWIDTH && lStyle & (TCS_FORCELABELLEFT | TCS_FORCEICONLEFT)) + center_offset_h = infoPtr->uHItemPadding; - TRACE("for <%s>, c_o=%d, draw=(%ld,%ld)-(%ld,%ld), textlen=%ld\n", - debugstr_w(infoPtr->items[iItem].pszText), center_offset_h, + if (center_offset_h < 2) + center_offset_h = 2; + + TRACE("for <%s>, c_o_h=%d, c_o_v=%d, draw=(%ld,%ld)-(%ld,%ld), textlen=%ld\n", + debugstr_w(infoPtr->items[iItem].pszText), center_offset_h, center_offset_v, drawRect->left, drawRect->top, drawRect->right, drawRect->bottom, (rcText.right-rcText.left)); if((lStyle & TCS_VERTICAL) && (lStyle & TCS_BOTTOM)) { - rcImage.top = drawRect->top + center_offset_h; + rcImage.top = drawRect->top + center_offset_h; /* if tab is TCS_VERTICAL and TCS_BOTTOM, the text is drawn from the */ /* right side of the tab, but the image still uses the left as its x position */ /* this keeps the image always drawn off of the same side of the tab */ rcImage.left = drawRect->right - cx - center_offset_v; - drawRect->top = rcImage.top + (cx + infoPtr->uHItemPadding); + drawRect->top += cy + infoPtr->uHItemPadding; } else if(lStyle & TCS_VERTICAL) { rcImage.top = drawRect->bottom - cy - center_offset_h; rcImage.left = drawRect->left + center_offset_v; - drawRect->bottom = rcImage.top - infoPtr->uHItemPadding; + drawRect->bottom -= cy + infoPtr->uHItemPadding; } else /* normal style, whether TCS_BOTTOM or not */ { - rcImage.left = drawRect->left + center_offset_h + 3; - drawRect->left = rcImage.left + cx + infoPtr->uHItemPadding; + rcImage.left = drawRect->left + center_offset_h; rcImage.top = drawRect->top + center_offset_v; + drawRect->left += cx + infoPtr->uHItemPadding; } TRACE("drawing image=%d, left=%ld, top=%ld\n", @@ -1639,70 +1735,52 @@ TAB_DrawItemInterior ILD_NORMAL ); } - else /* no image, so just shift the drawRect borders around */ - { + + /* Now position text */ + if (lStyle & TCS_FIXEDWIDTH && lStyle & TCS_FORCELABELLEFT) + center_offset_h = infoPtr->uHItemPadding; + else if(lStyle & TCS_VERTICAL) - { - center_offset_h = 0; - /* - currently the rcText rect is flawed because the rotated font does not - often match the horizontal font. So leave this as 0 - ((drawRect->bottom - drawRect->top) - (rcText.right - rcText.left)) / 2; - */ - if(lStyle & TCS_BOTTOM) - drawRect->top+=center_offset_h; - else - drawRect->bottom-=center_offset_h; - } + center_offset_h = ((drawRect->bottom - drawRect->top) - (rcText.right - rcText.left)) / 2; else - { center_offset_h = ((drawRect->right - drawRect->left) - (rcText.right - rcText.left)) / 2; - drawRect->left+=center_offset_h; - } - } if(lStyle & TCS_VERTICAL) { - center_offset_v = ((drawRect->right - drawRect->left) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; - drawRect->left += center_offset_v; + if(lStyle & TCS_BOTTOM) + drawRect->top+=center_offset_h; + else + drawRect->bottom-=center_offset_h; + + drawRect->left += ((drawRect->right - drawRect->left) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; } else { - center_offset_v = ((drawRect->bottom - drawRect->top) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; - drawRect->top += center_offset_v; + drawRect->left += center_offset_h; + drawRect->top += ((drawRect->bottom - drawRect->top) - ((rcText.bottom - rcText.top) + infoPtr->uVItemPadding)) / 2; } - /* Draw the text */ - if ((lStyle & TCS_FIXEDWIDTH && lStyle & TCS_FORCELABELLEFT) || - !center_offset_h) - uHorizAlign = DT_LEFT; - else - uHorizAlign = DT_CENTER; - if(lStyle & TCS_VERTICAL) /* if we are vertical rotate the text and each character */ { + LOGFONTA logfont; + HFONT hFont = 0; + INT nEscapement = 900; + INT nOrientation = 900; + if(lStyle & TCS_BOTTOM) { nEscapement = -900; nOrientation = -900; } - else - { - nEscapement = 900; - nOrientation = 900; - } - } - /* to get a font with the escapement and orientation we are looking for, we need to */ - /* call CreateFontIndirectA, which requires us to set the values of the logfont we pass in */ - if(lStyle & TCS_VERTICAL) - { + /* to get a font with the escapement and orientation we are looking for, we need to */ + /* call CreateFontIndirectA, which requires us to set the values of the logfont we pass in */ if (!GetObjectA((infoPtr->hFont) ? infoPtr->hFont : GetStockObject(SYSTEM_FONT), sizeof(LOGFONTA),&logfont)) { - iPointSize = 9; + INT iPointSize = 9; lstrcpyA(logfont.lfFaceName, "Arial"); logfont.lfHeight = -MulDiv(iPointSize, GetDeviceCaps(hdc, LOGPIXELSY), @@ -1716,11 +1794,8 @@ TAB_DrawItemInterior logfont.lfEscapement = nEscapement; logfont.lfOrientation = nOrientation; hFont = CreateFontIndirectA(&logfont); - hOldFont = SelectObject(hdc, hFont); - } + SelectObject(hdc, hFont); - if (lStyle & TCS_VERTICAL) - { ExtTextOutW(hdc, (lStyle & TCS_BOTTOM) ? drawRect->right : drawRect->left, (!(lStyle & TCS_BOTTOM)) ? drawRect->bottom : drawRect->top, @@ -1729,6 +1804,8 @@ TAB_DrawItemInterior infoPtr->items[iItem].pszText, lstrlenW(infoPtr->items[iItem].pszText), 0); + + DeleteObject(hFont); } else { @@ -1738,24 +1815,17 @@ TAB_DrawItemInterior infoPtr->items[iItem].pszText, lstrlenW(infoPtr->items[iItem].pszText), drawRect, - uHorizAlign | DT_SINGLELINE + DT_LEFT | DT_SINGLELINE ); } - /* clean things up */ *drawRect = rcTemp; /* restore drawRect */ - - if(lStyle & TCS_VERTICAL) - { - SelectObject(hdc, hOldFont); /* restore the original font */ - if (hFont) - DeleteObject(hFont); - } } /* * Cleanup */ + SelectObject(hdc, hOldFont); SetBkMode(hdc, oldBkMode); SelectObject(hdc, holdPen); DeleteObject( htextPen ); @@ -1792,6 +1862,13 @@ static void TAB_DrawItem( if (isVisible) { + RECT rUD, rC; + + /* Clip UpDown control to not draw over it */ + GetWindowRect(hwnd, &rC); + GetWindowRect(infoPtr->hwndUpDown, &rUD); + ExcludeClipRect(hdc, rUD.left - rC.left, rUD.top - rC.top, rUD.right - rC.left, rUD.bottom - rC.top); + /* If you need to see what the control is doing, * then override these variables. They will change what * fill colors are used for filling the tabs, and the @@ -1802,9 +1879,6 @@ static void TAB_DrawItem( if (lStyle & TCS_BUTTONS) { - HBRUSH hbr = CreateSolidBrush (bkgnd); - BOOL deleteBrush = TRUE; - /* Get item rectangle */ r = itemRect; @@ -1818,43 +1892,15 @@ static void TAB_DrawItem( if (iItem == infoPtr->iSelected) { - /* Background color */ - if (!(lStyle & TCS_OWNERDRAWFIXED)) - { - DeleteObject(hbr); - hbr = GetSysColorBrush(COLOR_SCROLLBAR); - - SetTextColor(hdc, comctl32_color.clr3dFace); - SetBkColor(hdc, comctl32_color.clr3dHilight); - - /* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT - * we better use 0x55aa bitmap brush to make scrollbar's background - * look different from the window background. - */ - if (comctl32_color.clr3dHilight == comctl32_color.clrWindow) - hbr = COMCTL32_hPattern55AABrush; - - deleteBrush = FALSE; - } - - /* Clear interior */ - FillRect(hdc, &r, hbr); - DrawEdge(hdc, &r, EDGE_SUNKEN, BF_SOFT|BF_RECT); + + OffsetRect(&r, 1, 1); } else /* ! selected */ { if (!(lStyle & TCS_FLATBUTTONS)) - { - /* Clear interior */ - FillRect(hdc, &r, hbr); - DrawEdge(hdc, &r, EDGE_RAISED, BF_SOFT|BF_RECT); - } } - - /* Cleanup */ - if (deleteBrush) DeleteObject(hbr); } else /* !TCS_BUTTONS */ { @@ -2031,11 +2077,17 @@ static void TAB_DrawItem( r1.bottom--; DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_DIAGONAL_ENDTOPLEFT); - if ((iItem == infoPtr->iSelected) && (selectedRect.left == 0)) { + if (iItem == infoPtr->iSelected) + { + r.top += 2; + r.left += 1; + if (selectedRect.left == 0) + { r1 = r; r1.bottom = r1.top; r1.top--; DrawEdge(hdc, &r1, EDGE_RAISED, BF_SOFT|BF_LEFT); + } } } @@ -2083,22 +2135,7 @@ static void TAB_DrawItem( TAB_DumpItemInternal(infoPtr, iItem); /* This modifies r to be the text rectangle. */ - { - HFONT hOldFont = SelectObject(hdc, infoPtr->hFont); - TAB_DrawItemInterior(hwnd, hdc, iItem, &r); - SelectObject(hdc,hOldFont); - } - - /* Draw the focus rectangle */ - if (((lStyle & TCS_FOCUSNEVER) == 0) && - (GetFocus() == hwnd) && - (iItem == infoPtr->uFocus) ) - { - r = itemRect; - InflateRect(&r, -1, -1); - - DrawFocusRect(hdc, &r); - } + TAB_DrawItemInterior(hwnd, hdc, iItem, &r); } } @@ -2357,7 +2394,7 @@ static void TAB_InvalidateTabArea( HWND hwnd, TAB_INFO* infoPtr) { - RECT clientRect, r; + RECT clientRect, rInvalidate; DWORD lStyle = GetWindowLongA(hwnd, GWL_STYLE); INT lastRow = infoPtr->uNumRows - 1; RECT rect; @@ -2365,49 +2402,54 @@ static void TAB_InvalidateTabArea( if (lastRow < 0) return; GetClientRect(hwnd, &clientRect); + rInvalidate = clientRect; TAB_InternalGetItemRect(hwnd, infoPtr, infoPtr->uNumItem-1 , &rect, NULL); if ((lStyle & TCS_BOTTOM) && !(lStyle & TCS_VERTICAL)) { - clientRect.top = clientRect.bottom - + rInvalidate.top = clientRect.bottom - infoPtr->tabHeight - lastRow * (infoPtr->tabHeight - 2) - ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) - 3; - clientRect.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; + rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; } else if((lStyle & TCS_BOTTOM) && (lStyle & TCS_VERTICAL)) { - clientRect.left = clientRect.right - infoPtr->tabHeight - + rInvalidate.left = clientRect.right - infoPtr->tabHeight - lastRow * (infoPtr->tabHeight - 2) - ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) - 2; - clientRect.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; + rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; } else if(lStyle & TCS_VERTICAL) { - clientRect.right = clientRect.left + infoPtr->tabHeight + + rInvalidate.right = clientRect.left + infoPtr->tabHeight + lastRow * (infoPtr->tabHeight - 2) - ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) + 2; - clientRect.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; + rInvalidate.bottom = clientRect.top + rect.bottom + 2 * SELECTED_TAB_OFFSET; } else { - clientRect.bottom = clientRect.top + infoPtr->tabHeight + + rInvalidate.bottom = clientRect.top + infoPtr->tabHeight + lastRow * (infoPtr->tabHeight - 2) + ((lStyle & TCS_BUTTONS) ? lastRow * BUTTON_SPACINGY : 0) + 2; - clientRect.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; + rInvalidate.right = clientRect.left + rect.right + 2 * SELECTED_TAB_OFFSET; } /* Punch out the updown control */ - if (infoPtr->needsScrolling && (clientRect.right > 0)) { + if (infoPtr->needsScrolling && (rInvalidate.right > 0)) { + RECT r; GetClientRect(infoPtr->hwndUpDown, &r); - clientRect.right = clientRect.right - (r.right - r.left); + if (rInvalidate.right > clientRect.right - r.left) + rInvalidate.right = rInvalidate.right - (r.right - r.left); + else + rInvalidate.right = clientRect.right - r.left; } TRACE("invalidate (%ld,%ld)-(%ld,%ld)\n", clientRect.left,clientRect.top, clientRect.right,clientRect.bottom); - InvalidateRect(hwnd, &clientRect, TRUE); + InvalidateRect(hwnd, &rInvalidate, TRUE); } static LRESULT @@ -3008,6 +3050,8 @@ TAB_Create (HWND hwnd, WPARAM wParam, LPARAM lParam) infoPtr->uNumRows = 0; infoPtr->uHItemPadding = 6; infoPtr->uVItemPadding = 3; + infoPtr->uHItemPadding_s = 6; + infoPtr->uVItemPadding_s = 3; infoPtr->hFont = 0; infoPtr->items = 0; infoPtr->hcurArrow = LoadCursorA (0, (LPSTR)IDC_ARROW); diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index 3be0a9edfee..1509ae5d0d6 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -32,9 +32,11 @@ #ifdef VISIBLE #define WAIT Sleep (1000) #define REDRAW(hwnd) RedrawWindow (hwnd, NULL, 0, RDW_UPDATENOW) +#define trace_tab(str) trace(str) #else #define WAIT #define REDRAW(hwnd) +#define trace_tab(str) #endif HWND @@ -47,10 +49,12 @@ create_tabcontrol (DWORD style) WC_TABCONTROLA, "TestTab", WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style, - 0, 0, 300, 100, + 10, 10, 300, 100, NULL, NULL, NULL, 0); assert (handle); + + SetWindowLong(handle, GWL_STYLE, WS_CLIPSIBLINGS | WS_CLIPCHILDREN | TCS_FOCUSNEVER | style); tcNewTab.mask = TCIF_TEXT | TCIF_IMAGE; tcNewTab.pszText = "Tab 1"; @@ -74,10 +78,13 @@ create_tabcontrol (DWORD style) void CheckSize(HWND hwnd, INT width, INT height) { - RECT rTab; + RECT rTab, r1; - SendMessage (hwnd, TCM_GETITEMRECT, 1, (LPARAM) &rTab); - /*trace ("Got (%ld,%ld)-(%ld,%ld)\n", rTab.left, rTab.top, rTab.right, rTab.bottom);*/ + r1.left=r1.top=r1.right=r1.bottom=0; + SendMessage (hwnd, TCM_GETITEMRECT, 0, (LPARAM) &rTab); + SendMessage (hwnd, TCM_ADJUSTRECT, FALSE, (LPARAM) &r1); + /* trace ("Got (%ld,%ld)-(%ld,%ld)", rTab.left, rTab.top, rTab.right, rTab.bottom); */ + trace (" (%ld,%ld)-(%ld,%ld)\n", r1.left, r1.top, r1.right, r1.bottom); if ((width >= 0) && (height < 0)) ok (width == rTab.right - rTab.left, "Expected [%d] got [%ld]", width, rTab.right - rTab.left); else if ((height >= 0) && (width < 0)) @@ -107,59 +114,84 @@ START_TEST(tab) hwTab = create_tabcontrol(TCS_FIXEDWIDTH); - trace ("Testing TCS_FIXEDWIDTH tabs no icon...\n"); - trace (" default width...\n"); + trace_tab ("Testing TCS_FIXEDWIDTH tabs no icon...\n"); + trace_tab (" default width...\n"); CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1); - trace (" set size...\n"); + trace_tab (" set size...\n"); TabCheckSetSize(hwTab, 50, 20, 50, 20); WAIT; - trace (" min size...\n"); + trace_tab (" min size...\n"); TabCheckSetSize(hwTab, 0, 1, 0, 1); WAIT; SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); - trace ("Testing TCS_FIXEDWIDTH tabs with icon...\n"); - trace (" set size > icon...\n"); + trace_tab ("Testing TCS_FIXEDWIDTH tabs with icon...\n"); + trace_tab (" set size > icon...\n"); TabCheckSetSize(hwTab, 50, 30, 50, 30); - WAIT; - trace (" set size < icon...\n"); + trace_tab (" set size < icon...\n"); TabCheckSetSize(hwTab, 20, 20, 25, 20); - WAIT; - trace (" min size...\n"); + trace_tab (" min size...\n"); TabCheckSetSize(hwTab, 0, 1, 25, 1); - WAIT; DestroyWindow (hwTab); - trace ("Testing TCS_FIXEDWIDTH buttons no icon...\n"); + trace_tab ("Testing TCS_FIXEDWIDTH buttons no icon...\n"); hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BUTTONS); - trace (" default width...\n"); + trace_tab (" default width...\n"); CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1); - trace (" set size 1...\n"); + trace_tab (" set size 1...\n"); TabCheckSetSize(hwTab, 20, 20, 20, 20); - trace (" set size 2...\n"); + trace_tab (" set size 2...\n"); TabCheckSetSize(hwTab, 10, 50, 10, 50); - trace (" min size...\n"); + trace_tab (" min size...\n"); TabCheckSetSize(hwTab, 0, 1, 0, 1); SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); - trace ("Testing TCS_FIXEDWIDTH buttons with icon...\n"); - trace (" set size > icon...\n"); + trace_tab ("Testing TCS_FIXEDWIDTH buttons with icon...\n"); + trace_tab (" set size > icon...\n"); TabCheckSetSize(hwTab, 50, 30, 50, 30); - trace (" set size < icon...\n"); + trace_tab (" set size < icon...\n"); TabCheckSetSize(hwTab, 20, 20, 25, 20); - trace (" min size...\n"); + trace_tab (" min size...\n"); + TabCheckSetSize(hwTab, 0, 1, 25, 1); + trace_tab (" Add padding...\n"); + SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4)); + trace_tab (" min size...\n"); TabCheckSetSize(hwTab, 0, 1, 25, 1); - trace (" Add padding...\n"); - SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4)); - trace (" min size...\n"); - TabCheckSetSize(hwTab, 0, 1, 25, 1); - WAIT; - DestroyWindow (hwTab); + + hwTab = create_tabcontrol(TCS_FIXEDWIDTH | TCS_BOTTOM); + trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs no icon...\n"); + + trace_tab (" default width...\n"); + CheckSize(hwTab, TAB_DEFAULT_WIDTH, -1); + trace_tab (" set size 1...\n"); + TabCheckSetSize(hwTab, 20, 20, 20, 20); + trace_tab (" set size 2...\n"); + TabCheckSetSize(hwTab, 10, 50, 10, 50); + trace_tab (" min size...\n"); + TabCheckSetSize(hwTab, 0, 1, 0, 1); + + SendMessage(hwTab, TCM_SETIMAGELIST, 0, (LPARAM)himl); + + trace_tab ("Testing TCS_FIXEDWIDTH | TCS_BOTTOM tabs with icon...\n"); + trace_tab (" set size > icon...\n"); + TabCheckSetSize(hwTab, 50, 30, 50, 30); + trace_tab (" set size < icon...\n"); + TabCheckSetSize(hwTab, 20, 20, 25, 20); + trace_tab (" min size...\n"); + TabCheckSetSize(hwTab, 0, 1, 25, 1); + trace_tab (" Add padding...\n"); + SendMessage(hwTab, TCM_SETPADDING, 0, MAKELPARAM(4,4)); + trace_tab (" min size...\n"); + TabCheckSetSize(hwTab, 0, 1, 25, 1); + + DestroyWindow (hwTab); + + ImageList_Destroy(himl); }