Release 951105
[wine/multimedia.git] / windows / painting.c
blob014426df0a093017b6bf96c30d54e0158cf52249
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="NPFMT"\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, (WPARAM)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 ((DWORD)hbrush <= CTLCOLOR_MAX)
98 if (!hwndParent) return;
99 #ifdef WINELIB32
100 hbrush = (HBRUSH)SendMessage( hwndParent,
101 WM_CTLCOLORMSGBOX+(DWORD)hbrush,
102 (WPARAM)hdc, (LPARAM)hwnd );
103 #else
104 hbrush = (HBRUSH)SendMessage( hwndParent, WM_CTLCOLOR,
105 hdc, MAKELONG( hwnd, hbrush ) );
106 #endif
108 if (hbrush) FillRect( hdc, rect, hbrush );
112 /***********************************************************************
113 * GetControlBrush (USER.326)
115 HBRUSH GetControlBrush( HWND hwnd, HDC hdc, WORD control )
117 #ifdef WINELIB32
118 return (HBRUSH)SendMessage( GetParent(hwnd), WM_CTLCOLOR+control,
119 (WPARAM)hdc, (LPARAM)hwnd );
120 #else
121 return (HBRUSH)SendMessage( GetParent(hwnd), WM_CTLCOLOR,
122 hdc, MAKELONG( hwnd, control ) );
123 #endif
127 /***********************************************************************
128 * RedrawWindow (USER.290)
130 BOOL RedrawWindow( HWND hwnd, LPRECT rectUpdate, HRGN hrgnUpdate, UINT flags )
132 HRGN tmpRgn, hrgn;
133 RECT rectClient;
134 WND * wndPtr;
136 if (!hwnd) hwnd = GetDesktopWindow();
137 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
138 if (!IsWindowVisible(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
139 return TRUE; /* No redraw needed */
141 if (rectUpdate)
143 dprintf_win( stddeb, "RedrawWindow: "NPFMT" %ld,%ld-%ld,%ld "NPFMT" flags=%04x\n",
144 hwnd, (LONG)rectUpdate->left, (LONG)rectUpdate->top,
145 (LONG)rectUpdate->right, (LONG)rectUpdate->bottom, hrgnUpdate, flags);
147 else
149 dprintf_win( stddeb, "RedrawWindow: "NPFMT" NULL "NPFMT" flags=%04x\n",
150 hwnd, hrgnUpdate, flags);
152 GetClientRect( hwnd, &rectClient );
154 if (flags & RDW_INVALIDATE) /* Invalidate */
156 if (wndPtr->hrgnUpdate) /* Is there already an update region? */
158 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
159 if ((hrgn = hrgnUpdate) == 0)
160 hrgn = CreateRectRgnIndirect( rectUpdate ? rectUpdate :
161 &rectClient );
162 CombineRgn( tmpRgn, wndPtr->hrgnUpdate, hrgn, RGN_OR );
163 DeleteObject( wndPtr->hrgnUpdate );
164 wndPtr->hrgnUpdate = tmpRgn;
165 if (!hrgnUpdate) DeleteObject( hrgn );
167 else /* No update region yet */
169 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
170 MSG_IncPaintCount( wndPtr->hmemTaskQ );
171 if (hrgnUpdate)
173 wndPtr->hrgnUpdate = CreateRectRgn( 0, 0, 0, 0 );
174 CombineRgn( wndPtr->hrgnUpdate, hrgnUpdate, 0, RGN_COPY );
176 else wndPtr->hrgnUpdate = CreateRectRgnIndirect( rectUpdate ?
177 rectUpdate : &rectClient );
179 if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
180 if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
181 flags |= RDW_FRAME; /* Force invalidating the frame of children */
183 else if (flags & RDW_VALIDATE) /* Validate */
185 /* We need an update region in order to validate anything */
186 if (wndPtr->hrgnUpdate)
188 if (!hrgnUpdate && !rectUpdate)
190 /* Special case: validate everything */
191 DeleteObject( wndPtr->hrgnUpdate );
192 wndPtr->hrgnUpdate = 0;
194 else
196 tmpRgn = CreateRectRgn( 0, 0, 0, 0 );
197 if ((hrgn = hrgnUpdate) == 0)
198 hrgn = CreateRectRgnIndirect( rectUpdate );
199 if (CombineRgn( tmpRgn, wndPtr->hrgnUpdate,
200 hrgn, RGN_DIFF ) == NULLREGION)
202 DeleteObject( tmpRgn );
203 tmpRgn = 0;
205 DeleteObject( wndPtr->hrgnUpdate );
206 wndPtr->hrgnUpdate = tmpRgn;
207 if (!hrgnUpdate) DeleteObject( hrgn );
209 if (!wndPtr->hrgnUpdate) /* No more update region */
210 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
211 MSG_DecPaintCount( wndPtr->hmemTaskQ );
213 if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
214 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
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) SendMessage( hwnd, WM_PAINT, 0, 0 );
235 else if (flags & RDW_ERASENOW)
237 if (wndPtr->flags & WIN_NEEDS_NCPAINT)
239 wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
240 SendMessage( hwnd, WM_NCPAINT, 0, 0 );
242 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
244 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
245 DCX_INTERSECTRGN | DCX_USESTYLE );
246 if (hdc)
248 /* Don't send WM_ERASEBKGND to icons */
249 /* (WM_ICONERASEBKGND is sent during processing of WM_NCPAINT) */
250 if (!(wndPtr->dwStyle & WS_MINIMIZE)
251 || !WIN_CLASS_INFO(wndPtr).hIcon)
253 if (SendMessage( hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0 ))
254 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
256 ReleaseDC( hwnd, hdc );
261 /* Recursively process children */
263 if (!(flags & RDW_NOCHILDREN) &&
264 ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
266 if (hrgnUpdate)
268 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
269 if (!hrgn) return TRUE;
270 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
272 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
273 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
274 OffsetRgn( hrgn, -wndPtr->rectClient.left,
275 -wndPtr->rectClient.top );
276 RedrawWindow( hwnd, NULL, hrgn, flags );
278 DeleteObject( hrgn );
280 else
282 RECT rect;
283 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
285 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
286 if (rectUpdate)
288 rect = *rectUpdate;
289 OffsetRect( &rect, -wndPtr->rectClient.left,
290 -wndPtr->rectClient.top );
291 RedrawWindow( hwnd, &rect, 0, flags );
293 else RedrawWindow( hwnd, NULL, 0, flags );
297 return TRUE;
301 /***********************************************************************
302 * UpdateWindow (USER.124)
304 void UpdateWindow( HWND hwnd )
306 RedrawWindow( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
310 /***********************************************************************
311 * InvalidateRgn (USER.126)
313 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
315 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
319 /***********************************************************************
320 * InvalidateRect (USER.125)
322 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
324 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
328 /***********************************************************************
329 * ValidateRgn (USER.128)
331 void ValidateRgn( HWND hwnd, HRGN hrgn )
333 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
337 /***********************************************************************
338 * ValidateRect (USER.127)
340 void ValidateRect( HWND hwnd, LPRECT rect )
342 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
346 /***********************************************************************
347 * GetUpdateRect (USER.190)
349 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
351 WND * wndPtr = WIN_FindWndPtr( hwnd );
352 if (!wndPtr) return FALSE;
354 if (rect)
356 if (wndPtr->hrgnUpdate)
358 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
359 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
360 GetRgnBox( hrgn, rect );
361 DeleteObject( hrgn );
363 else SetRectEmpty( rect );
365 return (wndPtr->hrgnUpdate != 0);
369 /***********************************************************************
370 * GetUpdateRgn (USER.237)
372 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
374 int retval;
375 WND * wndPtr = WIN_FindWndPtr( hwnd );
376 if (!wndPtr) return ERROR;
378 if (!wndPtr->hrgnUpdate)
380 SetRectRgn( hrgn, 0, 0, 0, 0 );
381 return NULLREGION;
383 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
384 if (erase) RedrawWindow( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
385 return retval;
389 /***********************************************************************
390 * ExcludeUpdateRgn (USER.238)
392 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
394 int retval = ERROR;
395 HRGN hrgn;
396 WND * wndPtr;
398 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
399 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
401 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
402 wndPtr->hrgnUpdate, RGN_DIFF );
403 if (retval) SelectVisRgn( hdc, hrgn );
404 DeleteObject( hrgn );
406 return retval;