2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * $Id: painting.c,v 1.38 2003/11/21 21:12:08 navaraf Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window painting function
24 * FILE: subsys/win32k/ntuser/painting.c
25 * PROGRAMER: Filip Navara (xnavara@volny.cz)
27 * 06/06/2001 Created (?)
28 * 18/11/2003 Complete rewrite
31 /* INCLUDES ******************************************************************/
33 #include <ddk/ntddk.h>
34 #include <internal/safe.h>
35 #include <win32k/win32k.h>
36 #include <include/object.h>
37 #include <include/guicheck.h>
38 #include <include/window.h>
39 #include <include/class.h>
40 #include <include/error.h>
41 #include <include/winsta.h>
43 #include <include/painting.h>
44 #include <user32/wininternal.h>
45 #include <include/rect.h>
46 #include <win32k/coord.h>
47 #include <win32k/region.h>
48 #include <include/vis.h>
53 /* GLOBALS ********************************************************************/
56 * Define this after the desktop will be moved to CSRSS and will
57 * get proper message queue.
59 /* #define DESKTOP_IN_CSRSS */
61 /* PRIVATE FUNCTIONS **********************************************************/
64 IntValidateParent(PWINDOW_OBJECT Child
)
67 PWINDOW_OBJECT ParentWindow
;
69 Parent
= NtUserGetAncestor(Child
->Self
, GA_PARENT
);
70 while (Parent
&& Parent
!= IntGetDesktopWindow())
72 ParentWindow
= IntGetWindowObject(Parent
);
73 if (ParentWindow
&& !(ParentWindow
->Style
& WS_CLIPCHILDREN
))
75 if (ParentWindow
->UpdateRegion
!= 0)
80 * We must offset the child region by the offset of the
81 * child rect in the parent.
83 OffsetX
= Child
->WindowRect
.left
- ParentWindow
->WindowRect
.left
;
84 OffsetY
= Child
->WindowRect
.top
- ParentWindow
->WindowRect
.top
;
85 NtGdiOffsetRgn(Child
->UpdateRegion
, OffsetX
, OffsetY
);
86 NtGdiCombineRgn(ParentWindow
->UpdateRegion
, ParentWindow
->UpdateRegion
,
87 Child
->UpdateRegion
, RGN_DIFF
);
88 /* FIXME: If the resulting region is empty, remove fake posted paint message */
89 NtGdiOffsetRgn(Child
->UpdateRegion
, -OffsetX
, -OffsetY
);
92 IntReleaseWindowObject(ParentWindow
);
93 Parent
= NtUserGetAncestor(Parent
, GA_PARENT
);
98 * IntGetNCUpdateRegion
100 * Get nonclient part of window update region.
103 * Handle to region that represents invalid nonclient window area. The
104 * caller is responsible for deleting it.
107 * This function also marks the nonclient update region of window
108 * as valid, clears the WINDOWOBJECT_NEED_NCPAINT flag and removes
109 * the fake paint message from message queue if the Remove is set
114 IntGetNCUpdateRegion(PWINDOW_OBJECT Window
, BOOL Remove
)
119 WindowRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->ClientRect
);
120 NtGdiOffsetRgn(WindowRgn
,
121 -Window
->WindowRect
.left
,
122 -Window
->WindowRect
.top
);
123 NonclientRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
124 if (NtGdiCombineRgn(NonclientRgn
, Window
->UpdateRegion
,
125 WindowRgn
, RGN_DIFF
) == NULLREGION
)
127 NtGdiDeleteObject(NonclientRgn
);
132 if (NtGdiCombineRgn(Window
->UpdateRegion
, Window
->UpdateRegion
,
133 WindowRgn
, RGN_AND
) == NULLREGION
)
135 NtGdiDeleteObject(Window
->UpdateRegion
);
136 Window
->UpdateRegion
= NULL
;
138 Window
->Flags
&= ~WINDOWOBJECT_NEED_NCPAINT
;
139 MsqDecPaintCountQueue(Window
->MessageQueue
);
148 * Internal function used by IntRedrawWindow.
152 IntPaintWindows(PWINDOW_OBJECT Window
, ULONG Flags
)
155 HWND hWnd
= Window
->Self
;
157 if (!(Window
->Style
& WS_VISIBLE
))
162 if (Flags
& (RDW_ERASENOW
| RDW_UPDATENOW
))
164 if (IntIsDesktopWindow(Window
))
167 * Repainting of desktop window
170 #ifndef DESKTOP_IN_CSRSS
171 VIS_RepaintDesktop(hWnd
, Window
->UpdateRegion
);
172 Window
->Flags
&= ~(WINDOWOBJECT_NEED_NCPAINT
|
173 WINDOWOBJECT_NEED_INTERNALPAINT
| WINDOWOBJECT_NEED_ERASEBKGND
);
174 NtGdiDeleteObject(Window
->UpdateRegion
);
175 Window
->UpdateRegion
= NULL
;
177 if (Window
->Flags
& WINDOWOBJECT_NEED_NCPAINT
)
179 MsqDecPaintCountQueue(Window
->MessageQueue
);
180 Window
->Flags
&= ~WINDOWOBJECT_NEED_NCPAINT
;
182 if (Window
->UpdateRegion
||
183 Window
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
)
185 MsqDecPaintCountQueue(Window
->MessageQueue
);
186 Window
->Flags
&= ~WINDOWOBJECT_NEED_INTERNALPAINT
;
188 if (Window
->UpdateRegion
)
190 hDC
= NtUserGetDCEx(hWnd
, 0, DCX_CACHE
| DCX_USESTYLE
|
191 DCX_INTERSECTUPDATE
);
194 NtUserSendMessage(hWnd
, WM_ERASEBKGND
, (WPARAM
)hDC
, 0);
195 NtUserReleaseDC(hWnd
, hDC
);
196 NtGdiDeleteObject(Window
->UpdateRegion
);
197 Window
->UpdateRegion
= NULL
;
205 * Repainting of non-desktop window
208 if (Window
->Flags
& WINDOWOBJECT_NEED_NCPAINT
)
210 NtUserSendMessage(hWnd
, WM_NCPAINT
, (WPARAM
)IntGetNCUpdateRegion(Window
, TRUE
), 0);
213 if (Window
->Flags
& WINDOWOBJECT_NEED_ERASEBKGND
)
215 if (Window
->UpdateRegion
)
217 hDC
= NtUserGetDCEx(hWnd
, 0, DCX_CACHE
| DCX_USESTYLE
|
218 DCX_INTERSECTUPDATE
);
221 if (NtUserSendMessage(hWnd
, WM_ERASEBKGND
, (WPARAM
)hDC
, 0))
222 Window
->Flags
&= ~WINDOWOBJECT_NEED_ERASEBKGND
;
223 NtUserReleaseDC(hWnd
, hDC
);
228 if (Flags
& RDW_UPDATENOW
)
230 if (Window
->UpdateRegion
!= NULL
||
231 Window
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
)
233 NtUserSendMessage(hWnd
, WM_PAINT
, 0, 0);
234 if (Window
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
)
236 Window
->Flags
&= ~WINDOWOBJECT_NEED_INTERNALPAINT
;
237 if (Window
->UpdateRegion
== NULL
)
239 MsqDecPaintCountQueue(Window
->MessageQueue
);
248 * Check that the window is still valid at this point
251 if (!IntIsWindow(hWnd
))
255 * Paint child windows.
258 if (!(Flags
& RDW_NOCHILDREN
) && !(Window
->Style
& WS_MINIMIZE
) &&
259 ((Flags
& RDW_ALLCHILDREN
) || !(Window
->Style
& WS_CLIPCHILDREN
)))
263 if ((List
= IntWinListChildren(Window
)))
265 for (phWnd
= List
; *phWnd
; ++phWnd
)
267 Window
= IntGetWindowObject(*phWnd
);
270 IntPaintWindows(Window
, Flags
);
271 IntReleaseWindowObject(Window
);
280 * IntInvalidateWindows
282 * Internal function used by IntRedrawWindow.
286 IntInvalidateWindows(PWINDOW_OBJECT Window
, HRGN hRgn
, ULONG Flags
,
290 BOOL HadPaintMessage
, HadNCPaintMessage
;
291 BOOL HasPaintMessage
, HasNCPaintMessage
;
295 * Clip the given region with window rectangle (or region)
299 if (!Window
->WindowRegion
)
302 hRgnWindow
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
303 NtGdiOffsetRgn(hRgnWindow
,
304 -Window
->WindowRect
.left
,
305 -Window
->WindowRect
.top
);
306 RgnType
= NtGdiCombineRgn(hRgn
, hRgn
, hRgnWindow
, RGN_AND
);
307 NtGdiDeleteObject(hRgnWindow
);
312 RgnType
= NtGdiCombineRgn(hRgn
, hRgn
, Window
->WindowRegion
, RGN_AND
);
317 * Save current state of pending updates
320 HadPaintMessage
= Window
->UpdateRegion
!= NULL
||
321 Window
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
;
322 HadNCPaintMessage
= Window
->Flags
& WINDOWOBJECT_NEED_NCPAINT
;
325 * Update the region and flags
328 if (Flags
& RDW_INVALIDATE
&& RgnType
!= NULLREGION
)
330 if (Window
->UpdateRegion
== NULL
)
332 Window
->UpdateRegion
= NtGdiCreateRectRgn(0, 0, 0, 0);
335 if (NtGdiCombineRgn(Window
->UpdateRegion
, Window
->UpdateRegion
,
336 hRgn
, RGN_OR
) == NULLREGION
)
338 NtGdiDeleteObject(Window
->UpdateRegion
);
339 Window
->UpdateRegion
= NULL
;
342 if (Flags
& RDW_FRAME
)
343 Window
->Flags
|= WINDOWOBJECT_NEED_NCPAINT
;
344 if (Flags
& RDW_ERASE
)
345 Window
->Flags
|= WINDOWOBJECT_NEED_ERASEBKGND
;
350 if (Flags
& RDW_VALIDATE
&& RgnType
!= NULLREGION
)
352 if (Window
->UpdateRegion
!= NULL
)
354 if (NtGdiCombineRgn(Window
->UpdateRegion
, Window
->UpdateRegion
,
355 hRgn
, RGN_DIFF
) == NULLREGION
)
357 NtGdiDeleteObject(Window
->UpdateRegion
);
358 Window
->UpdateRegion
= NULL
;
362 if (Window
->UpdateRegion
== NULL
)
363 Window
->Flags
&= ~WINDOWOBJECT_NEED_ERASEBKGND
;
364 if (Flags
& RDW_NOFRAME
)
365 Window
->Flags
&= ~WINDOWOBJECT_NEED_NCPAINT
;
366 if (Flags
& RDW_NOERASE
)
367 Window
->Flags
&= ~WINDOWOBJECT_NEED_ERASEBKGND
;
370 if (Flags
& RDW_INTERNALPAINT
)
372 Window
->Flags
|= WINDOWOBJECT_NEED_INTERNALPAINT
;
375 if (Flags
& RDW_NOINTERNALPAINT
)
377 Window
->Flags
&= ~WINDOWOBJECT_NEED_INTERNALPAINT
;
381 * Validate parent covered by region
386 IntValidateParent(Window
);
390 * Process children if needed
393 if (!(Flags
& RDW_NOCHILDREN
) && !(Window
->Style
& WS_MINIMIZE
) &&
394 ((Flags
& RDW_ALLCHILDREN
) || !(Window
->Style
& WS_CLIPCHILDREN
)))
397 PWINDOW_OBJECT Child
;
399 if ((List
= IntWinListChildren(Window
)))
401 for (phWnd
= List
; *phWnd
; ++phWnd
)
403 Child
= IntGetWindowObject(*phWnd
);
404 if ((Child
->Style
& (WS_VISIBLE
| WS_MINIMIZE
)) == WS_VISIBLE
)
407 * Recursive call to update children UpdateRegion
409 HRGN hRgnTemp
= NtGdiCreateRectRgn(0, 0, 0, 0);
410 NtGdiCombineRgn(hRgnTemp
, hRgn
, 0, RGN_COPY
);
411 NtGdiOffsetRgn(hRgnTemp
,
412 Window
->WindowRect
.left
- Child
->WindowRect
.left
,
413 Window
->WindowRect
.top
- Child
->WindowRect
.top
);
414 IntInvalidateWindows(Child
, hRgnTemp
, Flags
, FALSE
);
417 * Update our UpdateRegion depending on children
419 NtGdiCombineRgn(hRgnTemp
, Child
->UpdateRegion
, 0, RGN_COPY
);
420 NtGdiOffsetRgn(hRgnTemp
,
421 Child
->WindowRect
.left
- Window
->WindowRect
.left
,
422 Child
->WindowRect
.top
- Window
->WindowRect
.top
);
423 hRgnWindow
= UnsafeIntCreateRectRgnIndirect(&Window
->ClientRect
);
424 NtGdiOffsetRgn(hRgnWindow
,
425 -Window
->WindowRect
.left
,
426 -Window
->WindowRect
.top
);
427 NtGdiCombineRgn(hRgnTemp
, hRgnTemp
, hRgnWindow
, RGN_AND
);
428 if (NtGdiCombineRgn(Window
->UpdateRegion
, Window
->UpdateRegion
,
429 hRgnTemp
, RGN_DIFF
) == NULLREGION
)
431 NtGdiDeleteObject(Window
->UpdateRegion
);
432 Window
->UpdateRegion
= NULL
;
434 NtGdiDeleteObject(hRgnTemp
);
436 IntReleaseWindowObject(Child
);
443 * Fake post paint messages to window message queue if needed
446 #ifndef DESKTOP_IN_CSRSS
447 if (Window
->MessageQueue
)
450 HasPaintMessage
= Window
->UpdateRegion
!= NULL
||
451 Window
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
;
452 HasNCPaintMessage
= Window
->Flags
& WINDOWOBJECT_NEED_NCPAINT
;
454 if (HasPaintMessage
!= HadPaintMessage
)
457 MsqDecPaintCountQueue(Window
->MessageQueue
);
459 MsqIncPaintCountQueue(Window
->MessageQueue
);
462 if (HasNCPaintMessage
!= HadNCPaintMessage
)
464 if (HadNCPaintMessage
)
465 MsqDecPaintCountQueue(Window
->MessageQueue
);
467 MsqIncPaintCountQueue(Window
->MessageQueue
);
469 #ifndef DESKTOP_IN_CSRSS
475 * IntIsWindowDrawable
478 * Window is drawable when it is visible, all parents are not
479 * minimized, and it is itself not minimized.
483 IntIsWindowDrawable(PWINDOW_OBJECT Window
)
485 for (; Window
; Window
= Window
->Parent
)
487 if ((Window
->Style
& (WS_VISIBLE
| WS_MINIMIZE
)) != WS_VISIBLE
)
497 * Internal version of NtUserRedrawWindow that takes WINDOW_OBJECT as
502 IntRedrawWindow(PWINDOW_OBJECT Window
, const RECT
* UpdateRect
, HRGN UpdateRgn
,
509 * Validation of passed parameters.
512 if (!IntIsWindowDrawable(Window
) ||
513 (Flags
& (RDW_VALIDATE
| RDW_INVALIDATE
)) ==
514 (RDW_VALIDATE
| RDW_INVALIDATE
))
521 * Transform the parameters UpdateRgn and UpdateRect into
522 * a region hRgn specified in window coordinates.
525 if (Flags
& (RDW_INVALIDATE
| RDW_VALIDATE
))
527 if (UpdateRgn
!= NULL
)
529 hRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
530 NtGdiCombineRgn(hRgn
, UpdateRgn
, NULL
, RGN_COPY
);
532 Window
->ClientRect
.left
- Window
->WindowRect
.left
,
533 Window
->ClientRect
.top
- Window
->WindowRect
.top
);
535 if (UpdateRect
!= NULL
)
537 hRgn
= UnsafeIntCreateRectRgnIndirect((RECT
*)UpdateRect
);
539 Window
->ClientRect
.left
- Window
->WindowRect
.left
,
540 Window
->ClientRect
.top
- Window
->WindowRect
.top
);
542 if ((Flags
& (RDW_INVALIDATE
| RDW_FRAME
)) == (RDW_INVALIDATE
| RDW_FRAME
) ||
543 (Flags
& (RDW_VALIDATE
| RDW_NOFRAME
)) == (RDW_VALIDATE
| RDW_NOFRAME
))
545 hRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->WindowRect
);
547 -Window
->WindowRect
.left
,
548 -Window
->WindowRect
.top
);
552 hRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->ClientRect
);
554 -Window
->WindowRect
.left
,
555 -Window
->WindowRect
.top
);
561 * Adjust the window update region depending on hRgn and flags.
564 if (Flags
& (RDW_INVALIDATE
| RDW_VALIDATE
| RDW_INTERNALPAINT
| RDW_NOINTERNALPAINT
))
566 IntInvalidateWindows(Window
, hRgn
, Flags
, TRUE
);
568 if (Window
->UpdateRegion
!= NULL
&& Flags
& RDW_ERASENOW
)
570 /* Validate parent covered by region. */
571 IntValidateParent(Window
);
576 * Repaint and erase windows if needed.
579 if (Flags
& (RDW_ERASENOW
| RDW_UPDATENOW
))
581 IntPaintWindows(Window
, Flags
);
589 NtGdiDeleteObject(hRgn
);
595 IntFindWindowToRepaint(HWND hWnd
, PW32THREAD Thread
)
597 PWINDOW_OBJECT Window
;
598 PWINDOW_OBJECT Child
;
599 HWND hFoundWnd
= NULL
;
603 PLIST_ENTRY CurrentEntry
;
605 ExAcquireFastMutex(&Thread
->WindowListLock
);
607 for (CurrentEntry
= Thread
->WindowListHead
.Flink
;
608 CurrentEntry
!= &Thread
->WindowListHead
;
609 CurrentEntry
= CurrentEntry
->Flink
)
611 Window
= CONTAINING_RECORD(CurrentEntry
, WINDOW_OBJECT
, ThreadListEntry
);
612 if (Window
->Parent
!= NULL
&& !IntIsDesktopWindow(Window
->Parent
))
616 if (Window
->Style
& WS_VISIBLE
)
618 hFoundWnd
= IntFindWindowToRepaint(Window
->Self
, Thread
);
619 if (hFoundWnd
!= NULL
)
621 ExReleaseFastMutex(&Thread
->WindowListLock
);
627 ExReleaseFastMutex(&Thread
->WindowListLock
);
632 Window
= IntGetWindowObject(hWnd
);
636 if (Window
->UpdateRegion
!= NULL
||
637 Window
->Flags
& (WINDOWOBJECT_NEED_INTERNALPAINT
| WINDOWOBJECT_NEED_NCPAINT
))
639 IntReleaseWindowObject(Window
);
643 ExAcquireFastMutex(&Window
->ChildrenListLock
);
645 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
647 if (Child
->Style
& WS_VISIBLE
&&
648 (Child
->UpdateRegion
!= NULL
||
649 Child
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
||
650 Child
->Flags
& WINDOWOBJECT_NEED_NCPAINT
))
652 hFoundWnd
= Child
->Self
;
657 if (hFoundWnd
== NULL
)
659 for (Child
= Window
->FirstChild
; Child
; Child
= Child
->NextSibling
)
661 if (Child
->Style
& WS_VISIBLE
)
663 hFoundWnd
= IntFindWindowToRepaint(Child
->Self
, Thread
);
664 if (hFoundWnd
!= NULL
)
670 ExReleaseFastMutex(&Window
->ChildrenListLock
);
671 IntReleaseWindowObject(Window
);
678 IntGetPaintMessage(PWINDOW_OBJECT Wnd
, PW32THREAD Thread
, MSG
*Message
,
681 PWINDOW_OBJECT Window
;
682 PUSER_MESSAGE_QUEUE MessageQueue
= (PUSER_MESSAGE_QUEUE
)Thread
->MessageQueue
;
684 if (!MessageQueue
->PaintPosted
)
688 Message
->hwnd
= IntFindWindowToRepaint(Wnd
->Self
, PsGetWin32Thread());
690 Message
->hwnd
= IntFindWindowToRepaint(NULL
, PsGetWin32Thread());
692 if (Message
->hwnd
== NULL
)
694 DPRINT1("PAINTING BUG: Thread marked as containing dirty windows, but no dirty windows found!\n");
698 Window
= IntGetWindowObject(Message
->hwnd
);
701 if (Window
->Flags
& WINDOWOBJECT_NEED_NCPAINT
)
703 Message
->message
= WM_NCPAINT
;
704 Message
->wParam
= (WPARAM
)IntGetNCUpdateRegion(Window
, Remove
);
708 Message
->message
= WM_PAINT
;
709 Message
->wParam
= Message
->lParam
= 0;
710 if (Remove
&& Window
->Flags
& WINDOWOBJECT_NEED_INTERNALPAINT
)
712 Window
->Flags
&= ~WINDOWOBJECT_NEED_INTERNALPAINT
;
713 if (Window
->UpdateRegion
== NULL
)
715 MsqDecPaintCountQueue(Window
->MessageQueue
);
720 IntReleaseWindowObject(Window
);
727 /* PUBLIC FUNCTIONS ***********************************************************/
737 NtUserBeginPaint(HWND hWnd
, PAINTSTRUCT
* lPs
)
739 PWINDOW_OBJECT Window
;
744 if (!(Window
= IntGetWindowObject(hWnd
)))
746 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
750 NtUserHideCaret(hWnd
);
752 DcxFlags
= DCX_INTERSECTUPDATE
| DCX_WINDOWPAINT
| DCX_USESTYLE
;
753 if (IntGetClassLong(Window
, GCL_STYLE
, FALSE
) & CS_PARENTDC
)
755 /* FIXME: Is this correct? */
756 /* Don't clip the output to the update region for CS_PARENTDC window */
757 DcxFlags
&= ~DCX_INTERSECTUPDATE
;
760 lPs
->hdc
= NtUserGetDCEx(hWnd
, 0, DcxFlags
);
767 /* IntRedrawWindow(Window, NULL, 0, RDW_NOINTERNALPAINT | RDW_VALIDATE | RDW_NOCHILDREN);*/
768 if (Window
->UpdateRegion
!= NULL
)
770 MsqDecPaintCountQueue(Window
->MessageQueue
);
771 IntValidateParent(Window
);
772 NtGdiDeleteObject(Window
->UpdateRegion
);
773 Window
->UpdateRegion
= NULL
;
776 IntGetClientRect(Window
, &ClientRect
);
777 NtGdiGetClipBox(lPs
->hdc
, &ClipRect
);
778 NtGdiLPtoDP(lPs
->hdc
, (LPPOINT
)&ClipRect
, 2);
779 NtGdiIntersectRect(&lPs
->rcPaint
, &ClientRect
, &ClipRect
);
780 NtGdiDPtoLP(lPs
->hdc
, (LPPOINT
)&lPs
->rcPaint
, 2);
782 if (Window
->Flags
& WINDOWOBJECT_NEED_ERASEBKGND
)
784 Window
->Flags
&= ~WINDOWOBJECT_NEED_ERASEBKGND
;
785 lPs
->fErase
= !NtUserSendMessage(hWnd
, WM_ERASEBKGND
, (WPARAM
)lPs
->hdc
, 0);
792 IntReleaseWindowObject(Window
);
805 NtUserEndPaint(HWND hWnd
, CONST PAINTSTRUCT
* lPs
)
807 NtUserReleaseDC(hWnd
, lPs
->hdc
);
808 NtUserShowCaret(hWnd
);
814 * NtUserInvalidateRect
821 NtUserInvalidateRect(HWND hWnd
, CONST RECT
*Rect
, BOOL Erase
)
823 return NtUserRedrawWindow(hWnd
, Rect
, 0, RDW_INVALIDATE
| (Erase
? RDW_ERASE
: 0));
827 * NtUserInvalidateRgn
834 NtUserInvalidateRgn(HWND hWnd
, HRGN Rgn
, BOOL Erase
)
836 return NtUserRedrawWindow(hWnd
, NULL
, Rgn
, RDW_INVALIDATE
| (Erase
? RDW_ERASE
: 0));
847 NtUserValidateRgn(HWND hWnd
, HRGN hRgn
)
849 return NtUserRedrawWindow(hWnd
, NULL
, hRgn
, RDW_VALIDATE
| RDW_NOCHILDREN
);
860 NtUserUpdateWindow(HWND hWnd
)
862 return NtUserRedrawWindow(hWnd
, NULL
, 0, RDW_UPDATENOW
| RDW_ALLCHILDREN
);
873 NtUserGetUpdateRgn(HWND hWnd
, HRGN hRgn
, BOOL bErase
)
875 PWINDOW_OBJECT Window
;
878 if (!(Window
= IntGetWindowObject(hWnd
)))
880 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
884 if (Window
->UpdateRegion
== NULL
)
886 RegionType
= (NtGdiSetRectRgn(hRgn
, 0, 0, 0, 0) ? NULLREGION
: ERROR
);
890 RegionType
= NtGdiCombineRgn(hRgn
, Window
->UpdateRegion
, hRgn
, RGN_COPY
);
893 Window
->WindowRect
.left
- Window
->ClientRect
.left
,
894 Window
->WindowRect
.top
- Window
->ClientRect
.top
);
897 IntReleaseWindowObject(Window
);
899 if (bErase
&& RegionType
!= NULLREGION
&& RegionType
!= ERROR
)
901 NtUserRedrawWindow(hWnd
, NULL
, NULL
, RDW_ERASENOW
| RDW_NOCHILDREN
);
908 * NtUserGetUpdateRect
915 NtUserGetUpdateRect(HWND hWnd
, LPRECT lpRect
, BOOL fErase
)
917 HRGN hRgn
= NtGdiCreateRectRgn(0, 0, 0, 0);
921 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
925 NtUserGetUpdateRgn(hWnd
, hRgn
, fErase
);
926 NtGdiGetRgnBox(hRgn
, lpRect
);
928 return lpRect
->left
< lpRect
->right
&& lpRect
->top
< lpRect
->bottom
;
939 NtUserRedrawWindow(HWND hWnd
, CONST RECT
*lprcUpdate
, HRGN hrgnUpdate
,
946 if (!(Wnd
= IntGetWindowObject(hWnd
? hWnd
: IntGetDesktopWindow())))
948 SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE
);
952 if (lprcUpdate
!= NULL
)
954 Status
= MmCopyFromCaller(&SafeUpdateRect
, (PRECT
)lprcUpdate
,
957 if (!NT_SUCCESS(Status
))
959 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
964 Status
= IntRedrawWindow(Wnd
, NULL
== lprcUpdate
? NULL
: &SafeUpdateRect
,
967 if (!NT_SUCCESS(Status
))
969 /* IntRedrawWindow fails only in case that flags are invalid */
970 SetLastWin32Error(ERROR_INVALID_PARAMETER
);