2 * Window painting functions
4 * Copyright 1993 Alexandre Julliard
14 /* Last CTLCOLOR id */
15 #define CTLCOLOR_MAX CTLCOLOR_STATIC
18 /***********************************************************************
19 * BeginPaint (USER.39)
21 HDC
BeginPaint( HWND hwnd
, LPPAINTSTRUCT lps
)
24 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
25 if (!wndPtr
) return 0;
27 hrgnUpdate
= wndPtr
->hrgnUpdate
; /* Save update region */
28 if (!hrgnUpdate
) /* Create an empty region */
29 if (!(hrgnUpdate
= CreateRectRgn( 0, 0, 0, 0 ))) return 0;
31 if (wndPtr
->hrgnUpdate
|| (wndPtr
->flags
& WIN_INTERNAL_PAINT
))
32 MSG_DecPaintCount( wndPtr
->hmemTaskQ
);
34 wndPtr
->hrgnUpdate
= 0;
35 wndPtr
->flags
&= ~(WIN_NEEDS_BEGINPAINT
| WIN_INTERNAL_PAINT
);
37 if (!(lps
->hdc
= GetDCEx( hwnd
, hrgnUpdate
,
38 DCX_INTERSECTRGN
| DCX_USESTYLE
)))
40 fprintf( stderr
, "GetDCEx() failed in BeginPaint(), hwnd=%d\n", hwnd
);
41 DeleteObject( hrgnUpdate
);
44 GetRgnBox( InquireVisRgn(lps
->hdc
), &lps
->rcPaint
);
45 DPtoLP( lps
->hdc
, (LPPOINT
)&lps
->rcPaint
, 2 );
47 SendMessage( hwnd
, WM_NCPAINT
, hrgnUpdate
, 0 );
48 DeleteObject( hrgnUpdate
);
50 if (!(wndPtr
->flags
& WIN_ERASE_UPDATERGN
)) lps
->fErase
= TRUE
;
51 else lps
->fErase
= !SendMessage( hwnd
, WM_ERASEBKGND
, lps
->hdc
, 0 );
57 /***********************************************************************
60 void EndPaint( HWND hwnd
, LPPAINTSTRUCT lps
)
62 ReleaseDC( hwnd
, lps
->hdc
);
66 /***********************************************************************
67 * FillWindow (USER.324)
69 void FillWindow( HWND hwndParent
, HWND hwnd
, HDC hdc
, HBRUSH hbrush
)
72 GetClientRect( hwnd
, &rect
);
73 DPtoLP( hdc
, (LPPOINT
)&rect
, 2 );
74 PaintRect( hwndParent
, hwnd
, hdc
, hbrush
, &rect
);
78 /***********************************************************************
79 * PaintRect (USER.325)
81 void PaintRect(HWND hwndParent
, HWND hwnd
, HDC hdc
, HBRUSH hbrush
, LPRECT rect
)
83 /* Send WM_CTLCOLOR message if needed */
85 if (hbrush
<= CTLCOLOR_MAX
)
87 if (!hwndParent
) return;
88 hbrush
= (HBRUSH
)SendMessage( hwndParent
, WM_CTLCOLOR
,
89 hdc
, hwnd
| (hbrush
<< 16) );
91 if (hbrush
) FillRect( hdc
, rect
, hbrush
);
95 /***********************************************************************
96 * RedrawWindow (USER.290)
98 BOOL
RedrawWindow( HWND hwnd
, LPRECT rectUpdate
, HRGN hrgnUpdate
, UINT flags
)
100 HRGN tmpRgn
, hrgn
= 0;
101 RECT rectClient
, rectWindow
;
104 if (!hwnd
) hwnd
= GetDesktopWindow();
105 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return FALSE
;
106 if (!(wndPtr
->dwStyle
& WS_VISIBLE
) || (wndPtr
->flags
& WIN_NO_REDRAW
))
107 return TRUE
; /* No redraw needed */
109 GetClientRect( hwnd
, &rectClient
);
110 rectWindow
= wndPtr
->rectWindow
;
111 OffsetRect(&rectWindow
, -wndPtr
->rectClient
.left
, -wndPtr
->rectClient
.top
);
113 if (flags
& RDW_INVALIDATE
) /* Invalidate */
115 if (flags
& RDW_ERASE
) wndPtr
->flags
|= WIN_ERASE_UPDATERGN
;
117 if (hrgnUpdate
) /* Invalidate a region */
119 if (flags
& RDW_FRAME
) tmpRgn
= CreateRectRgnIndirect(&rectWindow
);
120 else tmpRgn
= CreateRectRgnIndirect( &rectClient
);
121 if (!tmpRgn
) return FALSE
;
122 hrgn
= CreateRectRgn( 0, 0, 0, 0 );
123 if (CombineRgn( hrgn
, hrgnUpdate
, tmpRgn
, RGN_AND
) == NULLREGION
)
125 DeleteObject( hrgn
);
128 DeleteObject( tmpRgn
);
130 else /* Invalidate a rectangle */
133 if (flags
& RDW_FRAME
)
135 if (rectUpdate
) IntersectRect( &rect
, rectUpdate
, &rectWindow
);
136 else rect
= rectWindow
;
140 if (rectUpdate
) IntersectRect( &rect
, rectUpdate
, &rectClient
);
141 else rect
= rectClient
;
143 if (!IsRectEmpty(&rect
)) hrgn
= CreateRectRgnIndirect( &rect
);
146 /* Set update region */
150 if (!wndPtr
->hrgnUpdate
)
152 wndPtr
->hrgnUpdate
= hrgn
;
153 if (!(wndPtr
->flags
& WIN_INTERNAL_PAINT
))
154 MSG_IncPaintCount( wndPtr
->hmemTaskQ
);
158 tmpRgn
= CreateRectRgn( 0, 0, 0, 0 );
159 CombineRgn( tmpRgn
, wndPtr
->hrgnUpdate
, hrgn
, RGN_OR
);
160 DeleteObject( wndPtr
->hrgnUpdate
);
161 DeleteObject( hrgn
);
162 wndPtr
->hrgnUpdate
= tmpRgn
;
165 flags
|= RDW_FRAME
; /* Force invalidating the frame of children */
167 else if (flags
& RDW_VALIDATE
) /* Validate */
169 if (flags
& RDW_NOERASE
) wndPtr
->flags
&= ~WIN_ERASE_UPDATERGN
;
170 if (!(hrgn
= CreateRectRgn( 0, 0, 0, 0 ))) return FALSE
;
172 /* Remove frame from update region */
174 if (wndPtr
->hrgnUpdate
&& (flags
& RDW_NOFRAME
))
176 if (!(tmpRgn
= CreateRectRgnIndirect( &rectClient
)))
178 if (CombineRgn(hrgn
,tmpRgn
,wndPtr
->hrgnUpdate
,RGN_AND
) == NULLREGION
)
180 DeleteObject( hrgn
);
183 DeleteObject( tmpRgn
);
184 DeleteObject( wndPtr
->hrgnUpdate
);
185 wndPtr
->hrgnUpdate
= hrgn
;
186 hrgn
= CreateRectRgn( 0, 0, 0, 0 );
189 /* Set update region */
191 if (wndPtr
->hrgnUpdate
)
194 if (hrgnUpdate
) /* Validate a region */
196 res
= CombineRgn(hrgn
,wndPtr
->hrgnUpdate
,hrgnUpdate
,RGN_DIFF
);
198 else /* Validate a rectangle */
200 if (rectUpdate
) tmpRgn
= CreateRectRgnIndirect( rectUpdate
);
201 else tmpRgn
= CreateRectRgnIndirect( &rectWindow
);
202 res
= CombineRgn( hrgn
, wndPtr
->hrgnUpdate
, tmpRgn
, RGN_DIFF
);
203 DeleteObject( tmpRgn
);
205 DeleteObject( wndPtr
->hrgnUpdate
);
206 if (res
== NULLREGION
)
208 DeleteObject( hrgn
);
209 wndPtr
->hrgnUpdate
= 0;
210 if (!(wndPtr
->flags
& WIN_INTERNAL_PAINT
))
211 MSG_DecPaintCount( wndPtr
->hmemTaskQ
);
213 else wndPtr
->hrgnUpdate
= hrgn
;
217 /* Set/clear internal paint flag */
219 if (flags
& RDW_INTERNALPAINT
)
221 if (!wndPtr
->hrgnUpdate
&& !(wndPtr
->flags
& WIN_INTERNAL_PAINT
))
222 MSG_IncPaintCount( wndPtr
->hmemTaskQ
);
223 wndPtr
->flags
|= WIN_INTERNAL_PAINT
;
225 else if (flags
& RDW_NOINTERNALPAINT
)
227 if (!wndPtr
->hrgnUpdate
&& (wndPtr
->flags
& WIN_INTERNAL_PAINT
))
228 MSG_DecPaintCount( wndPtr
->hmemTaskQ
);
229 wndPtr
->flags
&= ~WIN_INTERNAL_PAINT
;
232 /* Erase/update window */
234 if (flags
& RDW_UPDATENOW
) UpdateWindow( hwnd
);
235 else if (flags
& RDW_ERASENOW
)
237 HDC hdc
= GetDCEx( hwnd
, wndPtr
->hrgnUpdate
,
238 DCX_INTERSECTRGN
| DCX_USESTYLE
);
241 SendMessage( hwnd
, WM_NCPAINT
, wndPtr
->hrgnUpdate
, 0 );
243 /* Don't send WM_ERASEBKGND to icons */
244 /* (WM_ICONERASEBKGND is sent during processing of WM_NCPAINT) */
245 if (!(wndPtr
->dwStyle
& WS_MINIMIZE
)
246 || !WIN_CLASS_INFO(wndPtr
).hIcon
)
247 SendMessage( hwnd
, WM_ERASEBKGND
, hdc
, 0 );
248 ReleaseDC( hwnd
, hdc
);
252 /* Recursively process children */
254 if (!(flags
& RDW_NOCHILDREN
) &&
255 ((flags
&& RDW_ALLCHILDREN
) || !(wndPtr
->dwStyle
& WS_CLIPCHILDREN
)))
259 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
260 if (!hrgn
) return TRUE
;
261 for (hwnd
= wndPtr
->hwndChild
; (hwnd
); hwnd
= wndPtr
->hwndNext
)
263 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) break;
264 CombineRgn( hrgn
, hrgnUpdate
, 0, RGN_COPY
);
265 OffsetRgn( hrgn
, -wndPtr
->rectClient
.left
,
266 -wndPtr
->rectClient
.top
);
267 RedrawWindow( hwnd
, NULL
, hrgn
, flags
);
269 DeleteObject( hrgn
);
274 for (hwnd
= wndPtr
->hwndChild
; (hwnd
); hwnd
= wndPtr
->hwndNext
)
276 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) break;
280 OffsetRect( &rect
, -wndPtr
->rectClient
.left
,
281 -wndPtr
->rectClient
.top
);
282 RedrawWindow( hwnd
, &rect
, 0, flags
);
284 else RedrawWindow( hwnd
, NULL
, 0, flags
);
292 /***********************************************************************
293 * UpdateWindow (USER.124)
295 void UpdateWindow( HWND hwnd
)
297 if (GetUpdateRect( hwnd
, NULL
, FALSE
))
299 if (IsWindowVisible( hwnd
)) SendMessage( hwnd
, WM_PAINT
, 0, 0 );
304 /***********************************************************************
305 * InvalidateRgn (USER.126)
307 void InvalidateRgn( HWND hwnd
, HRGN hrgn
, BOOL erase
)
309 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_INVALIDATE
| (erase
? RDW_ERASE
: 0) );
313 /***********************************************************************
314 * InvalidateRect (USER.125)
316 void InvalidateRect( HWND hwnd
, LPRECT rect
, BOOL erase
)
318 RedrawWindow( hwnd
, rect
, 0, RDW_INVALIDATE
| (erase
? RDW_ERASE
: 0) );
322 /***********************************************************************
323 * ValidateRgn (USER.128)
325 void ValidateRgn( HWND hwnd
, HRGN hrgn
)
327 RedrawWindow( hwnd
, NULL
, hrgn
, RDW_VALIDATE
| RDW_NOCHILDREN
);
331 /***********************************************************************
332 * ValidateRect (USER.127)
334 void ValidateRect( HWND hwnd
, LPRECT rect
)
336 RedrawWindow( hwnd
, rect
, 0, RDW_VALIDATE
| RDW_NOCHILDREN
);
340 /***********************************************************************
341 * GetUpdateRect (USER.190)
343 BOOL
GetUpdateRect( HWND hwnd
, LPRECT rect
, BOOL erase
)
345 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
346 if (!wndPtr
) return FALSE
;
350 if (wndPtr
->hrgnUpdate
)
352 HRGN hrgn
= CreateRectRgn( 0, 0, 0, 0 );
353 if (GetUpdateRgn( hwnd
, hrgn
, erase
) == ERROR
) return FALSE
;
354 GetRgnBox( hrgn
, rect
);
355 DeleteObject( hrgn
);
357 else SetRectEmpty( rect
);
359 return (wndPtr
->hrgnUpdate
!= 0);
363 /***********************************************************************
364 * GetUpdateRgn (USER.237)
366 int GetUpdateRgn( HWND hwnd
, HRGN hrgn
, BOOL erase
)
370 WND
* wndPtr
= WIN_FindWndPtr( hwnd
);
371 if (!wndPtr
) return ERROR
;
373 if (!wndPtr
->hrgnUpdate
)
375 if (!(hrgnClip
= CreateRectRgn( 0, 0, 0, 0 ))) return ERROR
;
376 retval
= CombineRgn( hrgn
, hrgnClip
, 0, RGN_COPY
);
380 hrgnClip
= CreateRectRgn( 0, 0,
381 wndPtr
->rectClient
.right
-wndPtr
->rectClient
.left
,
382 wndPtr
->rectClient
.bottom
-wndPtr
->rectClient
.top
);
383 if (!hrgnClip
) return ERROR
;
384 retval
= CombineRgn( hrgn
, wndPtr
->hrgnUpdate
, hrgnClip
, RGN_AND
);
387 HDC hdc
= GetDCEx( hwnd
, wndPtr
->hrgnUpdate
,
388 DCX_INTERSECTRGN
| DCX_USESTYLE
);
391 SendMessage( hwnd
, WM_ERASEBKGND
, hdc
, 0 );
392 ReleaseDC( hwnd
, hdc
);
396 DeleteObject( hrgnClip
);
401 /***********************************************************************
402 * ExcludeUpdateRgn (USER.238)
404 int ExcludeUpdateRgn( HDC hdc
, HWND hwnd
)
410 if (!(wndPtr
= WIN_FindWndPtr( hwnd
))) return ERROR
;
411 if ((hrgn
= CreateRectRgn( 0, 0, 0, 0 )) != 0)
413 retval
= CombineRgn( hrgn
, InquireVisRgn(hdc
),
414 wndPtr
->hrgnUpdate
, RGN_DIFF
);
415 if (retval
) SelectVisRgn( hdc
, hrgn
);
416 DeleteObject( hrgn
);