2 * Window painting functions
4 * Copyright 1993 Alexandre Julliard
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
15 /* Last CTLCOLOR id */
16 #define CTLCOLOR_MAX CTLCOLOR_STATIC
19 /***********************************************************************
20 * BeginPaint (USER.39)
22 HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
25 WND * wndPtr = WIN_FindWndPtr( hwnd );
26 if (!wndPtr) return 0;
28 hrgnUpdate = wndPtr->hrgnUpdate; /* Save update region */
29 if (!hrgnUpdate) /* Create an empty region */
30 if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
32 if (!(lps->hdc = GetDCEx( hwnd, hrgnUpdate,
33 DCX_INTERSECTRGN | DCX_USESTYLE ))) return 0;
34 GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
36 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
37 MSG_DecPaintCount( wndPtr->hmemTaskQ );
39 wndPtr->hrgnUpdate = 0;
40 wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
42 SendMessage( hwnd, WM_NCPAINT, hrgnUpdate, 0 );
43 DeleteObject( hrgnUpdate );
45 if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE;
46 else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
52 /***********************************************************************
55 void EndPaint( HWND hwnd, LPPAINTSTRUCT lps )
57 ReleaseDC( hwnd, lps->hdc );
61 /***********************************************************************
62 * FillWindow (USER.324)
64 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
67 GetClientRect( hwnd, &rect );
68 PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
72 /***********************************************************************
73 * PaintRect (USER.325)
75 void PaintRect(HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush, LPRECT rect)
77 /* Send WM_CTLCOLOR message if needed */
79 if (hbrush <= CTLCOLOR_MAX)
81 if (!hwndParent) return;
82 hbrush = (HBRUSH)SendMessage( hwndParent, WM_CTLCOLOR,
83 hdc, hwnd | (hbrush << 16) );
85 if (hbrush) FillRect( hdc, rect, hbrush );
89 /***********************************************************************
90 * RedrawWindow (USER.290)
92 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
94 HRGN tmpRgn, hrgn = 0;
95 RECT rectClient, rectWindow;
98 if (!hwnd) hwnd = GetDesktopWindow();
99 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
100 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
101 return TRUE; /* No redraw needed */
103 GetClientRect( hwnd, &rectClient );
104 rectWindow = wndPtr->rectWindow;
105 OffsetRect(&rectWindow, -wndPtr->rectClient.left, -wndPtr->rectClient.top);
107 if (flags & RDW_INVALIDATE) /* Invalidate */
109 if (flags & RDW_ERASE) wndPtr->flags |= WIN_ERASE_UPDATERGN;
111 if (hrgnUpdate) /* Invalidate a region */
113 if (flags & RDW_FRAME) tmpRgn = CreateRectRgnIndirect(&rectWindow);
114 else tmpRgn = CreateRectRgnIndirect( &rectClient );
115 if (!tmpRgn) return FALSE;
116 hrgn = CreateRectRgn( 0, 0, 0, 0 );
117 if (CombineRgn( hrgn, hrgnUpdate, tmpRgn, RGN_AND ) == NULLREGION)
119 DeleteObject( hrgn );
122 DeleteObject( tmpRgn );
124 else /* Invalidate a rectangle */
127 if (flags & RDW_FRAME)
129 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectWindow);
130 else rect = rectWindow;
134 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectClient);
135 else rect = rectClient;
137 if (!IsRectEmpty(&rect)) hrgn = CreateRectRgnIndirect( &rect );
140 /* Set update region */
144 if (!wndPtr->hrgnUpdate)
146 wndPtr->hrgnUpdate = hrgn;
147 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
148 MSG_IncPaintCount( wndPtr->hmemTaskQ );
152 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
153 CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
154 DeleteObject( wndPtr->hrgnUpdate );
155 DeleteObject( hrgn );
156 wndPtr->hrgnUpdate = tmpRgn;
159 flags |= RDW_FRAME; /* Force invalidating the frame of children */
161 else if (flags & RDW_VALIDATE) /* Validate */
163 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_ERASE_UPDATERGN;
164 if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
166 /* Remove frame from update region */
168 if (wndPtr->hrgnUpdate && (flags & RDW_NOFRAME))
170 if (!(tmpRgn = CreateRectRgnIndirect( &rectClient )))
172 if (CombineRgn(hrgn,tmpRgn,wndPtr->hrgnUpdate,RGN_AND) == NULLREGION)
174 DeleteObject( hrgn );
177 DeleteObject( tmpRgn );
178 DeleteObject( wndPtr->hrgnUpdate );
179 wndPtr->hrgnUpdate = hrgn;
180 hrgn = CreateRectRgn( 0, 0, 0, 0 );
183 /* Set update region */
185 if (wndPtr->hrgnUpdate)
188 if (hrgnUpdate) /* Validate a region */
190 res = CombineRgn(hrgn,wndPtr->hrgnUpdate,hrgnUpdate,RGN_DIFF);
192 else /* Validate a rectangle */
194 if (rectUpdate) tmpRgn = CreateRectRgnIndirect( rectUpdate );
195 else tmpRgn = CreateRectRgnIndirect( &rectWindow );
196 res = CombineRgn( hrgn, wndPtr->hrgnUpdate, tmpRgn, RGN_DIFF );
197 DeleteObject( tmpRgn );
199 DeleteObject( wndPtr->hrgnUpdate );
200 if (res == NULLREGION)
202 DeleteObject( hrgn );
203 wndPtr->hrgnUpdate = 0;
204 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
205 MSG_DecPaintCount( wndPtr->hmemTaskQ );
207 else wndPtr->hrgnUpdate = hrgn;
211 /* Set/clear internal paint flag */
213 if (flags & RDW_INTERNALPAINT)
215 if (!wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
216 MSG_IncPaintCount( wndPtr->hmemTaskQ );
217 wndPtr->flags |= WIN_INTERNAL_PAINT;
219 else if (flags & RDW_NOINTERNALPAINT)
221 if (!wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
222 MSG_DecPaintCount( wndPtr->hmemTaskQ );
223 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
226 /* Erase/update window */
228 if (flags & RDW_UPDATENOW) UpdateWindow( hwnd );
229 else if (flags & RDW_ERASENOW)
231 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
232 DCX_INTERSECTRGN | DCX_USESTYLE );
235 SendMessage( hwnd, WM_NCPAINT, wndPtr->hrgnUpdate, 0 );
237 /* Don't send WM_ERASEBKGND to icons */
238 /* (WM_ICONERASEBKGND is sent during processing of WM_NCPAINT) */
239 if (!(wndPtr->dwStyle & WS_MINIMIZE)
240 || !WIN_CLASS_INFO(wndPtr).hIcon)
241 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
242 ReleaseDC( hwnd, hdc );
246 /* Recursively process children */
248 if (!(flags & RDW_NOCHILDREN) &&
249 ((flags && RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
253 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
254 if (!hrgn) return TRUE;
255 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
257 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
258 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
259 OffsetRgn( hrgn, -wndPtr->rectClient.left,
260 -wndPtr->rectClient.top );
261 RedrawWindow( hwnd, NULL, hrgn, flags );
263 DeleteObject( hrgn );
268 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
270 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
274 OffsetRect( &rect, -wndPtr->rectClient.left,
275 -wndPtr->rectClient.top );
276 RedrawWindow( hwnd, &rect, 0, flags );
278 else RedrawWindow( hwnd, NULL, 0, flags );
286 /***********************************************************************
287 * UpdateWindow (USER.124)
289 void UpdateWindow( HWND hwnd )
291 if (GetUpdateRect( hwnd, NULL, FALSE ))
293 if (IsWindowVisible( hwnd )) SendMessage( hwnd, WM_PAINT, 0, 0 );
298 /***********************************************************************
299 * InvalidateRgn (USER.126)
301 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
303 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
307 /***********************************************************************
308 * InvalidateRect (USER.125)
310 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
312 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
316 /***********************************************************************
317 * ValidateRgn (USER.128)
319 void ValidateRgn( HWND hwnd, HRGN hrgn )
321 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
325 /***********************************************************************
326 * ValidateRect (USER.127)
328 void ValidateRect( HWND hwnd, LPRECT rect )
330 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
334 /***********************************************************************
335 * GetUpdateRect (USER.190)
337 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
339 WND * wndPtr = WIN_FindWndPtr( hwnd );
340 if (!wndPtr) return FALSE;
344 if (wndPtr->hrgnUpdate)
346 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
347 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
348 GetRgnBox( hrgn, rect );
349 DeleteObject( hrgn );
351 else SetRectEmpty( rect );
353 return (wndPtr->hrgnUpdate != 0);
357 /***********************************************************************
358 * GetUpdateRgn (USER.237)
360 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
364 WND * wndPtr = WIN_FindWndPtr( hwnd );
365 if (!wndPtr) return ERROR;
367 if (!wndPtr->hrgnUpdate)
369 if (!(hrgnClip = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
370 retval = CombineRgn( hrgn, hrgnClip, 0, RGN_COPY );
374 hrgnClip = CreateRectRgn( 0, 0,
375 wndPtr->rectClient.right-wndPtr->rectClient.left,
376 wndPtr->rectClient.bottom-wndPtr->rectClient.top );
377 if (!hrgnClip) return ERROR;
378 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
381 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
382 DCX_INTERSECTRGN | DCX_USESTYLE );
385 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
386 ReleaseDC( hwnd, hdc );
390 DeleteObject( hrgnClip );
395 /***********************************************************************
396 * ExcludeUpdateRgn (USER.238)
398 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
404 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
405 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
407 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
408 wndPtr->hrgnUpdate, RGN_DIFF );
409 if (retval) SelectVisRgn( hdc, hrgn );
410 DeleteObject( hrgn );