2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/ntuser/windc.c
5 * PURPOSE: Window DC management
6 * COPYRIGHT: Copyright 2007 ReactOS
10 /* INCLUDES ******************************************************************/
17 /* GLOBALS *******************************************************************/
19 /* NOTE - I think we should store this per window station (including gdi objects) */
21 static PDCE FirstDce
= NULL
;
22 //static INT DCECount = 0; // Count of DCE in system.
24 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
25 DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
27 /* FUNCTIONS *****************************************************************/
30 // This should be moved to dc.c or dcutil.c.
33 DceCreateDisplayDC(VOID
)
36 UNICODE_STRING DriverName
;
37 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
38 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
40 // If NULL, first time through! Build the default window dc!
42 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
43 { // This is a cheesy way to do this.
44 PDC dc
= DC_LockDc ( hDC
);
45 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
46 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
47 defaultDCstate
->pdcattr
= &defaultDCstate
->dcattr
;
48 DC_vCopyState(dc
, defaultDCstate
);
56 DceGetVisRgn(PWINDOW_OBJECT Window
, ULONG Flags
, HWND hWndChild
, ULONG CFlags
)
60 VisRgn
= VIS_ComputeVisibleRegion( Window
,
61 0 == (Flags
& DCX_WINDOW
),
62 0 != (Flags
& DCX_CLIPCHILDREN
),
63 0 != (Flags
& DCX_CLIPSIBLINGS
));
66 VisRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
73 DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL
, DCE_TYPE Type
)
78 if (Window
) Wnd
= Window
->Wnd
;
80 pDce
= ExAllocatePoolWithTag(PagedPool
, sizeof(DCE
), TAG_PDCE
);
84 pDce
->hDC
= DceCreateDisplayDC();
87 ExFreePoolWithTag(pDce
, TAG_PDCE
);
91 pDce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
94 pDce
->hrgnClip
= NULL
;
95 pDce
->hrgnClipPublic
= NULL
;
96 pDce
->hrgnSavedVis
= NULL
;
97 pDce
->ptiOwner
= NULL
;
98 pDce
->ppiOwner
= NULL
;
100 KeEnterCriticalRegion();
101 if (FirstDce
== NULL
)
104 InitializeListHead(&FirstDce
->List
);
107 InsertTailList(&FirstDce
->List
, &pDce
->List
);
108 KeLeaveCriticalRegion();
110 DCU_SetDcUndeletable(pDce
->hDC
);
112 if (Type
== DCE_WINDOW_DC
|| Type
== DCE_CLASS_DC
) //Window DCE have ownership.
114 pDce
->ptiOwner
= GetW32ThreadInfo();
115 pDce
->ppiOwner
= pDce
->ptiOwner
->ppi
;
119 DPRINT("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce
->hDC
);
120 IntGdiSetDCOwnerEx( pDce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
);
123 if (Type
== DCE_CACHE_DC
)
125 pDce
->DCXFlags
= DCX_CACHE
| DCX_DCEEMPTY
;
129 pDce
->DCXFlags
= DCX_DCEBUSY
;
132 if (Type
== DCE_WINDOW_DC
)
134 if (Wnd
->style
& WS_CLIPCHILDREN
) pDce
->DCXFlags
|= DCX_CLIPCHILDREN
;
135 if (Wnd
->style
& WS_CLIPSIBLINGS
) pDce
->DCXFlags
|= DCX_CLIPSIBLINGS
;
143 DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL
, HDC hDC
, ULONG Flags
,
147 DC
*dc
= DC_LockDc(hDC
);
159 if (Flags
& DCX_WINDOW
)
161 dc
->ptlDCOrig
.x
= Wnd
->rcWindow
.left
;
162 dc
->ptlDCOrig
.y
= Wnd
->rcWindow
.top
;
166 dc
->ptlDCOrig
.x
= Wnd
->rcClient
.left
;
167 dc
->ptlDCOrig
.y
= Wnd
->rcClient
.top
;
175 DceDeleteClipRgn(DCE
* Dce
)
177 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
179 if (Dce
->DCXFlags
& DCX_KEEPCLIPRGN
)
181 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
183 else if (Dce
->hrgnClip
!= NULL
)
185 REGION_FreeRgnByHandle(Dce
->hrgnClip
);
188 Dce
->hrgnClip
= NULL
;
190 /* make it dirty so that the vis rgn gets recomputed next time */
191 Dce
->DCXFlags
|= DCX_DCEDIRTY
;
195 DceReleaseDC(DCE
* dce
, BOOL EndPaint
)
197 if (DCX_DCEBUSY
!= (dce
->DCXFlags
& (DCX_DCEEMPTY
| DCX_DCEBUSY
)))
202 /* restore previous visible region */
204 if ((dce
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) &&
205 ((dce
->DCXFlags
& DCX_CACHE
) || EndPaint
))
207 DceDeleteClipRgn(dce
);
210 if (dce
->DCXFlags
& DCX_CACHE
)
212 if (!(dce
->DCXFlags
& DCX_NORESETATTRS
))
214 /* make the DC clean so that SetDCState doesn't try to update the vis rgn */
215 IntGdiSetHookFlags(dce
->hDC
, DCHF_VALIDATEVISRGN
);
218 if (!IntGdiCleanDC(dce
->hDC
)) return 0;
220 if (dce
->DCXFlags
& DCX_DCEDIRTY
)
222 /* don't keep around invalidated entries
223 * because SetDCState() disables hVisRgn updates
224 * by removing dirty bit. */
225 dce
->hwndCurrent
= 0;
226 dce
->DCXFlags
&= DCX_CACHE
;
227 dce
->DCXFlags
|= DCX_DCEEMPTY
;
230 dce
->DCXFlags
&= ~DCX_DCEBUSY
;
231 DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce
->hDC
);
232 if (!IntGdiSetDCOwnerEx( dce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
))
234 dce
->ptiOwner
= NULL
; // Reset ownership.
235 dce
->ppiOwner
= NULL
;
237 return 1; // Released!
241 DceUpdateVisRgn(DCE
*Dce
, PWINDOW_OBJECT Window
, ULONG Flags
)
243 HANDLE hRgnVisible
= NULL
;
245 PWINDOW_OBJECT DesktopWindow
;
247 if (Flags
& DCX_PARENTCLIP
)
249 PWINDOW_OBJECT Parent
;
252 Parent
= Window
->spwndParent
;
259 ParentWnd
= Parent
->Wnd
;
261 if (ParentWnd
->style
& WS_CLIPSIBLINGS
)
263 DcxFlags
= DCX_CLIPSIBLINGS
|
264 (Flags
& ~(DCX_CLIPCHILDREN
| DCX_WINDOW
));
268 DcxFlags
= Flags
& ~(DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
| DCX_WINDOW
);
270 hRgnVisible
= DceGetVisRgn(Parent
, DcxFlags
, Window
->hSelf
, Flags
);
272 else if (Window
== NULL
)
274 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
275 if (NULL
!= DesktopWindow
)
277 hRgnVisible
= IntSysCreateRectRgnIndirect(&DesktopWindow
->Wnd
->rcWindow
);
286 hRgnVisible
= DceGetVisRgn(Window
, Flags
, 0, 0);
290 if (Flags
& DCX_INTERSECTRGN
)
292 if(Dce
->hrgnClip
!= NULL
)
294 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hrgnClip
, RGN_AND
);
298 if(hRgnVisible
!= NULL
)
300 REGION_FreeRgnByHandle(hRgnVisible
);
302 hRgnVisible
= IntSysCreateRectRgn(0, 0, 0, 0);
306 if (Flags
& DCX_EXCLUDERGN
&& Dce
->hrgnClip
!= NULL
)
308 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hrgnClip
, RGN_DIFF
);
311 Dce
->DCXFlags
&= ~DCX_DCEDIRTY
;
312 GdiSelectVisRgn(Dce
->hDC
, hRgnVisible
);
316 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
319 if (hRgnVisible
!= NULL
)
321 REGION_FreeRgnByHandle(hRgnVisible
);
326 UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
328 PWINDOW_OBJECT Parent
;
331 BOOL UpdateVisRgn
= TRUE
;
332 BOOL UpdateClipOrigin
= FALSE
;
338 Flags
&= ~DCX_USESTYLE
;
344 if (Flags
& (DCX_WINDOW
| DCX_PARENTCLIP
)) Flags
|= DCX_CACHE
;
346 // When GetDC is called with hWnd nz, DCX_CACHE & _WINDOW are clear w _USESTYLE set.
347 if (Flags
& DCX_USESTYLE
)
349 Flags
&= ~(DCX_CLIPCHILDREN
| DCX_CLIPSIBLINGS
| DCX_PARENTCLIP
);
350 if (!(Flags
& DCX_WINDOW
)) // not window rectangle
352 if (Wnd
->pcls
->style
& CS_PARENTDC
)
354 Flags
|= DCX_PARENTCLIP
;
357 if (!(Flags
& DCX_CACHE
) && // Not on the cheap wine list.
358 !(Wnd
->pcls
->style
& CS_OWNDC
) )
360 if (!(Wnd
->pcls
->style
& CS_CLASSDC
))
361 // The window is not POWNED or has any CLASS, so we are looking for cheap wine.
365 if (Wnd
->pcls
->pdce
) hDC
= ((PDCE
)Wnd
->pcls
->pdce
)->hDC
;
366 DPRINT("We have CLASS!!\n");
369 /* else // For Testing!
371 DPRINT1("We have POWNER!!\n");
372 if (Window->Dce) DPRINT1("We have POWNER with DCE!!\n");
375 if (Wnd
->style
& WS_CLIPSIBLINGS
)
377 Flags
|= DCX_CLIPSIBLINGS
;
380 if (Wnd
->style
& WS_CLIPCHILDREN
&&
381 !(Wnd
->style
& WS_MINIMIZE
))
383 Flags
|= DCX_CLIPCHILDREN
;
388 if (Wnd
->style
& WS_CLIPSIBLINGS
) Flags
|= DCX_CLIPSIBLINGS
;
393 if (Flags
& DCX_WINDOW
) Flags
&= ~DCX_CLIPCHILDREN
;
395 if (Flags
& DCX_NOCLIPCHILDREN
)
398 Flags
&= ~(DCX_PARENTCLIP
| DCX_CLIPCHILDREN
);
401 Parent
= (Window
? Window
->spwndParent
: NULL
);
403 if (NULL
== Window
|| !(Wnd
->style
& WS_CHILD
) || NULL
== Parent
)
405 Flags
&= ~DCX_PARENTCLIP
;
406 Flags
|= DCX_CLIPSIBLINGS
;
409 /* it seems parent clip is ignored when clipping siblings or children */
410 if (Flags
& (DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
)) Flags
&= ~DCX_PARENTCLIP
;
412 if (Flags
& DCX_PARENTCLIP
)
414 if ((Wnd
->style
& WS_VISIBLE
) &&
415 (Parent
->Wnd
->style
& WS_VISIBLE
))
417 Flags
&= ~DCX_CLIPCHILDREN
;
418 if (Parent
->Wnd
->style
& WS_CLIPSIBLINGS
)
420 Flags
|= DCX_CLIPSIBLINGS
;
425 // Window nz, check to see if we still own this or it is just cheap wine tonight.
426 if (!(Flags
& DCX_CACHE
))
428 if ( Wnd
->head
.pti
!= GetW32ThreadInfo())
429 Flags
|= DCX_CACHE
; // Ah~ Not Powned! Forced to be cheap~
432 DcxFlags
= Flags
& DCX_CACHECOMPAREMASK
;
434 if (Flags
& DCX_CACHE
)
435 { // Scan the cheap wine list for our match.
436 DCE
* DceEmpty
= NULL
;
437 DCE
* DceUnused
= NULL
;
438 KeEnterCriticalRegion();
442 // The reason for this you may ask?
443 // Well, it seems ReactOS calls GetDC with out first creating a desktop DC window!
444 // Need to test for null here. Not sure if this is a bug or a feature.
445 // First time use hax, need to use DceAllocDCE during window display init.
448 // The way I understand this, you can have more than one DC per window.
449 // Only one Owned if one was requested and saved and one Cached.
451 if ((Dce
->DCXFlags
& (DCX_CACHE
| DCX_DCEBUSY
)) == DCX_CACHE
)
454 if (Dce
->DCXFlags
& DCX_DCEEMPTY
)
458 else if (Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
) &&
459 ((Dce
->DCXFlags
& DCX_CACHECOMPAREMASK
) == DcxFlags
))
462 UpdateVisRgn
= FALSE
;
464 UpdateClipOrigin
= TRUE
;
468 Dce
= (PDCE
)Dce
->List
.Flink
;
469 } while (Dce
!= FirstDce
);
470 KeLeaveCriticalRegion();
472 Dce
= (DceEmpty
== NULL
) ? DceUnused
: DceEmpty
;
476 Dce
= DceAllocDCE(NULL
, DCE_CACHE_DC
);
478 if (!Dce
) return NULL
;
480 Dce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
482 else // If we are here, we are POWNED or having CLASS.
484 KeEnterCriticalRegion();
487 { // Check for Window handle than HDC match for CLASS.
488 if ((Dce
->hwndCurrent
== Window
->hSelf
) || (Dce
->hDC
== hDC
)) break;
489 Dce
= (PDCE
)Dce
->List
.Flink
;
490 } while (Dce
!= FirstDce
);
491 KeLeaveCriticalRegion();
493 DPRINT("DCX:Flags -> %x:%x\n",Dce
->DCXFlags
& DCX_CACHE
, Flags
& DCX_CACHE
);
495 if (Dce
->hwndCurrent
== Window
->hSelf
)
497 DPRINT("Owned DCE!\n");
498 UpdateVisRgn
= FALSE
; /* updated automatically, via DCHook() */
502 DPRINT("Owned/Class DCE\n");
503 /* we should free dce->clip_rgn here, but Windows apparently doesn't */
504 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
505 Dce
->hrgnClip
= NULL
;
513 // First time use hax, need to use DceAllocDCE during window display init.
519 if (!GDIOBJ_ValidateHandle(Dce
->hDC
, GDI_OBJECT_TYPE_DC
))
521 DPRINT1("FIXME: Got DCE with invalid hDC! 0x%x\n", Dce
->hDC
);
522 Dce
->hDC
= DceCreateDisplayDC();
523 /* FIXME: Handle error */
526 if (!(Flags
& (DCX_EXCLUDERGN
| DCX_INTERSECTRGN
)) && ClipRegion
)
528 if (!(Flags
& DCX_KEEPCLIPRGN
))
529 REGION_FreeRgnByHandle(ClipRegion
);
534 if (NULL
!= Dce
->hrgnClip
)
536 DceDeleteClipRgn(Dce
);
540 Dce
->DCXFlags
= Flags
| DCX_DCEBUSY
;
542 if (0 != (Flags
& DCX_INTERSECTUPDATE
) && NULL
== ClipRegion
)
544 Flags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
545 Dce
->DCXFlags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
546 ClipRegion
= Window
->hrgnUpdate
;
549 if (ClipRegion
== (HRGN
) 1)
551 if (!(Flags
& DCX_WINDOW
))
553 Dce
->hrgnClip
= IntSysCreateRectRgnIndirect(&Window
->Wnd
->rcClient
);
557 Dce
->hrgnClip
= IntSysCreateRectRgnIndirect(&Window
->Wnd
->rcWindow
);
559 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
561 else if (ClipRegion
!= NULL
)
563 Dce
->hrgnClip
= ClipRegion
;
566 DceSetDrawable(Window
, Dce
->hDC
, Flags
, UpdateClipOrigin
);
570 DceUpdateVisRgn(Dce
, Window
, Flags
);
573 if (Dce
->DCXFlags
& DCX_CACHE
)
575 DPRINT("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %x\n", Dce
->hDC
);
576 // Need to set ownership so Sync dcattr will work.
577 IntGdiSetDCOwnerEx( Dce
->hDC
, GDI_OBJ_HMGR_POWNED
, FALSE
);
578 Dce
->ptiOwner
= GetW32ThreadInfo(); // Set the temp owning
579 Dce
->ppiOwner
= Dce
->ptiOwner
->ppi
;
584 /***********************************************************************
588 DceFreeDCE(PDCE pdce
, BOOLEAN Force
)
593 if (NULL
== pdce
) return NULL
;
595 ret
= (PDCE
) pdce
->List
.Flink
;
598 SetDCHook(pdce
->hDC
, NULL
, 0L);
601 if (Force
&& !GDIOBJ_OwnedByCurrentProcess(pdce
->hDC
))
603 DPRINT("Change ownership for DCE! -> %x\n" , pdce
);
604 // Note: Windows sets W32PF_OWNDCCLEANUP and moves on.
605 if (!IsObjectDead((HGDIOBJ
) pdce
->hDC
))
607 DC_SetOwnership( pdce
->hDC
, PsGetCurrentProcess());
611 DPRINT1("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce
->hDC
);
616 if (!Hit
) IntGdiDeleteDC(pdce
->hDC
, TRUE
);
618 if (pdce
->hrgnClip
&& ! (pdce
->DCXFlags
& DCX_KEEPCLIPRGN
))
620 REGION_FreeRgnByHandle(pdce
->hrgnClip
);
623 RemoveEntryList(&pdce
->List
);
625 if (IsListEmpty(&pdce
->List
))
627 DPRINT1("List is Empty! DCE! -> %x\n" , pdce
);
632 ExFreePoolWithTag(pdce
, TAG_PDCE
);
638 DceFreeClassDCE(HDC hDC
)
640 PDCE pDCE
= FirstDce
;
641 KeEnterCriticalRegion();
645 if (pDCE
->hDC
== hDC
)
647 pDCE
= DceFreeDCE(pDCE
, FALSE
);
651 pDCE
= (PDCE
)pDCE
->List
.Flink
;
652 } while (pDCE
!= FirstDce
);
653 KeLeaveCriticalRegion();
659 PDCE pDCE
= FirstDce
;
660 KeEnterCriticalRegion();
664 pDCE
= DceFreeDCE(pDCE
, TRUE
);
666 } while (pDCE
!= FirstDce
);
667 KeLeaveCriticalRegion();
672 DceResetActiveDCEs(PWINDOW_OBJECT Window
)
676 PWINDOW_OBJECT CurrentWindow
;
685 if(!pDCE
) return; // Another null test!
689 if (0 == (pDCE
->DCXFlags
& DCX_DCEEMPTY
))
691 if (Window
->hSelf
== pDCE
->hwndCurrent
)
693 CurrentWindow
= Window
;
697 CurrentWindow
= UserGetWindowObject(pDCE
->hwndCurrent
);
698 if (NULL
== CurrentWindow
)
700 pDCE
= (PDCE
) pDCE
->List
.Flink
;
705 if (!GDIOBJ_ValidateHandle(pDCE
->hDC
, GDI_OBJECT_TYPE_DC
) ||
706 (dc
= DC_LockDc(pDCE
->hDC
)) == NULL
)
708 pDCE
= (PDCE
) pDCE
->List
.Flink
;
711 if (Window
== CurrentWindow
|| IntIsChildWindow(Window
, CurrentWindow
))
713 if (pDCE
->DCXFlags
& DCX_WINDOW
)
715 DeltaX
= CurrentWindow
->Wnd
->rcWindow
.left
- dc
->ptlDCOrig
.x
;
716 DeltaY
= CurrentWindow
->Wnd
->rcWindow
.top
- dc
->ptlDCOrig
.y
;
717 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->rcWindow
.left
;
718 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->rcWindow
.top
;
722 DeltaX
= CurrentWindow
->Wnd
->rcClient
.left
- dc
->ptlDCOrig
.x
;
723 DeltaY
= CurrentWindow
->Wnd
->rcClient
.top
- dc
->ptlDCOrig
.y
;
724 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->rcClient
.left
;
725 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->rcClient
.top
;
727 if (NULL
!= dc
->rosdc
.hClipRgn
)
729 int FASTCALL
CLIPPING_UpdateGCRegion(DC
* Dc
);
730 NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
, DeltaX
, DeltaY
);
731 CLIPPING_UpdateGCRegion(dc
);
733 if (NULL
!= pDCE
->hrgnClip
)
735 NtGdiOffsetRgn(pDCE
->hrgnClip
, DeltaX
, DeltaY
);
740 DceUpdateVisRgn(pDCE
, CurrentWindow
, pDCE
->DCXFlags
);
742 if (Window
->hSelf
!= pDCE
->hwndCurrent
)
744 // IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
745 // UserDerefObject(CurrentWindow);
748 pDCE
=(PDCE
) pDCE
->List
.Flink
;
749 } while (pDCE
!= FirstDce
);
753 IntWindowFromDC(HDC hDc
)
757 KeEnterCriticalRegion();
763 Ret
= Dce
->hwndCurrent
;
766 Dce
= (PDCE
)Dce
->List
.Flink
;
767 } while (Dce
!= FirstDce
);
768 KeLeaveCriticalRegion();
773 UserReleaseDC(PWINDOW_OBJECT Window
, HDC hDc
, BOOL EndPaint
)
779 DPRINT("%p %p\n", Window
, hDc
);
781 KeEnterCriticalRegion();
791 dce
= (PDCE
) dce
->List
.Flink
;
793 while (dce
!= FirstDce
);
794 KeLeaveCriticalRegion();
796 if ( Hit
&& (dce
->DCXFlags
& DCX_DCEBUSY
))
798 nRet
= DceReleaseDC(dce
, EndPaint
);
805 UserGetWindowDC(PWINDOW_OBJECT Wnd
)
807 return UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
811 UserGethWnd( HDC hdc
, PWNDOBJ
*pwndo
)
817 hWnd
= IntWindowFromDC(hdc
);
819 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
821 pWndgdi
= (WNDGDI
*)IntGetProp(Wnd
, AtomWndObj
);
823 if ( pWndgdi
&& pWndgdi
->Hwnd
== hWnd
)
825 if (pwndo
) *pwndo
= (PWNDOBJ
)pWndgdi
;
832 NtUserGetDCEx(HWND hWnd OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
834 PWINDOW_OBJECT Wnd
=NULL
;
837 DPRINT("Enter NtUserGetDCEx\n");
838 UserEnterExclusive();
840 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
844 RETURN( UserGetDCEx(Wnd
, ClipRegion
, Flags
));
847 DPRINT("Leave NtUserGetDCEx, ret=%i\n",_ret_
);
855 * The NtUserGetWindowDC function retrieves the device context (DC) for the
856 * entire window, including title bar, menus, and scroll bars. A window device
857 * context permits painting anywhere in a window, because the origin of the
858 * device context is the upper-left corner of the window instead of the client
865 NtUserGetWindowDC(HWND hWnd
)
867 return NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
871 NtUserGetDC(HWND hWnd
)
873 DPRINT("NtUGetDC -> %x:%x\n", hWnd
, !hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
875 return NtUserGetDCEx(hWnd
, NULL
, NULL
== hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
879 * Select logical palette into device context.
880 * \param hDC handle to the device context
881 * \param hpal handle to the palette
882 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
883 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
884 * palette colors in the best way.
885 * \return old palette
887 * \todo implement ForceBackground == TRUE
891 NtUserSelectPalette(HDC hDC
,
893 BOOL ForceBackground
)
896 UserEnterExclusive();
897 // Implement window checks
898 oldPal
= GdiSelectPalette( hDC
, hpal
, ForceBackground
);