Release 941017
[wine/gsoc-2012-control.git] / windows / painting.c
blob878e9d8ac254530c1c1062c54107af850a226497
1 /*
2 * Window painting functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <X11/Xlib.h>
11 #include "win.h"
12 #include "message.h"
13 #include "gdi.h"
15 /* Last CTLCOLOR id */
16 #define CTLCOLOR_MAX CTLCOLOR_STATIC
19 /***********************************************************************
20 * BeginPaint (USER.39)
22 HDC BeginPaint( HWND hwnd, LPPAINTSTRUCT lps )
24 HRGN hrgnUpdate;
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 );
48 return lps->hdc;
52 /***********************************************************************
53 * EndPaint (USER.40)
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 )
66 RECT rect;
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;
96 WND * wndPtr;
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 */
104 * I can't help but feel that this belongs somewhere upstream...
106 * Don't redraw the window if it is iconified and we have an
107 * icon to draw for it
109 /* if (IsIconic(hwnd) && wndPtr->hIcon) return FALSE; */
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 );
244 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
245 ReleaseDC( hwnd, hdc );
249 /* Recursively process children */
251 if (!(flags & RDW_NOCHILDREN) &&
252 ((flags && RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)))
254 if (hrgnUpdate)
256 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
257 if (!hrgn) return TRUE;
258 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
260 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
261 CombineRgn( hrgn, hrgnUpdate, 0, RGN_COPY );
262 OffsetRgn( hrgn, -wndPtr->rectClient.left,
263 -wndPtr->rectClient.top );
264 RedrawWindow( hwnd, NULL, hrgn, flags );
266 DeleteObject( hrgn );
268 else
270 RECT rect;
271 for (hwnd = wndPtr->hwndChild; (hwnd); hwnd = wndPtr->hwndNext)
273 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) break;
274 if (rectUpdate)
276 rect = *rectUpdate;
277 OffsetRect( &rect, -wndPtr->rectClient.left,
278 -wndPtr->rectClient.top );
279 RedrawWindow( hwnd, &rect, 0, flags );
281 else RedrawWindow( hwnd, NULL, 0, flags );
285 return TRUE;
289 /***********************************************************************
290 * UpdateWindow (USER.124)
292 void UpdateWindow( HWND hwnd )
294 if (GetUpdateRect( hwnd, NULL, FALSE ))
296 if (IsWindowVisible( hwnd )) SendMessage( hwnd, WM_PAINT, 0, 0 );
301 /***********************************************************************
302 * InvalidateRgn (USER.126)
304 void InvalidateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
306 RedrawWindow( hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
310 /***********************************************************************
311 * InvalidateRect (USER.125)
313 void InvalidateRect( HWND hwnd, LPRECT rect, BOOL erase )
315 RedrawWindow( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
319 /***********************************************************************
320 * ValidateRgn (USER.128)
322 void ValidateRgn( HWND hwnd, HRGN hrgn )
324 RedrawWindow( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
328 /***********************************************************************
329 * ValidateRect (USER.127)
331 void ValidateRect( HWND hwnd, LPRECT rect )
333 RedrawWindow( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
337 /***********************************************************************
338 * GetUpdateRect (USER.190)
340 BOOL GetUpdateRect( HWND hwnd, LPRECT rect, BOOL erase )
342 WND * wndPtr = WIN_FindWndPtr( hwnd );
343 if (!wndPtr) return FALSE;
345 if (rect)
347 if (wndPtr->hrgnUpdate)
349 HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
350 if (GetUpdateRgn( hwnd, hrgn, erase ) == ERROR) return FALSE;
351 GetRgnBox( hrgn, rect );
352 DeleteObject( hrgn );
354 else SetRectEmpty( rect );
356 return (wndPtr->hrgnUpdate != 0);
360 /***********************************************************************
361 * GetUpdateRgn (USER.237)
363 int GetUpdateRgn( HWND hwnd, HRGN hrgn, BOOL erase )
365 HRGN hrgnClip;
366 int retval;
367 WND * wndPtr = WIN_FindWndPtr( hwnd );
368 if (!wndPtr) return ERROR;
370 if (!wndPtr->hrgnUpdate)
372 if (!(hrgnClip = CreateRectRgn( 0, 0, 0, 0 ))) return ERROR;
373 retval = CombineRgn( hrgn, hrgnClip, 0, RGN_COPY );
375 else
377 hrgnClip = CreateRectRgn( 0, 0,
378 wndPtr->rectClient.right-wndPtr->rectClient.left,
379 wndPtr->rectClient.bottom-wndPtr->rectClient.top );
380 if (!hrgnClip) return ERROR;
381 retval = CombineRgn( hrgn, wndPtr->hrgnUpdate, hrgnClip, RGN_AND );
382 if (erase)
384 HDC hdc = GetDCEx( hwnd, wndPtr->hrgnUpdate,
385 DCX_INTERSECTRGN | DCX_USESTYLE );
386 if (hdc)
388 SendMessage( hwnd, WM_ERASEBKGND, hdc, 0 );
389 ReleaseDC( hwnd, hdc );
393 DeleteObject( hrgnClip );
394 return retval;
398 /***********************************************************************
399 * ExcludeUpdateRgn (USER.238)
401 int ExcludeUpdateRgn( HDC hdc, HWND hwnd )
403 int retval;
404 HRGN hrgn;
405 WND * wndPtr;
407 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
408 if ((hrgn = CreateRectRgn( 0, 0, 0, 0 )) != 0)
410 retval = CombineRgn( hrgn, InquireVisRgn(hdc),
411 wndPtr->hrgnUpdate, RGN_DIFF );
412 if (retval) SelectVisRgn( hdc, hrgn );
413 DeleteObject( hrgn );
415 return retval;