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;
|
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 )
|
|||||||
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 )
|
|||||||
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:
|
|||||||
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 )
|
|||||||
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 )
|
|||||||
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 )
|
|||||||
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 )
|
|||||||
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 )
|
|||||||
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 )
|
|||||||
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
|
||||||
|
* 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
|
/* There is 1-pixel margin at the left, right, and bottom */
|
||||||
* that label will be drawn out of client rect.
|
rc.left--; rc.right++; rc.bottom++;
|
||||||
* But Windows doesn't clip label's rect, so do I.
|
FillRect(hDC, &rc, hbr);
|
||||||
*/
|
rc.left++; rc.right--; rc.bottom--;
|
||||||
|
|
||||||
/* There is 1-pixel margin at the left, right, and bottom */
|
BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
|
||||||
rc.left--; rc.right++; rc.bottom++;
|
}
|
||||||
FillRect(hDC, &rc, hbr);
|
SelectClipRgn( hDC, hrgn );
|
||||||
rc.left++; rc.right--; rc.bottom--;
|
if (hrgn) DeleteObject( hrgn );
|
||||||
|
|
||||||
BUTTON_DrawLabel(hwnd, hDC, dtFlags, &rc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -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 )
|
|||||||
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(
|
|||||||
!(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(
|
|||||||
/*
|
/*
|
||||||
* 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
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 =
|
|||||||
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)
|
|||||||
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
|
|||||||
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 @@
|
|||||||
#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"
|
||||||
|
|
||||||
@ -112,6 +113,32 @@ static const signed char LTRBInnerFlat[] = {
|
|||||||
#define COLOR_MAX COLOR_MENUBAR
|
#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
|
* UITOOLS_DrawDiagEdge
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user