user32: Add a common helper to set controls clip region, and make it behave correctly when mirrored.

This commit is contained in:
Alexandre Julliard 2010-09-02 11:35:14 +02:00
parent 05375a2a96
commit 0f90053575
6 changed files with 72 additions and 83 deletions

View File

@ -213,15 +213,6 @@ static inline WCHAR *get_button_text( HWND hwnd )
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
*/
@ -773,6 +764,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
BOOL pushedState = (state & BUTTON_HIGHLIGHTED);
HWND parent;
HRGN hrgn;
GetClientRect( hwnd, &rc );
@ -782,7 +774,7 @@ static void PB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!parent) parent = 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));
hOldBrush = SelectObject(hDC,GetSysColorBrush(COLOR_BTNFACE));
@ -842,6 +834,8 @@ draw_focus:
SelectObject( hDC, hOldPen );
SelectObject( hDC, hOldBrush );
SetBkMode(hDC, oldBkMode);
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
}
/**********************************************************************
@ -858,6 +852,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
LONG state = get_button_state( hwnd );
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
HWND parent;
HRGN hrgn;
if (style & BS_PUSHLIKE)
{
@ -877,7 +872,7 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!hBrush) /* did the app forget to call defwindowproc ? */
hBrush = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC,
(WPARAM)hDC, (LPARAM)hwnd );
setup_clipping( hwnd, hDC );
hrgn = set_control_clipping( hDC, &client );
if (style & BS_LEFTTEXT)
{
@ -968,6 +963,8 @@ static void CB_Paint( HWND hwnd, HDC hDC, UINT action )
IntersectRect(&rtext, &rtext, &client);
DrawFocusRect( hDC, &rtext );
}
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
}
@ -1007,6 +1004,7 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
TEXTMETRICW tm;
LONG style = GetWindowLongW( hwnd, GWL_STYLE );
HWND parent;
HRGN hrgn;
if ((hFont = get_button_font( hwnd ))) SelectObject( hDC, hFont );
/* GroupBox acts like static control, so it sends CTLCOLORSTATIC */
@ -1016,10 +1014,9 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!hbr) /* did the app forget to call defwindowproc ? */
hbr = (HBRUSH)DefWindowProcW(parent, WM_CTLCOLORSTATIC,
(WPARAM)hDC, (LPARAM)hwnd);
setup_clipping( hwnd, hDC );
GetClientRect( hwnd, &rc);
rcFrame = rc;
hrgn = set_control_clipping( hDC, &rc );
GetTextMetricsW (hDC, &tm);
rcFrame.top += (tm.tmHeight / 2) - 1;
@ -1028,20 +1025,22 @@ static void GB_Paint( HWND hwnd, HDC hDC, UINT action )
InflateRect(&rc, -7, 1);
dtFlags = BUTTON_CalcLabelRect(hwnd, hDC, &rc);
if (dtFlags == (UINT)-1L)
return;
if (dtFlags != (UINT)-1)
{
/* Because buttons have CS_PARENTDC class style, there is a chance
* that label will be drawn out of client rect.
* But Windows doesn't clip label's rect, so do I.
*/
/* Because buttons have CS_PARENTDC class style, there is a chance
* that label will be drawn out of client rect.
* But Windows doesn't clip label's rect, so do I.
*/
/* There is 1-pixel margin at the left, right, and bottom */
rc.left--; rc.right++; rc.bottom++;
FillRect(hDC, &rc, hbr);
rc.left++; rc.right--; rc.bottom--;
/* There is 1-pixel margin at the left, right, and bottom */
rc.left--; rc.right++; rc.bottom++;
FillRect(hDC, &rc, hbr);
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 )
LONG_PTR id = GetWindowLongPtrW( hwnd, GWLP_ID );
HWND parent;
HFONT hFont, hPrevFont = 0;
HRGN hrgn;
dis.CtlType = ODT_BUTTON;
dis.CtlID = id;
@ -1118,8 +1118,10 @@ static void OB_Paint( HWND hwnd, HDC hDC, UINT action )
if (!parent) parent = 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 );
if (hPrevFont) SelectObject(hDC, hPrevFont);
SelectClipRgn( hDC, hrgn );
if (hrgn) DeleteObject( hrgn );
}

View File

@ -753,19 +753,6 @@ static void CBPaintText(
!(lphc->wState & CBF_DROPPED) )
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;
dis.CtlType = ODT_COMBOBOX;
@ -781,16 +768,12 @@ static void CBPaintText(
/*
* Clip the DC and have the parent draw the item.
*/
IntersectClipRect(hdc,
rectEdit.left, rectEdit.top,
rectEdit.right, rectEdit.bottom);
clipRegion = set_control_clipping( hdc, &rectEdit );
SendMessageW(lphc->owner, WM_DRAWITEM, ctlid, (LPARAM)&dis );
/*
* Reset the clipping region.
*/
SelectClipRgn(hdc, clipRegion);
SelectClipRgn( hdc, clipRegion );
if (clipRegion) DeleteObject( clipRegion );
}
else
{

View File

@ -243,4 +243,6 @@ typedef struct tagDIALOGINFO
extern DIALOGINFO *DIALOG_get_info( HWND hwnd, BOOL create ) 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 */

View File

@ -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
else everything ends clipped */
GetClientRect(descr->self, &r);
hrgn = CreateRectRgnIndirect(&r);
SelectClipRgn( hdc, hrgn);
DeleteObject( hrgn );
hrgn = set_control_clipping( hdc, &r );
dis.CtlType = ODT_LISTBOX;
dis.CtlID = GetWindowLongPtrW( descr->self, GWLP_ID );
@ -565,6 +563,8 @@ static void LISTBOX_PaintItem( LB_DESCR *descr, HDC hdc, const RECT *rect,
descr->self, index, debugstr_w(item->str), action,
dis.itemState, wine_dbgstr_rect(rect) );
SendMessageW(descr->owner, WM_DRAWITEM, dis.CtlID, (LPARAM)&dis);
SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
}
else
{

View File

@ -108,34 +108,6 @@ const struct builtin_class_descr STATIC_builtin_class =
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
*
@ -317,12 +289,13 @@ static VOID STATIC_TryPaintFcn(HWND hwnd, LONG full_style)
if (!IsRectEmpty(&rc) && IsWindowVisible(hwnd) && staticPaintFunc[style])
{
HDC hdc;
HRGN hOrigClipping;
HRGN hrgn;
hdc = GetDC( hwnd );
setup_clipping(hwnd, hdc, &hOrigClipping);
hrgn = set_control_clipping( hdc, &rc );
(staticPaintFunc[style])( hwnd, hdc, full_style );
restore_clipping(hdc, hOrigClipping);
SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
ReleaseDC( hwnd, hdc );
}
}
@ -418,13 +391,15 @@ LRESULT StaticWndProc_common( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam
case WM_PAINT:
{
PAINTSTRUCT ps;
RECT rect;
HDC hdc = wParam ? (HDC)wParam : BeginPaint(hwnd, &ps);
GetClientRect( hwnd, &rect );
if (staticPaintFunc[style])
{
HRGN hOrigClipping;
setup_clipping(hwnd, hdc, &hOrigClipping);
HRGN hrgn = set_control_clipping( hdc, &rect );
(staticPaintFunc[style])( hwnd, hdc, full_style );
restore_clipping(hdc, hOrigClipping);
SelectClipRgn( hdc, hrgn );
if (hrgn) DeleteObject( hrgn );
}
if (!wParam) EndPaint(hwnd, &ps);
}

View File

@ -26,6 +26,7 @@
#include "wingdi.h"
#include "winuser.h"
#include "user_private.h"
#include "controls.h"
#include "wine/unicode.h"
#include "wine/debug.h"
@ -112,6 +113,32 @@ static const signed char LTRBInnerFlat[] = {
#define COLOR_MAX COLOR_MENUBAR
/***********************************************************************
* 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
*