Release 950109
[wine/multimedia.git] / windows / painting.c
blobfe45db7c8207682609b3fc0a157e2464ee7845c4
1 /*
2 * Window painting functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include <stdio.h>
8 #include <X11/Xlib.h>
10 #include "win.h"
11 #include "message.h"
12 #include "gdi.h"
14 /* Last CTLCOLOR id */
15 #define CTLCOLOR_MAX CTLCOLOR_STATIC
18 /***********************************************************************
19 * BeginPaint (USER.39)
21 HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
23 HRGN hrgnUpdate;
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 );
42 return 0;
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 );
53 return lps->hdc;
57 /***********************************************************************
58 * EndPaint (USER.40)
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 )
71 RECT rect;
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;
102 WND * wndPtr;
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 );
126 hrgn = 0;
128 DeleteObject( tmpRgn );
130 else /* Invalidate a rectangle */
132 RECT rect;
133 if (flags & RDW_FRAME)
135 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectWindow);
136 else rect = rectWindow;
138 else
140 if (rectUpdate) IntersectRect( &rect, rectUpdate, &rectClient);
141 else rect = rectClient;
143 if (!IsRectEmpty(&rect)) hrgn = CreateRectRgnIndirect( &rect );
146 /* Set update region */
148 if (hrgn)
150 if (!wndPtr->hrgnUpdate)
152 wndPtr->hrgnUpdate = hrgn;
153 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
154 MSG_IncPaintCount( wndPtr->hmemTaskQ );
156 else
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 )))
177 return FALSE;
178 if (CombineRgn(hrgn,tmpRgn,wndPtr->hrgnUpdate,RGN_AND) == NULLREGION)
180 DeleteObject( hrgn );
181 hrgn = 0;
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)
193 int res;
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 );
239 if (hdc)
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)))
257 if (hrgnUpdate)
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 );
271 else
273 RECT rect;
274 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
276 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
277 if (rectUpdate)
279 rect = *rectUpdate;
280 OffsetRect( &rect, -wndPtr->rectClient.left,
281 -wndPtr->rectClient.top );
282 RedrawWindow( hwnd, &rect, 0, flags );
284 else RedrawWindow( hwnd, NULL, 0, flags );
288 return TRUE;
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;
348 if (rect)
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 )
368 HRGN hrgnClip;
369 int retval;
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 );
378 else
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 );
385 if (erase)
387 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
388 DCX_INTERSECTRGN | DCX_USESTYLE );
389 if (hdc)
391 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
392 ReleaseDC( hwnd, hdc );
396 DeleteObject( hrgnClip );
397 return retval;
401 /***********************************************************************
402 * ExcludeUpdateRgn (USER.238)
404 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
406 int retval = ERROR;
407 HRGN hrgn;
408 WND * wndPtr;
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 );
418 return retval;