Release 950727
[wine/multimedia.git] / windows / painting.c
blobb188ac39d10f423a3c43a1fb658b24d8f2d52037
1 /*
2 * Window painting functions
4 * Copyright 1993, 1994, 1995 Alexandre Julliard
5 */
7 #include <stdio.h>
8 #include <X11/Xlib.h>
10 #include "win.h"
11 #include "message.h"
12 #include "gdi.h"
13 #include "stddebug.h"
14 /* #define DEBUG_WIN */
15 #include "debug.h"
17 /* Last CTLCOLOR id */
18 #define CTLCOLOR_MAX CTLCOLOR_STATIC
21 /***********************************************************************
22 * BeginPaint (USER.39)
24 HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
26 HRGN hrgnUpdate;
27 WND * wndPtr = WIN_FindWndPtr( hwnd );
28 if (!wndPtr) return 0;
30 hrgnUpdate = wndPtr->hrgnUpdate; /* Save update region */
31 if (!hrgnUpdate) /* Create an empty region */
32 if (!(hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 ))) return 0;
34 if (wndPtr->hrgnUpdate || (wndPtr->flags & WIN_INTERNAL_PAINT))
35 MSG_DecPaintCount( wndPtr->hmemTaskQ );
37 wndPtr->hrgnUpdate = 0;
38 wndPtr->flags &= ~(WIN_NEEDS_BEGINPAINT | WIN_INTERNAL_PAINT);
40 if (wndPtr->flags & WIN_NEEDS_NCPAINT)
42 wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
43 SendMessage( hwnd, WM_NCPAINT, 0, 0 );
46 lps->hdc = GetDCEx( hwnd, hrgnUpdate, DCX_INTERSECTRGN | DCX_USESTYLE );
47 DeleteObject( hrgnUpdate );
48 if (!lps->hdc)
50 fprintf( stderr, "GetDCEx() failed in BeginPaint(), hwnd=%x\n", hwnd );
51 return 0;
54 GetRgnBox( InquireVisRgn(lps->hdc), &lps->rcPaint );
55 DPtoLP( lps->hdc, (LPPOINT)&lps->rcPaint, 2 );
57 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
59 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
60 lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
62 else lps->fErase = TRUE;
64 return lps->hdc;
68 /***********************************************************************
69 * EndPaint (USER.40)
71 void EndPaint( HWND hwnd, LPPAINTSTRUCT lps )
73 ReleaseDC( hwnd, lps->hdc );
77 /***********************************************************************
78 * FillWindow (USER.324)
80 void FillWindow( HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush )
82 RECT rect;
83 GetClientRect( hwnd, &rect );
84 DPtoLP( hdc, (LPPOINT)&rect, 2 );
85 PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
89 /***********************************************************************
90 * PaintRect (USER.325)
92 void PaintRect(HWND hwndParent, HWND hwnd, HDC hdc, HBRUSH hbrush, LPRECT rect)
94 /* Send WM_CTLCOLOR message if needed */
96 if (hbrush <= CTLCOLOR_MAX)
98 if (!hwndParent) return;
99 hbrush = (HBRUSH)SendMessage( hwndParent, WM_CTLCOLOR,
100 hdc, MAKELONG( hwnd, hbrush ) );
102 if (hbrush) FillRect( hdc, rect, hbrush );
106 /***********************************************************************
107 * GetControlBrush (USER.326)
109 HBRUSH GetControlBrush( HWND hwnd, HDC hdc, WORD control )
111 return (HBRUSH)SendMessage( GetParent(hwnd), WM_CTLCOLOR,
112 hdc, MAKELONG( hwnd, control ) );
116 /***********************************************************************
117 * RedrawWindow (USER.290)
119 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
121 HRGN tmpRgn, hrgn;
122 RECT rectClient;
123 WND * wndPtr;
125 if (!hwnd) hwnd = GetDesktopWindow();
126 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
127 if (!IsWindowVisible(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
128 return TRUE; /* No redraw needed */
130 if (rectUpdate)
132 dprintf_win( stddeb, "RedrawWindow: %x %d,%d-%d,%d %x flags=%04x\n",
133 hwnd, rectUpdate->left, rectUpdate->top,
134 rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags);
136 else
138 dprintf_win( stddeb, "RedrawWindow: %x NULL %x flags=%04x\n",
139 hwnd, hrgnUpdate, flags);
141 GetClientRect( hwnd, &rectClient );
143 if (flags & RDW_INVALIDATE) /* Invalidate */
145 if (wndPtr->hrgnUpdate) /* Is there already an update region? */
147 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
148 if ((hrgn = hrgnUpdate) == 0)
149 hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
150 &rectClient );
151 CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
152 DeleteObject( wndPtr->hrgnUpdate );
153 wndPtr->hrgnUpdate = tmpRgn;
154 if (!hrgnUpdate) DeleteObject( hrgn );
156 else /* No update region yet */
158 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
159 MSG_IncPaintCount( wndPtr->hmemTaskQ );
160 if (hrgnUpdate)
162 wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
163 CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate, 0, RGN_COPY );
165 else wndPtr->hrgnUpdate = CreateRectRgnIndirect( rectUpdate ?
166 rectUpdate : &rectClient );
168 if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
169 if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
170 flags |= RDW_FRAME; /* Force invalidating the frame of children */
172 else if (flags & RDW_VALIDATE) /* Validate */
174 /* We need an update region in order to validate anything */
175 if (wndPtr->hrgnUpdate)
177 if (!hrgnUpdate && !rectUpdate)
179 /* Special case: validate everything */
180 DeleteObject( wndPtr->hrgnUpdate );
181 wndPtr->hrgnUpdate = 0;
183 else
185 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
186 if ((hrgn = hrgnUpdate) == 0)
187 hrgn = CreateRectRgnIndirect( rectUpdate );
188 if (CombineRgn( tmpRgn, wndPtr->hrgnUpdate,
189 hrgn, RGN_DIFF ) == NULLREGION)
191 DeleteObject( tmpRgn );
192 tmpRgn = 0;
194 DeleteObject( wndPtr->hrgnUpdate );
195 wndPtr->hrgnUpdate = tmpRgn;
196 if (!hrgnUpdate) DeleteObject( hrgn );
198 if (!wndPtr->hrgnUpdate) /* No more update region */
199 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
200 MSG_DecPaintCount( wndPtr->hmemTaskQ );
202 if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
203 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
206 /* Set/clear internal paint flag */
208 if (flags & RDW_INTERNALPAINT)
210 if (!wndPtr->hrgnUpdate && !(wndPtr->flags & WIN_INTERNAL_PAINT))
211 MSG_IncPaintCount( wndPtr->hmemTaskQ );
212 wndPtr->flags |= WIN_INTERNAL_PAINT;
214 else if (flags & RDW_NOINTERNALPAINT)
216 if (!wndPtr->hrgnUpdate && (wndPtr->flags & WIN_INTERNAL_PAINT))
217 MSG_DecPaintCount( wndPtr->hmemTaskQ );
218 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
221 /* Erase/update window */
223 if (flags & RDW_UPDATENOW) SendMessage( hwnd, WM_PAINT, 0, 0 );
224 else if (flags & RDW_ERASENOW)
226 if (wndPtr->flags & WIN_NEEDS_NCPAINT)
228 wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
229 SendMessage( hwnd, WM_NCPAINT, 0, 0 );
231 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
233 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
234 DCX_INTERSECTRGN | DCX_USESTYLE );
235 if (hdc)
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)
242 if (SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 ))
243 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
245 ReleaseDC( hwnd, hdc );
250 /* Recursively process children */
252 if (!(flags & RDW_NOCHILDREN) &&
253 ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
255 if (hrgnUpdate)
257 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
258 if (!hrgn) return TRUE;
259 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
261 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
262 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
263 OffsetRgn( hrgn, -wndPtr->rectClient.left,
264 -wndPtr->rectClient.top );
265 RedrawWindow( hwnd, NULL, hrgn, flags );
267 DeleteObject( hrgn );
269 else
271 RECT rect;
272 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
274 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
275 if (rectUpdate)
277 rect = *rectUpdate;
278 OffsetRect( &rect, -wndPtr->rectClient.left,
279 -wndPtr->rectClient.top );
280 RedrawWindow( hwnd, &rect, 0, flags );
282 else RedrawWindow( hwnd, NULL, 0, flags );
286 return TRUE;
290 /***********************************************************************
291 * UpdateWindow (USER.124)
293 void UpdateWindow( HWND hwnd )
295 RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
299 /***********************************************************************
300 * InvalidateRgn (USER.126)
302 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
304 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
308 /***********************************************************************
309 * InvalidateRect (USER.125)
311 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
313 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
317 /***********************************************************************
318 * ValidateRgn (USER.128)
320 void ValidateRgn( HWND hwnd, HRGN hrgn )
322 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
326 /***********************************************************************
327 * ValidateRect (USER.127)
329 void ValidateRect( HWND hwnd, LPRECT rect )
331 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
335 /***********************************************************************
336 * GetUpdateRect (USER.190)
338 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
340 WND * wndPtr = WIN_FindWndPtr( hwnd );
341 if (!wndPtr) return FALSE;
343 if (rect)
345 if (wndPtr->hrgnUpdate)
347 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
348 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
349 GetRgnBox( hrgn, rect );
350 DeleteObject( hrgn );
352 else SetRectEmpty( rect );
354 return (wndPtr->hrgnUpdate != 0);
358 /***********************************************************************
359 * GetUpdateRgn (USER.237)
361 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
363 int retval;
364 WND * wndPtr = WIN_FindWndPtr( hwnd );
365 if (!wndPtr) return ERROR;
367 if (!wndPtr->hrgnUpdate)
369 SetRectRgn( hrgn, 0, 0, 0, 0 );
370 return NULLREGION;
372 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
373 if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
374 return retval;
378 /***********************************************************************
379 * ExcludeUpdateRgn (USER.238)
381 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
383 int retval = ERROR;
384 HRGN hrgn;
385 WND * wndPtr;
387 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
388 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
390 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
391 wndPtr->hrgnUpdate, RGN_DIFF );
392 if (retval) SelectVisRgn( hdc, hrgn );
393 DeleteObject( hrgn );
395 return retval;