Release 970305
[wine/multimedia.git] / windows / painting.c
blob78f60625d4e463b84e9f9c57311caeb7c8894d8f
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 "queue.h"
12 #include "gdi.h"
13 #include "dce.h"
14 #include "heap.h"
15 #include "stddebug.h"
16 /* #define DEBUG_WIN */
17 #include "debug.h"
19 /* Last CTLCOLOR id */
20 #define CTLCOLOR_MAX CTLCOLOR_STATIC
22 /***********************************************************************
23 * WIN_UpdateNCArea
26 void WIN_UpdateNCArea(WND* wnd, BOOL32 bUpdate)
28 POINT16 pt = {0, 0};
29 HRGN32 hClip = 1;
31 dprintf_nonclient(stddeb,"NCUpdate: hwnd %04x, hrgnUpdate %04x\n",
32 wnd->hwndSelf, wnd->hrgnUpdate );
34 /* desktop window doesn't have nonclient area */
35 if(wnd == WIN_GetDesktop())
37 wnd->flags &= ~WIN_NEEDS_NCPAINT;
38 return;
41 if( wnd->hrgnUpdate > 1 )
43 ClientToScreen16(wnd->hwndSelf, &pt);
45 hClip = CreateRectRgn32( 0, 0, 0, 0 );
46 if (!CombineRgn32( hClip, wnd->hrgnUpdate, 0, RGN_COPY ))
48 DeleteObject32(hClip);
49 hClip = 1;
51 else
52 OffsetRgn32( hClip, pt.x, pt.y );
54 if (bUpdate)
56 /* exclude non-client area from update region */
57 HRGN32 hrgn = CreateRectRgn32( 0, 0,
58 wnd->rectClient.right - wnd->rectClient.left,
59 wnd->rectClient.bottom - wnd->rectClient.top);
61 if (hrgn && (CombineRgn32( wnd->hrgnUpdate, wnd->hrgnUpdate,
62 hrgn, RGN_AND) == NULLREGION))
64 DeleteObject32( wnd->hrgnUpdate );
65 wnd->hrgnUpdate = 1;
68 DeleteObject32( hrgn );
72 wnd->flags &= ~WIN_NEEDS_NCPAINT;
74 if ((wnd->hwndSelf == GetActiveWindow32()) &&
75 !(wnd->flags & WIN_NCACTIVATED))
77 wnd->flags |= WIN_NCACTIVATED;
78 if( hClip > 1) DeleteObject32( hClip );
79 hClip = 1;
82 if (hClip) SendMessage16( wnd->hwndSelf, WM_NCPAINT, hClip, 0L );
84 if (hClip > 1) DeleteObject32( hClip );
88 /***********************************************************************
89 * BeginPaint16 (USER.39)
91 HDC16 BeginPaint16( HWND16 hwnd, LPPAINTSTRUCT16 lps )
93 BOOL32 bIcon;
94 HRGN32 hrgnUpdate;
95 WND *wndPtr = WIN_FindWndPtr( hwnd );
96 if (!wndPtr) return 0;
98 bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
100 wndPtr->flags &= ~WIN_NEEDS_BEGINPAINT;
102 if (wndPtr->flags & WIN_NEEDS_NCPAINT) WIN_UpdateNCArea( wndPtr, TRUE );
104 if (((hrgnUpdate = wndPtr->hrgnUpdate) != 0) ||
105 (wndPtr->flags & WIN_INTERNAL_PAINT))
106 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
108 wndPtr->hrgnUpdate = 0;
109 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
111 HideCaret32( hwnd );
113 dprintf_win(stddeb,"hrgnUpdate = %04x, ", hrgnUpdate);
115 /* When bIcon is TRUE hrgnUpdate is automatically in window coordinates
116 * (because rectClient == rectWindow for WS_MINIMIZE windows).
119 if (wndPtr->class->style & CS_PARENTDC)
120 /* Don't clip the output to the update region for CS_PARENTDC window */
121 lps->hdc = GetDCEx16( hwnd, 0, DCX_WINDOWPAINT | DCX_USESTYLE |
122 (bIcon ? DCX_WINDOW : 0) );
123 else
124 lps->hdc = GetDCEx16(hwnd, hrgnUpdate, DCX_INTERSECTRGN |
125 DCX_WINDOWPAINT | DCX_USESTYLE |
126 (bIcon ? DCX_WINDOW : 0) );
128 dprintf_win(stddeb,"hdc = %04x\n", lps->hdc);
130 if (!lps->hdc)
132 fprintf(stderr, "GetDCEx() failed in BeginPaint(), hwnd=%04x\n", hwnd);
133 return 0;
136 GetRgnBox16( InquireVisRgn(lps->hdc), &lps->rcPaint );
137 DPtoLP16( lps->hdc, (LPPOINT16)&lps->rcPaint, 2 );
139 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
141 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
142 lps->fErase = !SendMessage16(hwnd, (bIcon) ? WM_ICONERASEBKGND
143 : WM_ERASEBKGND,
144 (WPARAM16)lps->hdc, 0 );
146 else lps->fErase = TRUE;
148 return lps->hdc;
152 /***********************************************************************
153 * BeginPaint32 (USER32.9)
155 HDC32 BeginPaint32( HWND32 hwnd, PAINTSTRUCT32 *lps )
157 PAINTSTRUCT16 ps;
159 BeginPaint16( hwnd, &ps );
160 lps->hdc = (HDC32)ps.hdc;
161 lps->fErase = ps.fErase;
162 lps->rcPaint.top = ps.rcPaint.top;
163 lps->rcPaint.left = ps.rcPaint.left;
164 lps->rcPaint.right = ps.rcPaint.right;
165 lps->rcPaint.bottom = ps.rcPaint.bottom;
166 lps->fRestore = ps.fRestore;
167 lps->fIncUpdate = ps.fIncUpdate;
168 return lps->hdc;
172 /***********************************************************************
173 * EndPaint16 (USER.40)
175 BOOL16 EndPaint16( HWND16 hwnd, const PAINTSTRUCT16* lps )
177 ReleaseDC16( hwnd, lps->hdc );
178 ShowCaret32( hwnd );
179 return TRUE;
183 /***********************************************************************
184 * EndPaint32 (USER32.175)
186 BOOL32 EndPaint32( HWND32 hwnd, const PAINTSTRUCT32 *lps )
188 ReleaseDC32( hwnd, lps->hdc );
189 ShowCaret32( hwnd );
190 return TRUE;
194 /***********************************************************************
195 * FillWindow (USER.324)
197 void FillWindow( HWND16 hwndParent, HWND16 hwnd, HDC16 hdc, HBRUSH16 hbrush )
199 RECT16 rect;
200 GetClientRect16( hwnd, &rect );
201 DPtoLP16( hdc, (LPPOINT16)&rect, 2 );
202 PaintRect( hwndParent, hwnd, hdc, hbrush, &rect );
206 /***********************************************************************
207 * PaintRect (USER.325)
209 void PaintRect( HWND16 hwndParent, HWND16 hwnd, HDC16 hdc,
210 HBRUSH16 hbrush, const RECT16 *rect)
212 /* Send WM_CTLCOLOR message if needed */
214 if ((UINT32)hbrush <= CTLCOLOR_MAX)
216 if (!hwndParent) return;
217 hbrush = (HBRUSH16)SendMessage32A( hwndParent,
218 WM_CTLCOLORMSGBOX + (UINT32)hbrush,
219 (WPARAM32)hdc, (LPARAM)hwnd );
221 if (hbrush) FillRect16( hdc, rect, hbrush );
225 /***********************************************************************
226 * GetControlBrush (USER.326)
228 HBRUSH16 GetControlBrush( HWND16 hwnd, HDC16 hdc, UINT16 control )
230 return (HBRUSH16)SendMessage32A( GetParent32(hwnd), WM_CTLCOLOR+control,
231 (WPARAM32)hdc, (LPARAM)hwnd );
235 /***********************************************************************
236 * PAINT_RedrawWindow
238 * Note: Windows uses WM_SYNCPAINT to cut down the number of intertask
239 * SendMessage() calls. From SDK:
240 * This message avoids lots of inter-app message traffic
241 * by switching to the other task and continuing the
242 * recursion there.
244 * wParam = flags
245 * LOWORD(lParam) = hrgnClip
246 * HIWORD(lParam) = hwndSkip (not used; always NULL)
248 BOOL32 PAINT_RedrawWindow( HWND32 hwnd, const RECT32 *rectUpdate,
249 HRGN32 hrgnUpdate, UINT32 flags, UINT32 control )
251 BOOL32 bIcon;
252 HRGN32 hrgn;
253 RECT32 rectClient;
254 WND* wndPtr;
255 WND **list, **ppWnd;
257 if (!hwnd) hwnd = GetDesktopWindow32();
258 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return FALSE;
259 if (!IsWindowVisible32(hwnd) || (wndPtr->flags & WIN_NO_REDRAW))
260 return TRUE; /* No redraw needed */
262 bIcon = (wndPtr->dwStyle & WS_MINIMIZE && wndPtr->class->hIcon);
263 if (rectUpdate)
265 dprintf_win(stddeb, "RedrawWindow: %04x %d,%d-%d,%d %04x flags=%04x\n",
266 hwnd, rectUpdate->left, rectUpdate->top,
267 rectUpdate->right, rectUpdate->bottom, hrgnUpdate, flags );
269 else
271 dprintf_win(stddeb, "RedrawWindow: %04x NULL %04x flags=%04x\n",
272 hwnd, hrgnUpdate, flags);
275 GetClientRect32( hwnd, &rectClient );
277 if (flags & RDW_INVALIDATE) /* Invalidate */
279 int rgnNotEmpty = COMPLEXREGION;
281 if (wndPtr->hrgnUpdate > 1) /* Is there already an update region? */
283 if ((hrgn = hrgnUpdate) == 0)
284 hrgn = CreateRectRgnIndirect32( rectUpdate ? rectUpdate :
285 &rectClient );
286 rgnNotEmpty = CombineRgn32( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
287 hrgn, RGN_OR );
288 if (!hrgnUpdate) DeleteObject32( hrgn );
290 else /* No update region yet */
292 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
293 QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
294 if (hrgnUpdate)
296 wndPtr->hrgnUpdate = CreateRectRgn32( 0, 0, 0, 0 );
297 rgnNotEmpty = CombineRgn32( wndPtr->hrgnUpdate, hrgnUpdate,
298 0, RGN_COPY );
300 else wndPtr->hrgnUpdate = CreateRectRgnIndirect32( rectUpdate ?
301 rectUpdate : &rectClient );
304 if (flags & RDW_FRAME) wndPtr->flags |= WIN_NEEDS_NCPAINT;
306 /* check for bogus update region */
307 if ( rgnNotEmpty == NULLREGION )
309 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
310 DeleteObject32( wndPtr->hrgnUpdate );
311 wndPtr->hrgnUpdate=0;
312 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
313 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
315 else
316 if (flags & RDW_ERASE) wndPtr->flags |= WIN_NEEDS_ERASEBKGND;
317 flags |= RDW_FRAME; /* Force children frame invalidation */
319 else if (flags & RDW_VALIDATE) /* Validate */
321 /* We need an update region in order to validate anything */
322 if (wndPtr->hrgnUpdate > 1)
324 if (!hrgnUpdate && !rectUpdate)
326 /* Special case: validate everything */
327 DeleteObject32( wndPtr->hrgnUpdate );
328 wndPtr->hrgnUpdate = 0;
330 else
332 if ((hrgn = hrgnUpdate) == 0)
333 hrgn = CreateRectRgnIndirect32( rectUpdate );
334 if (CombineRgn32( wndPtr->hrgnUpdate, wndPtr->hrgnUpdate,
335 hrgn, RGN_DIFF ) == NULLREGION)
337 DeleteObject32( wndPtr->hrgnUpdate );
338 wndPtr->hrgnUpdate = 0;
340 if (!hrgnUpdate) DeleteObject32( hrgn );
342 if (!wndPtr->hrgnUpdate) /* No more update region */
343 if (!(wndPtr->flags & WIN_INTERNAL_PAINT))
344 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
346 if (flags & RDW_NOFRAME) wndPtr->flags &= ~WIN_NEEDS_NCPAINT;
347 if (flags & RDW_NOERASE) wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
350 /* Set/clear internal paint flag */
352 if (flags & RDW_INTERNALPAINT)
354 if ( wndPtr->hrgnUpdate <= 1 && !(wndPtr->flags & WIN_INTERNAL_PAINT))
355 QUEUE_IncPaintCount( wndPtr->hmemTaskQ );
356 wndPtr->flags |= WIN_INTERNAL_PAINT;
358 else if (flags & RDW_NOINTERNALPAINT)
360 if ( wndPtr->hrgnUpdate <= 1 && (wndPtr->flags & WIN_INTERNAL_PAINT))
361 QUEUE_DecPaintCount( wndPtr->hmemTaskQ );
362 wndPtr->flags &= ~WIN_INTERNAL_PAINT;
365 /* Erase/update window */
367 if (flags & RDW_UPDATENOW)
369 if (wndPtr->hrgnUpdate) /* wm_painticon wparam is 1 */
370 SendMessage16( hwnd, (bIcon) ? WM_PAINTICON : WM_PAINT, bIcon, 0 );
372 else if (flags & RDW_ERASENOW)
374 if (wndPtr->flags & WIN_NEEDS_NCPAINT)
375 WIN_UpdateNCArea( wndPtr, FALSE);
377 if (wndPtr->flags & WIN_NEEDS_ERASEBKGND)
379 HDC32 hdc = GetDCEx32( hwnd, wndPtr->hrgnUpdate,
380 DCX_INTERSECTRGN | DCX_USESTYLE |
381 DCX_KEEPCLIPRGN | DCX_WINDOWPAINT |
382 (bIcon ? DCX_WINDOW : 0) );
383 if (hdc)
385 if (SendMessage16( hwnd, (bIcon) ? WM_ICONERASEBKGND
386 : WM_ERASEBKGND,
387 (WPARAM16)hdc, 0 ))
388 wndPtr->flags &= ~WIN_NEEDS_ERASEBKGND;
389 ReleaseDC32( hwnd, hdc );
394 /* Recursively process children */
396 if (!(flags & RDW_NOCHILDREN) &&
397 ((flags & RDW_ALLCHILDREN) || !(wndPtr->dwStyle & WS_CLIPCHILDREN)) &&
398 !(wndPtr->dwStyle & WS_MINIMIZE) )
400 if ( hrgnUpdate || rectUpdate )
402 if (!(hrgn = CreateRectRgn32( 0, 0, 0, 0 ))) return TRUE;
403 if( !hrgnUpdate )
405 control |= (RDW_C_DELETEHRGN | RDW_C_USEHRGN);
406 if( !(hrgnUpdate = CreateRectRgnIndirect32( rectUpdate )) )
408 DeleteObject32( hrgn );
409 return TRUE;
412 list = WIN_BuildWinArray( wndPtr );
413 for (ppWnd = list; *ppWnd; ppWnd++)
415 wndPtr = *ppWnd;
416 if (!IsWindow32(wndPtr->hwndSelf)) continue;
417 if (wndPtr->dwStyle & WS_VISIBLE)
419 SetRectRgn32( hrgn, wndPtr->rectWindow.left,
420 wndPtr->rectWindow.top,
421 wndPtr->rectWindow.right,
422 wndPtr->rectWindow.bottom );
423 if (!CombineRgn32( hrgn, hrgn, hrgnUpdate, RGN_AND ))
424 continue;
425 OffsetRgn32( hrgn, -wndPtr->rectClient.left,
426 -wndPtr->rectClient.top );
427 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, hrgn, flags,
428 RDW_C_USEHRGN );
431 HeapFree( SystemHeap, 0, list );
432 DeleteObject32( hrgn );
433 if (control & RDW_C_DELETEHRGN) DeleteObject32( hrgnUpdate );
435 else
437 list = WIN_BuildWinArray( wndPtr );
438 for (ppWnd = list; *ppWnd; ppWnd++)
440 wndPtr = *ppWnd;
441 if (IsWindow32( wndPtr->hwndSelf ))
442 PAINT_RedrawWindow( wndPtr->hwndSelf, NULL, 0, flags, 0 );
444 HeapFree( SystemHeap, 0, list );
448 return TRUE;
452 /***********************************************************************
453 * RedrawWindow32 (USER32.425)
455 BOOL32 RedrawWindow32( HWND32 hwnd, const RECT32 *rectUpdate,
456 HRGN32 hrgnUpdate, UINT32 flags )
458 WND* wnd = WIN_FindWndPtr( hwnd );
460 /* check if there is something to redraw */
462 return ( wnd && WIN_IsWindowDrawable( wnd, !(flags & RDW_FRAME) ) )
463 ? PAINT_RedrawWindow( hwnd, rectUpdate, hrgnUpdate, flags, 0 )
464 : 1;
468 /***********************************************************************
469 * RedrawWindow16 (USER.290)
471 BOOL16 RedrawWindow16( HWND16 hwnd, const RECT16 *rectUpdate,
472 HRGN16 hrgnUpdate, UINT16 flags )
474 if (rectUpdate)
476 RECT32 r;
477 CONV_RECT16TO32( rectUpdate, &r );
478 return (BOOL16)RedrawWindow32( (HWND32)hwnd, &r, hrgnUpdate, flags );
480 return (BOOL16)RedrawWindow32( (HWND32)hwnd, NULL, hrgnUpdate, flags );
484 /***********************************************************************
485 * UpdateWindow16 (USER.124)
487 void UpdateWindow16( HWND16 hwnd )
489 RedrawWindow32( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
493 /***********************************************************************
494 * UpdateWindow32 (USER32.566)
496 void UpdateWindow32( HWND32 hwnd )
498 RedrawWindow32( hwnd, NULL, 0, RDW_UPDATENOW | RDW_NOCHILDREN );
502 /***********************************************************************
503 * InvalidateRgn16 (USER.126)
505 void InvalidateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
507 RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
511 /***********************************************************************
512 * InvalidateRgn32 (USER32.328)
514 void InvalidateRgn32( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
516 RedrawWindow32(hwnd, NULL, hrgn, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
520 /***********************************************************************
521 * InvalidateRect16 (USER.125)
523 void InvalidateRect16( HWND16 hwnd, const RECT16 *rect, BOOL16 erase )
525 RedrawWindow16( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
529 /***********************************************************************
530 * InvalidateRect32 (USER32.327)
532 void InvalidateRect32( HWND32 hwnd, const RECT32 *rect, BOOL32 erase )
534 RedrawWindow32( hwnd, rect, 0, RDW_INVALIDATE | (erase ? RDW_ERASE : 0) );
538 /***********************************************************************
539 * ValidateRgn16 (USER.128)
541 void ValidateRgn16( HWND16 hwnd, HRGN16 hrgn )
543 RedrawWindow32( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
547 /***********************************************************************
548 * ValidateRgn32 (USER32.571)
550 void ValidateRgn32( HWND32 hwnd, HRGN32 hrgn )
552 RedrawWindow32( hwnd, NULL, hrgn, RDW_VALIDATE | RDW_NOCHILDREN );
556 /***********************************************************************
557 * ValidateRect16 (USER.127)
559 void ValidateRect16( HWND16 hwnd, const RECT16 *rect )
561 RedrawWindow16( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
565 /***********************************************************************
566 * ValidateRect32 (USER32.570)
568 void ValidateRect32( HWND32 hwnd, const RECT32 *rect )
570 RedrawWindow32( hwnd, rect, 0, RDW_VALIDATE | RDW_NOCHILDREN );
574 /***********************************************************************
575 * GetUpdateRect16 (USER.190)
577 BOOL16 GetUpdateRect16( HWND16 hwnd, LPRECT16 rect, BOOL16 erase )
579 RECT32 r;
580 BOOL16 ret;
582 if (!rect) return GetUpdateRect32( hwnd, NULL, erase );
583 ret = GetUpdateRect32( hwnd, &r, erase );
584 CONV_RECT32TO16( &r, rect );
585 return ret;
589 /***********************************************************************
590 * GetUpdateRect32 (USER32.296)
592 BOOL32 GetUpdateRect32( HWND32 hwnd, LPRECT32 rect, BOOL32 erase )
594 WND * wndPtr = WIN_FindWndPtr( hwnd );
595 if (!wndPtr) return FALSE;
597 if (rect)
599 if (wndPtr->hrgnUpdate > 1)
601 HRGN32 hrgn = CreateRectRgn32( 0, 0, 0, 0 );
602 if (GetUpdateRgn32( hwnd, hrgn, erase ) == ERROR) return FALSE;
603 GetRgnBox32( hrgn, rect );
604 DeleteObject32( hrgn );
606 else SetRectEmpty32( rect );
608 return (wndPtr->hrgnUpdate > 1);
612 /***********************************************************************
613 * GetUpdateRgn16 (USER.237)
615 INT16 GetUpdateRgn16( HWND16 hwnd, HRGN16 hrgn, BOOL16 erase )
617 return GetUpdateRgn32( hwnd, hrgn, erase );
621 /***********************************************************************
622 * GetUpdateRgn32 (USER32.297)
624 INT32 GetUpdateRgn32( HWND32 hwnd, HRGN32 hrgn, BOOL32 erase )
626 INT32 retval;
627 WND * wndPtr = WIN_FindWndPtr( hwnd );
628 if (!wndPtr) return ERROR;
630 if (wndPtr->hrgnUpdate <= 1)
632 SetRectRgn32( hrgn, 0, 0, 0, 0 );
633 return NULLREGION;
635 retval = CombineRgn32( hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY );
636 if (erase) RedrawWindow32( hwnd, NULL, 0, RDW_ERASENOW | RDW_NOCHILDREN );
637 return retval;
641 /***********************************************************************
642 * ExcludeUpdateRgn16 (USER.238)
644 INT16 ExcludeUpdateRgn16( HDC16 hdc, HWND16 hwnd )
646 return ExcludeUpdateRgn32( hdc, hwnd );
650 /***********************************************************************
651 * ExcludeUpdateRgn32 (USER32.194)
653 INT32 ExcludeUpdateRgn32( HDC32 hdc, HWND32 hwnd )
655 RECT32 rect;
656 WND * wndPtr;
658 if (!(wndPtr = WIN_FindWndPtr( hwnd ))) return ERROR;
660 if (wndPtr->hrgnUpdate)
662 INT32 ret;
663 HRGN32 hrgn = CreateRectRgn32(wndPtr->rectWindow.left - wndPtr->rectClient.left,
664 wndPtr->rectWindow.top - wndPtr->rectClient.top,
665 wndPtr->rectClient.right - wndPtr->rectClient.left,
666 wndPtr->rectClient.bottom - wndPtr->rectClient.top);
667 if( wndPtr->hrgnUpdate > 1 )
668 CombineRgn32(hrgn, wndPtr->hrgnUpdate, 0, RGN_COPY);
670 /* do ugly coordinate translations in dce.c */
672 ret = DCE_ExcludeRgn( hdc, wndPtr, hrgn );
673 DeleteObject32( hrgn );
674 return ret;
676 return GetClipBox32( hdc, &rect );