user32: Add a common helper to set controls clip region, and make it behave correctly when mirrored.
This commit is contained in:
parent
05375a2a96
commit
0f90053575
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue