Release 941227
[wine/multimedia.git] / windows / painting.c
blob16251ca1718db2dbd711d16b2c612c62b9a40abb
1 /*
2 * Window painting functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <stdio.h>
10 #include <X11/Xlib.h>
12 #include "win.h"
13 #include "message.h"
14 #include "gdi.h"
16 /* Last CTLCOLOR id */
17 #define CTLCOLOR_MAX CTLCOLOR_STATIC
20 /***********************************************************************
21 * BeginPaint (USER.39)
23 HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
25 HRGN hrgnUpdate;
26 WND * wndPtr = WIN_FindWndPtr( hwnd );
27 if (!wndPtr) return 0;
29 hrgnUpdate = wndPtr->hrgnUpdate; /* Save update region */
30 if (!hrgnUpdate) /* Create an empty region */
31 if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
33 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
34 MSG_DecPaintCount( wndPtr->hmemTaskQ );
36 wndPtr->hrgnUpdate = 0;
37 wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
39 if (!(lps->hdc = GetDCEx( hwnd, hrgnUpdate,
40 DCX_INTERSECTRGN | DCX_USESTYLE )))
42 fprintf( stderr, "GetDCEx() failed in BeginPaint(), hwnd=%d\n", hwnd );
43 DeleteObject( hrgnUpdate );
44 return 0;
46 GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
47 DPtoLP( lps->hdc, (LPPOINT)&lps->rcPaint, 2 );
49 SendMessage( hwnd, WM_NCPAINT, hrgnUpdate, 0 );
50 DeleteObject( hrgnUpdate );
52 if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE;
53 else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
55 return lps->hdc;
59 /***********************************************************************
60 * EndPaint (USER.40)
62 void EndPaint( HWND hwnd, LPPAINTSTRUCT lps )
64 ReleaseDC( hwnd, lps->hdc );
68 /***********************************************************************
69 * FillWindow (USER.324)
71 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
73 RECT rect;
74 GetClientRect( hwnd, &rect );
75 DPtoLP( hdc, (LPPOINT)&rect, 2 );
76 PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
80 /***********************************************************************
81 * PaintRect (USER.325)
83 void PaintRect(HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush, LPRECT rect)
85 /* Send WM_CTLCOLOR message if needed */
87 if (hbrush <= CTLCOLOR_MAX)
89 if (!hwndParent) return;
90 hbrush = (HBRUSH)SendMessage( hwndParent, WM_CTLCOLOR,
91 hdc, hwnd | (hbrush << 16) );
93 if (hbrush) FillRect( hdc, rect, hbrush );
97 /***********************************************************************
98 * RedrawWindow (USER.290)
100 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
102 HRGN tmpRgn, hrgn = 0;
103 RECT rectClient, rectWindow;
104 WND * wndPtr;
106 if (!hwnd) hwnd = GetDesktopWindow();
107 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
108 if (!(wndPtr->dwStyle & WS_VISIBLE) || (wndPtr->flags & WIN_NO_REDRAW))
109 return TRUE; /* No redraw needed */
111 GetClientRect( hwnd, &rectClient );
112 rectWindow = wndPtr->rectWindow;
113 OffsetRect(&rectWindow, -wndPtr->rectClient.left, -wndPtr->rectClient.top);
115 if (flags & RDW_INVALIDATE) /* Invalidate */
117 if (flags & RDW_ERASE) wndPtr->flags |= WIN_ERASE_UPDATERGN;
119 if (hrgnUpdate) /* Invalidate a region */
121 if (flags & RDW_FRAME) tmpRgn = CreateRectRgnIndirect(&rectWindow);
122 else tmpRgn = CreateRectRgnIndirect( &rectClient );
123 if (!tmpRgn) return FALSE;
124 hrgn = CreateRectRgn( 0, 0, 0, 0 );
125 if (CombineRgn( hrgn, hrgnUpdate, tmpRgn, RGN_AND ) == NULLREGION)
127 DeleteObject( hrgn );
128 hrgn = 0;
130 DeleteObject( tmpRgn );
132 else /* Invalidate a rectangle */
134 RECT rect;
135 if (flags & RDW_FRAME)
137 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectWindow);
138 else rect = rectWindow;
140 else
142 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectClient);
143 else rect = rectClient;
145 if (!IsRectEmpty(&rect)) hrgn = CreateRectRgnIndirect( &rect );
148 /* Set update region */
150 if (hrgn)
152 if (!wndPtr->hrgnUpdate)
154 wndPtr->hrgnUpdate = hrgn;
155 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
156 MSG_IncPaintCount( wndPtr->hmemTaskQ );
158 else
160 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
161 CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
162 DeleteObject( wndPtr->hrgnUpdate );
163 DeleteObject( hrgn );
164 wndPtr->hrgnUpdate = tmpRgn;
167 flags |= RDW_FRAME; /* Force invalidating the frame of children */
169 else if (flags & RDW_VALIDATE) /* Validate */
171 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_ERASE_UPDATERGN;
172 if (!(hrgn = CreateRectRgn( 0, 0, 0, 0 ))) return FALSE;
174 /* Remove frame from update region */
176 if (wndPtr->hrgnUpdate && (flags & RDW_NOFRAME))
178 if (!(tmpRgn = CreateRectRgnIndirect( &rectClient )))
179 return FALSE;
180 if (CombineRgn(hrgn,tmpRgn,wndPtr->hrgnUpdate,RGN_AND) == NULLREGION)
182 DeleteObject( hrgn );
183 hrgn = 0;
185 DeleteObject( tmpRgn );
186 DeleteObject( wndPtr->hrgnUpdate );
187 wndPtr->hrgnUpdate = hrgn;
188 hrgn = CreateRectRgn( 0, 0, 0, 0 );
191 /* Set update region */
193 if (wndPtr->hrgnUpdate)
195 int res;
196 if (hrgnUpdate) /* Validate a region */
198 res = CombineRgn(hrgn,wndPtr->hrgnUpdate,hrgnUpdate,RGN_DIFF);
200 else /* Validate a rectangle */
202 if (rectUpdate) tmpRgn = CreateRectRgnIndirect( rectUpdate );
203 else tmpRgn = CreateRectRgnIndirect( &rectWindow );
204 res = CombineRgn( hrgn, wndPtr->hrgnUpdate, tmpRgn, RGN_DIFF );
205 DeleteObject( tmpRgn );
207 DeleteObject( wndPtr->hrgnUpdate );
208 if (res == NULLREGION)
210 DeleteObject( hrgn );
211 wndPtr->hrgnUpdate = 0;
212 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
213 MSG_DecPaintCount( wndPtr->hmemTaskQ );
215 else wndPtr->hrgnUpdate = hrgn;
219 /* Set/clear internal paint flag */
221 if (flags & RDW_INTERNALPAINT)
223 if (!wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
224 MSG_IncPaintCount( wndPtr->hmemTaskQ );
225 wndPtr->flags |= WIN_INTERNAL_PAINT;
227 else if (flags & RDW_NOINTERNALPAINT)
229 if (!wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
230 MSG_DecPaintCount( wndPtr->hmemTaskQ );
231 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
234 /* Erase/update window */
236 if (flags & RDW_UPDATENOW) UpdateWindow( hwnd );
237 else if (flags & RDW_ERASENOW)
239 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
240 DCX_INTERSECTRGN | DCX_USESTYLE );
241 if (hdc)
243 SendMessage( hwnd, WM_NCPAINT, wndPtr->hrgnUpdate, 0 );
245 /* Don't send WM_ERASEBKGND to icons */
246 /* (WM_ICONERASEBKGND is sent during processing of WM_NCPAINT) */
247 if (!(wndPtr->dwStyle & WS_MINIMIZE)
248 || !WIN_CLASS_INFO(wndPtr).hIcon)
249 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
250 ReleaseDC( hwnd, hdc );
254 /* Recursively process children */
256 if (!(flags & RDW_NOCHILDREN) &&
257 ((flags && RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
259 if (hrgnUpdate)
261 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
262 if (!hrgn) return TRUE;
263 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
265 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
266 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
267 OffsetRgn( hrgn, -wndPtr->rectClient.left,
268 -wndPtr->rectClient.top );
269 RedrawWindow( hwnd, NULL, hrgn, flags );
271 DeleteObject( hrgn );
273 else
275 RECT rect;
276 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
278 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
279 if (rectUpdate)
281 rect = *rectUpdate;
282 OffsetRect( &rect, -wndPtr->rectClient.left,
283 -wndPtr->rectClient.top );
284 RedrawWindow( hwnd, &rect, 0, flags );
286 else RedrawWindow( hwnd, NULL, 0, flags );
290 return TRUE;
294 /***********************************************************************
295 * UpdateWindow (USER.124)
297 void UpdateWindow( HWND hwnd )
299 if (GetUpdateRect( hwnd, NULL, FALSE ))
301 if (IsWindowVisible( hwnd )) SendMessage( hwnd, WM_PAINT, 0, 0 );
306 /***********************************************************************
307 * InvalidateRgn (USER.126)
309 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
311 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
315 /***********************************************************************
316 * InvalidateRect (USER.125)
318 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
320 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
324 /***********************************************************************
325 * ValidateRgn (USER.128)
327 void ValidateRgn( HWND hwnd, HRGN hrgn )
329 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
333 /***********************************************************************
334 * ValidateRect (USER.127)
336 void ValidateRect( HWND hwnd, LPRECT rect )
338 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
342 /***********************************************************************
343 * GetUpdateRect (USER.190)
345 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
347 WND * wndPtr = WIN_FindWndPtr( hwnd );
348 if (!wndPtr) return FALSE;
350 if (rect)
352 if (wndPtr->hrgnUpdate)
354 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
355 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
356 GetRgnBox( hrgn, rect );
357 DeleteObject( hrgn );
359 else SetRectEmpty( rect );
361 return (wndPtr->hrgnUpdate != 0);
365 /***********************************************************************
366 * GetUpdateRgn (USER.237)
368 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
370 HRGN hrgnClip;
371 int retval;
372 WND * wndPtr = WIN_FindWndPtr( hwnd );
373 if (!wndPtr) return ERROR;
375 if (!wndPtr->hrgnUpdate)
377 if (!(hrgnClip = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
378 retval = CombineRgn( hrgn, hrgnClip, 0, RGN_COPY );
380 else
382 hrgnClip = CreateRectRgn( 0, 0,
383 wndPtr->rectClient.right-wndPtr->rectClient.left,
384 wndPtr->rectClient.bottom-wndPtr->rectClient.top );
385 if (!hrgnClip) return ERROR;
386 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
387 if (erase)
389 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
390 DCX_INTERSECTRGN | DCX_USESTYLE );
391 if (hdc)
393 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
394 ReleaseDC( hwnd, hdc );
398 DeleteObject( hrgnClip );
399 return retval;
403 /***********************************************************************
404 * ExcludeUpdateRgn (USER.238)
406 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
408 int retval = ERROR;
409 HRGN hrgn;
410 WND * wndPtr;
412 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
413 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
415 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
416 wndPtr->hrgnUpdate, RGN_DIFF );
417 if (retval) SelectVisRgn( hdc, hrgn );
418 DeleteObject( hrgn );
420 return retval;