Commit 0f900535 authored by Alexandre Julliard's avatar Alexandre Julliard

user32: Add a common helper to set controls clip region, and make it behave…

user32: Add a common helper to set controls clip region, and make it behave correctly when mirrored.
parent 05375a2a
...@@ -213,15 +213,6 @@ static inline WCHAR *get_button_text( HWND hwnd ) ...@@ -213,15 +213,6 @@ static inline WCHAR *get_button_text( HWND hwnd )
return buffer; return buffer;
} }
static void setup_clipping( HWND hwnd, HDC hdc )
{
RECT rc;
GetClientRect( hwnd, &rc );
DPtoLP( hdc, (POINT *)&rc, 2 );
IntersectClipRect( hdc, rc.left, rc.top, rc.right, rc.bottom );
}
/*********************************************************************** /***********************************************************************
* ButtonWndProc_common * ButtonWndProc_common
*/ */
...@@ -773,6 +764,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -773,6 +764,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG style = GetWindowLongW( hwnd, GWL_STYLE ); LONG style = GetWindowLongW( hwnd, GWL_STYLE );
BOOL pushedState = (state & BUTTON_HIGHLIGHTED); BOOL pushedState = (state & BUTTON_HIGHLIGHTED);
HWND parent; HWND parent;
HRGN hrgn;
GetClientRect( hwnd, &rc ); GetClientRect( hwnd, &rc );
...@@ -782,7 +774,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -782,7 +774,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!parent) parent = hwnd; if (!parent) parent = hwnd;
SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd );
setup_clipping( hwnd, hDC ); hrgn = set_control_clipping( hDC, &rc );
hOldPen = SelectObject(hDC, SYSCOLOR_GetPen(COLOR_WINDOWFRAME)); hOldPen = SelectObject(hDC, SYSCOLOR_GetPen(COLOR_WINDOWFRAME));
hOldBrush = SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE)); hOldBrush = SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE));
...@@ -842,6 +834,8 @@ draw_focus: ...@@ -842,6 +834,8 @@ draw_focus:
SelectObject( hDC, hOldPen ); SelectObject( hDC, hOldPen );
SelectObject( hDC, hOldBrush ); SelectObject( hDC, hOldBrush );
SetBkMode(hDC, oldBkMode); SetBkMode(hDC, oldBkMode);
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
} }
/********************************************************************** /**********************************************************************
...@@ -858,6 +852,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -858,6 +852,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG state = get_button_state( hwnd ); LONG state = get_button_state( hwnd );
LONG style = GetWindowLongW( hwnd, GWL_STYLE ); LONG style = GetWindowLongW( hwnd, GWL_STYLE );
HWND parent; HWND parent;
HRGN hrgn;
if (style & BS_PUSHLIKE) if (style & BS_PUSHLIKE)
{ {
...@@ -877,7 +872,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -877,7 +872,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!hBrush) /* did the app forget to call defwindowproc ? */ if (!hBrush) /* did the app forget to call defwindowproc ? */
hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC,
(WPARAM)hDC, (LPARAM)hwnd ); (WPARAM)hDC, (LPARAM)hwnd );
setup_clipping( hwnd, hDC ); hrgn = set_control_clipping( hDC, &client );
if (style & BS_LEFTTEXT) if (style & BS_LEFTTEXT)
{ {
...@@ -968,6 +963,8 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -968,6 +963,8 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
IntersectRect(&rtext, &rtext, &client); IntersectRect(&rtext, &rtext, &client);
DrawFocusRect( hDC, &rtext ); DrawFocusRect( hDC, &rtext );
} }
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
} }
...@@ -1007,6 +1004,7 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -1007,6 +1004,7 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
TEXTMETRICW tm; TEXTMETRICW tm;
LONG style = GetWindowLongW( hwnd, GWL_STYLE ); LONG style = GetWindowLongW( hwnd, GWL_STYLE );
HWND parent; HWND parent;
HRGN hrgn;
if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont ); if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
/* GroupBox acts like static control, so it sends CTLCOLORSTATIC */ /* GroupBox acts like static control, so it sends CTLCOLORSTATIC */
...@@ -1016,10 +1014,9 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -1016,10 +1014,9 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!hbr) /* did the app forget to call defwindowproc ? */ if (!hbr) /* did the app forget to call defwindowproc ? */
hbr = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC, hbr = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC,
(WPARAM)hDC, (LPARAM)hwnd); (WPARAM)hDC, (LPARAM)hwnd);
setup_clipping( hwnd, hDC );
GetClientRect( hwnd, &rc); GetClientRect( hwnd, &rc);
rcFrame = rc; rcFrame = rc;
hrgn = set_control_clipping( hDC, &rc );
GetTextMetricsW (hDC, &tm); GetTextMetricsW (hDC, &tm);
rcFrame.top += (tm.tmHeight / 2) - 1; rcFrame.top += (tm.tmHeight / 2) - 1;
...@@ -1028,20 +1025,22 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -1028,20 +1025,22 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
InflateRect(&rc, -7, 1); InflateRect(&rc, -7, 1);
dtFlags = BUTTON_CalcLabelRect(hwnd, hDC, &rc); dtFlags = BUTTON_CalcLabelRect(hwnd, hDC, &rc);
if (dtFlags == (UINT)-1L) if (dtFlags != (UINT)-1)
return; {
/* Because buttons have CS_PARENTDC class style, there is a chance
/* Because buttons have CS_PARENTDC class style, there is a chance * that label will be drawn out of client rect.
* that label will be drawn out of client rect. * But Windows doesn't clip label's rect, so do I.
* But Windows doesn't clip label's rect, so do I. */
*/
/* There is 1-pixel margin at the left, right, and bottom */ /* There is 1-pixel margin at the left, right, and bottom */
rc.left--; rc.right++; rc.bottom++; rc.left--; rc.right++; rc.bottom++;
FillRect(hDC, &rc, hbr); FillRect(hDC, &rc, hbr);
rc.left++; rc.right--; rc.bottom--; rc.left++; rc.right--; rc.bottom--;
BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc); BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
}
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
} }
...@@ -1100,6 +1099,7 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -1100,6 +1099,7 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID ); LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID );
HWND parent; HWND parent;
HFONT hFont, hPrevFont = 0; HFONT hFont, hPrevFont = 0;
HRGN hrgn;
dis.CtlType = ODT_BUTTON; dis.CtlType = ODT_BUTTON;
dis.CtlID = id; dis.CtlID = id;
...@@ -1118,8 +1118,10 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action ) ...@@ -1118,8 +1118,10 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!parent) parent = hwnd; if (!parent) parent = hwnd;
SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd ); SendMessageW( parent, WM_CTLCOLORBTN, (WPARAM)hDC, (LPARAM)hwnd );
setup_clipping( hwnd, hDC ); hrgn = set_control_clipping( hDC, &dis.rcItem );
SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis ); SendMessageW( GetParent(hwnd), WM_DRAWITEM, id, (LPARAM)&dis );
if (hPrevFont) SelectObject(hDC, hPrevFont); if (hPrevFont) SelectObject(hDC, hPrevFont);
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
} }
...@@ -753,19 +753,6 @@ static void CBPaintText( ...@@ -753,19 +753,6 @@ static void CBPaintText(
!(lphc->wState & CBF_DROPPED) ) !(lphc->wState & CBF_DROPPED) )
itemState |= ODS_SELECTED | ODS_FOCUS; itemState |= ODS_SELECTED | ODS_FOCUS;
/*
* Save the current clip region.
* To retrieve the clip region, we need to create one "dummy"
* clip region.
*/
clipRegion = CreateRectRgnIndirect(&rectEdit);
if (GetClipRgn(hdc, clipRegion)!=1)
{
DeleteObject(clipRegion);
clipRegion=NULL;
}
if (!IsWindowEnabled(lphc->self)) itemState |= ODS_DISABLED; if (!IsWindowEnabled(lphc->self)) itemState |= ODS_DISABLED;
dis.CtlType = ODT_COMBOBOX; dis.CtlType = ODT_COMBOBOX;
...@@ -781,16 +768,12 @@ static void CBPaintText( ...@@ -781,16 +768,12 @@ static void CBPaintText(
/* /*
* Clip the DC and have the parent draw the item. * Clip the DC and have the parent draw the item.
*/ */
IntersectClipRect(hdc, clipRegion = set_control_clipping( hdc, &rectEdit );
rectEdit.left, rectEdit.top,
rectEdit.right, rectEdit.bottom);
SendMessageW(lphc->owner, WM_DRAWITEM, ctlid, (LPARAM)&dis ); SendMessageW(lphc->owner, WM_DRAWITEM, ctlid, (LPARAM)&dis );
/* SelectClipRgn( hdc, clipRegion );
* Reset the clipping region. if (clipRegion) DeleteObject( clipRegion );
*/
SelectClipRgn(hdc, clipRegion);
} }
else else
{ {
......
...@@ -243,4 +243,6 @@ typedef struct tagDIALOGINFO ...@@ -243,4 +243,6 @@ typedef struct tagDIALOGINFO
extern DIALOGINFO *DIALOG_get_info( HWND hwnd, BOOL create ) DECLSPEC_HIDDEN; extern DIALOGINFO *DIALOG_get_info( HWND hwnd, BOOL create ) DECLSPEC_HIDDEN;
extern INT DIALOG_DoDialogBox( HWND hwnd, HWND owner ) DECLSPEC_HIDDEN; extern INT DIALOG_DoDialogBox( HWND hwnd, HWND owner ) DECLSPEC_HIDDEN;
HRGN set_control_clipping( HDC hdc, const RECT *rect ) DECLSPEC_HIDDEN;
#endif /* __WINE_CONTROLS_H */ #endif /* __WINE_CONTROLS_H */
...@@ -543,9 +543,7 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect, ...@@ -543,9 +543,7 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
after they are done, so a region has better to exist after they are done, so a region has better to exist
else everything ends clipped */ else everything ends clipped */
GetClientRect(descr->self, &r); GetClientRect(descr->self, &r);
hrgn = CreateRectRgnIndirect(&r); hrgn = set_control_clipping( hdc, &r );
SelectClipRgn( hdc, hrgn);
DeleteObject( hrgn );
dis.CtlType = ODT_LISTBOX; dis.CtlType = ODT_LISTBOX;
dis.CtlID = GetWindowLongPtrW( descr->self, GWLP_ID ); dis.CtlID = GetWindowLongPtrW( descr->self, GWLP_ID );
...@@ -565,6 +563,8 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect, ...@@ -565,6 +563,8 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
descr->self, index, debugstr_w(item->str), action, descr->self, index, debugstr_w(item->str), action,
dis.itemState, wine_dbgstr_rect(rect) ); dis.itemState, wine_dbgstr_rect(rect) );
SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis); SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
} }
else else
{ {
......
...@@ -108,34 +108,6 @@ const struct builtin_class_descr STATIC_builtin_class = ...@@ -108,34 +108,6 @@ const struct builtin_class_descr STATIC_builtin_class =
0 /* brush */ 0 /* brush */
}; };
static void setup_clipping(HWND hwnd, HDC hdc, HRGN *orig)
{
RECT rc;
HRGN hrgn;
/* Native control has always a clipping region set (this may be because
* builtin controls uses CS_PARENTDC) and an application depends on it
*/
hrgn = CreateRectRgn(0, 0, 1, 1);
if (GetClipRgn(hdc, hrgn) != 1)
{
DeleteObject(hrgn);
*orig = NULL;
} else
*orig = hrgn;
GetClientRect(hwnd, &rc);
DPtoLP(hdc, (POINT *)&rc, 2);
IntersectClipRect(hdc, rc.left, rc.top, rc.right, rc.bottom);
}
static void restore_clipping(HDC hdc, HRGN hrgn)
{
SelectClipRgn(hdc, hrgn);
if (hrgn != NULL)
DeleteObject(hrgn);
}
/*********************************************************************** /***********************************************************************
* STATIC_SetIcon * STATIC_SetIcon
* *
...@@ -317,12 +289,13 @@ static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style) ...@@ -317,12 +289,13 @@ static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style]) if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
{ {
HDC hdc; HDC hdc;
HRGN hOrigClipping; HRGN hrgn;
hdc = GetDC( hwnd ); hdc = GetDC( hwnd );
setup_clipping(hwnd, hdc, &hOrigClipping); hrgn = set_control_clipping( hdc, &rc );
(staticPaintFunc[style])( hwnd, hdc, full_style ); (staticPaintFunc[style])( hwnd, hdc, full_style );
restore_clipping(hdc, hOrigClipping); SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
ReleaseDC( hwnd, hdc ); ReleaseDC( hwnd, hdc );
} }
} }
...@@ -418,13 +391,15 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ...@@ -418,13 +391,15 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
case WM_PAINT: case WM_PAINT:
{ {
PAINTSTRUCT ps; PAINTSTRUCT ps;
RECT rect;
HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps); HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
GetClientRect( hwnd, &rect );
if (staticPaintFunc[style]) if (staticPaintFunc[style])
{ {
HRGN hOrigClipping; HRGN hrgn = set_control_clipping( hdc, &rect );
setup_clipping(hwnd, hdc, &hOrigClipping);
(staticPaintFunc[style])( hwnd, hdc, full_style ); (staticPaintFunc[style])( hwnd, hdc, full_style );
restore_clipping(hdc, hOrigClipping); SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
} }
if (!wParam) EndPaint(hwnd, &ps); if (!wParam) EndPaint(hwnd, &ps);
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "wingdi.h" #include "wingdi.h"
#include "winuser.h" #include "winuser.h"
#include "user_private.h" #include "user_private.h"
#include "controls.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "wine/debug.h" #include "wine/debug.h"
...@@ -113,6 +114,32 @@ static const signed char LTRBInnerFlat[] = { ...@@ -113,6 +114,32 @@ static const signed char LTRBInnerFlat[] = {
/*********************************************************************** /***********************************************************************
* set_control_clipping
*
* Set clipping for a builtin control that uses CS_PARENTDC.
* Return the previous clip region if any.
*/
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;
}
/***********************************************************************
* UITOOLS_DrawDiagEdge * UITOOLS_DrawDiagEdge
* *
* Same as DrawEdge invoked with BF_DIAGONAL * Same as DrawEdge invoked with BF_DIAGONAL
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment