From: Zhiyi Zhang <zzhang@codeweavers.com> Use a clip region to protect the tab item background when drawing the text of an owner-draw tab control. This partially reverts 0d173d01. Tests show that the top edge of the rcItem in DRAWITEMSTRUCT shouldn't be added 2 pixels for a owner-draw tab, and the tab item background can't be overwritten when painting the text, which suggests the presence of a clip region. Fix the text position being off by 2 pixels for an application, which uses the rcItem in DRAWITEMSTRUCT to calculate text position. --- dlls/comctl32/commctrl.c | 20 ++++++++++++++++++++ dlls/comctl32/tab.c | 16 +++++++++++----- dlls/comctl32/tests/tab.c | 1 - dlls/comctl32_v6/button.c | 20 -------------------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c index e0724529fc4..3ddc3452fec 100644 --- a/dlls/comctl32/commctrl.c +++ b/dlls/comctl32/commctrl.c @@ -3199,3 +3199,23 @@ BOOL COMCTL32_IsThemed(HWND hwnd) return FALSE; #endif } + +HRGN set_control_clipping( HDC hdc, const RECT *rect ) +{ + RECT rc = *rect; + HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); + + if (GetClipRgn( hdc, hrgn ) != 1) + { + DeleteObject( hrgn ); + hrgn = 0; + } + DPtoLP( hdc, (POINT *)&rc, 2 ); + if (GetLayout( hdc ) & LAYOUT_RTL) /* compensate for the shifting done by IntersectClipRect */ + { + rc.left++; + rc.right++; + } + IntersectClipRect( hdc, rc.left, rc.top, rc.right, rc.bottom ); + return hrgn; +} diff --git a/dlls/comctl32/tab.c b/dlls/comctl32/tab.c index 3a964c41608..352c4bf861d 100644 --- a/dlls/comctl32/tab.c +++ b/dlls/comctl32/tab.c @@ -1705,13 +1705,10 @@ TAB_DrawItemInterior(const TAB_INFO *infoPtr, HDC hdc, INT iItem, RECT *drawRect if ((infoPtr->dwStyle & TCS_OWNERDRAWFIXED) && IsWindow(infoPtr->hwndNotify)) { DRAWITEMSTRUCT dis; + RECT clipRect; + HRGN hrgn; UINT id; - drawRect->top += 2; - drawRect->right -= 1; - if ( iItem == infoPtr->iSelected ) - InflateRect(drawRect, -1, 0); - id = (UINT)GetWindowLongPtrW( infoPtr->hwnd, GWLP_ID ); /* fill DRAWITEMSTRUCT */ @@ -1739,8 +1736,17 @@ TAB_DrawItemInterior(const TAB_INFO *infoPtr, HDC hdc, INT iItem, RECT *drawRect memcpy(&dis.itemData, (ULONG_PTR*)TAB_GetItem(infoPtr, iItem)->extra, 4); } + /* Avoid overwriting the background */ + SetRect( &clipRect, drawRect->left, drawRect->top + 2, drawRect->right - 1, drawRect->bottom ); + if ( iItem == infoPtr->iSelected ) + InflateRect( &clipRect, -1, 0 ); + hrgn = set_control_clipping( hdc, &clipRect ); + /* draw notification */ SendMessageW( infoPtr->hwndNotify, WM_DRAWITEM, id, (LPARAM)&dis ); + + SelectClipRgn( hdc, hrgn ); + if (hrgn) DeleteObject( hrgn ); } else { diff --git a/dlls/comctl32/tests/tab.c b/dlls/comctl32/tests/tab.c index aac2cde01a2..642801b2e72 100644 --- a/dlls/comctl32/tests/tab.c +++ b/dlls/comctl32/tests/tab.c @@ -1487,7 +1487,6 @@ static void test_TCS_OWNERDRAWFIXED(void) RedrawWindow(hTab, NULL, 0, RDW_UPDATENOW); /* Check the draw rect from WM_DRAWITEM */ - todo_wine ok(g_drawitem.rcItem.top == 0 && g_drawitem.rcItem.left == 0 && g_drawitem.rcItem.right > 0 && g_drawitem.rcItem.bottom > 0, "Got unexpected rect %s.\n", wine_dbgstr_rect(&g_drawitem.rcItem)); /* Check that tab item background is not overwritten */ diff --git a/dlls/comctl32_v6/button.c b/dlls/comctl32_v6/button.c index 9128e523c20..ade2a9efdcc 100644 --- a/dlls/comctl32_v6/button.c +++ b/dlls/comctl32_v6/button.c @@ -309,26 +309,6 @@ static void init_custom_draw(NMCUSTOMDRAW *nmcd, const BUTTON_INFO *infoPtr, HDC /* FIXME: Handle it properly when we support keyboard cues? */ } -HRGN set_control_clipping( HDC hdc, const RECT *rect ) -{ - RECT rc = *rect; - HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 ); - - if (GetClipRgn( hdc, hrgn ) != 1) - { - DeleteObject( hrgn ); - hrgn = 0; - } - DPtoLP( hdc, (POINT *)&rc, 2 ); - if (GetLayout( hdc ) & LAYOUT_RTL) /* compensate for the shifting done by IntersectClipRect */ - { - rc.left++; - rc.right++; - } - IntersectClipRect( hdc, rc.left, rc.top, rc.right, rc.bottom ); - return hrgn; -} - static WCHAR *heap_strndupW(const WCHAR *src, size_t length) { size_t size = (length + 1) * sizeof(WCHAR); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10307