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 int FASTCALL
CLIPPING_UpdateGCRegion(DC
* Dc
);
19 /* GLOBALS *******************************************************************/
21 /* NOTE - I think we should store this per window station (including gdi objects) */
23 static PDCE FirstDce
= NULL
;
24 //static INT DCECount = 0; // Count of DCE in system.
26 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
27 DCX_NORESETATTRS | DCX_LOCKWINDOWUPDATE | \
28 DCX_LAYEREDWIN | DCX_CACHE | DCX_WINDOW | \
31 /* FUNCTIONS *****************************************************************/
34 // This should be moved to dc.c or dcutil.c.
37 DceCreateDisplayDC(VOID
)
40 UNICODE_STRING DriverName
;
41 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
42 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
44 // If NULL, first time through! Build the default window dc!
46 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
47 { // This is a cheesy way to do this.
48 PDC dc
= DC_LockDc ( hDC
);
49 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
50 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
51 defaultDCstate
->pdcattr
= &defaultDCstate
->dcattr
;
52 DC_vCopyState(dc
, defaultDCstate
, TRUE
);
60 DceGetVisRgn(PWINDOW_OBJECT Window
, ULONG Flags
, HWND hWndChild
, ULONG CFlags
)
64 VisRgn
= VIS_ComputeVisibleRegion( Window
,
65 0 == (Flags
& DCX_WINDOW
),
66 0 != (Flags
& DCX_CLIPCHILDREN
),
67 0 != (Flags
& DCX_CLIPSIBLINGS
));
70 VisRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
76 DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL
, DCE_TYPE Type
)
81 if (Window
) Wnd
= Window
->Wnd
;
83 pDce
= ExAllocatePoolWithTag(PagedPool
, sizeof(DCE
), TAG_PDCE
);
87 pDce
->hDC
= DceCreateDisplayDC();
90 ExFreePoolWithTag(pDce
, TAG_PDCE
);
94 pDce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
97 pDce
->hrgnClip
= NULL
;
98 pDce
->hrgnClipPublic
= NULL
;
99 pDce
->hrgnSavedVis
= NULL
;
100 pDce
->ppiOwner
= NULL
;
102 KeEnterCriticalRegion();
103 if (FirstDce
== NULL
)
106 InitializeListHead(&FirstDce
->List
);
109 InsertTailList(&FirstDce
->List
, &pDce
->List
);
110 KeLeaveCriticalRegion();
112 DCU_SetDcUndeletable(pDce
->hDC
);
114 if (Type
== DCE_WINDOW_DC
|| Type
== DCE_CLASS_DC
) //Window DCE have ownership.
116 pDce
->ptiOwner
= GetW32ThreadInfo();
120 DPRINT("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce
->hDC
);
121 IntGdiSetDCOwnerEx( pDce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
);
122 pDce
->ptiOwner
= NULL
;
125 if (Type
== DCE_CACHE_DC
)
127 pDce
->DCXFlags
= DCX_CACHE
| DCX_DCEEMPTY
;
131 pDce
->DCXFlags
= DCX_DCEBUSY
;
134 if (Type
== DCE_WINDOW_DC
)
136 if (Wnd
->style
& WS_CLIPCHILDREN
) pDce
->DCXFlags
|= DCX_CLIPCHILDREN
;
137 if (Wnd
->style
& WS_CLIPSIBLINGS
) pDce
->DCXFlags
|= DCX_CLIPSIBLINGS
;
145 DceSetDrawable( PWINDOW_OBJECT Window OPTIONAL
,
151 DC
*dc
= DC_LockDc(hDC
);
163 if (Flags
& DCX_WINDOW
)
165 dc
->ptlDCOrig
.x
= Wnd
->rcWindow
.left
;
166 dc
->ptlDCOrig
.y
= Wnd
->rcWindow
.top
;
170 dc
->ptlDCOrig
.x
= Wnd
->rcClient
.left
;
171 dc
->ptlDCOrig
.y
= Wnd
->rcClient
.top
;
179 DceDeleteClipRgn(DCE
* Dce
)
181 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
183 if (Dce
->DCXFlags
& DCX_KEEPCLIPRGN
)
185 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
187 else if (Dce
->hrgnClip
!= NULL
)
189 REGION_FreeRgnByHandle(Dce
->hrgnClip
);
192 Dce
->hrgnClip
= NULL
;
194 /* make it dirty so that the vis rgn gets recomputed next time */
195 Dce
->DCXFlags
|= DCX_DCEDIRTY
;
199 DceReleaseDC(DCE
* dce
, BOOL EndPaint
)
201 if (DCX_DCEBUSY
!= (dce
->DCXFlags
& (DCX_DCEEMPTY
| DCX_DCEBUSY
)))
206 /* restore previous visible region */
208 if ((dce
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) &&
209 ((dce
->DCXFlags
& DCX_CACHE
) || EndPaint
))
211 DceDeleteClipRgn(dce
);
214 if (dce
->DCXFlags
& DCX_CACHE
)
216 if (!(dce
->DCXFlags
& DCX_NORESETATTRS
))
218 /* make the DC clean so that SetDCState doesn't try to update the vis rgn */
219 IntGdiSetHookFlags(dce
->hDC
, DCHF_VALIDATEVISRGN
);
222 if (!IntGdiCleanDC(dce
->hDC
)) return 0;
224 if (dce
->DCXFlags
& DCX_DCEDIRTY
)
226 /* don't keep around invalidated entries
227 * because SetDCState() disables hVisRgn updates
228 * by removing dirty bit. */
229 dce
->hwndCurrent
= 0;
230 dce
->DCXFlags
&= DCX_CACHE
;
231 dce
->DCXFlags
|= DCX_DCEEMPTY
;
234 dce
->DCXFlags
&= ~DCX_DCEBUSY
;
235 DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce
->hDC
);
236 if (!IntGdiSetDCOwnerEx( dce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
))
238 dce
->ptiOwner
= NULL
; // Reset ownership.
239 dce
->ppiOwner
= NULL
;
241 return 1; // Released!
245 DceUpdateVisRgn(DCE
*Dce
, PWINDOW_OBJECT Window
, ULONG Flags
)
247 HANDLE hRgnVisible
= NULL
;
249 PWINDOW_OBJECT DesktopWindow
;
251 if (Flags
& DCX_PARENTCLIP
)
253 PWINDOW_OBJECT Parent
;
256 Parent
= Window
->spwndParent
;
263 ParentWnd
= Parent
->Wnd
;
265 if (ParentWnd
->style
& WS_CLIPSIBLINGS
)
267 DcxFlags
= DCX_CLIPSIBLINGS
|
268 (Flags
& ~(DCX_CLIPCHILDREN
| DCX_WINDOW
));
272 DcxFlags
= Flags
& ~(DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
| DCX_WINDOW
);
274 hRgnVisible
= DceGetVisRgn(Parent
, DcxFlags
, Window
->hSelf
, Flags
);
276 else if (Window
== NULL
)
278 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
279 if (NULL
!= DesktopWindow
)
281 hRgnVisible
= IntSysCreateRectRgnIndirect(&DesktopWindow
->Wnd
->rcWindow
);
290 hRgnVisible
= DceGetVisRgn(Window
, Flags
, 0, 0);
294 if (Flags
& DCX_INTERSECTRGN
)
296 if(Dce
->hrgnClip
!= NULL
)
298 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hrgnClip
, RGN_AND
);
302 if(hRgnVisible
!= NULL
)
304 REGION_FreeRgnByHandle(hRgnVisible
);
306 hRgnVisible
= IntSysCreateRectRgn(0, 0, 0, 0);
309 else if (Flags
& DCX_EXCLUDERGN
&& Dce
->hrgnClip
!= NULL
)
311 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hrgnClip
, RGN_DIFF
);
314 Dce
->DCXFlags
&= ~DCX_DCEDIRTY
;
315 GdiSelectVisRgn(Dce
->hDC
, hRgnVisible
);
319 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
322 if (hRgnVisible
!= NULL
)
324 REGION_FreeRgnByHandle(hRgnVisible
);
329 UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
331 PWINDOW_OBJECT Parent
;
334 BOOL UpdateClipOrigin
= FALSE
;
341 Flags
&= ~DCX_USESTYLE
;
347 if (Flags
& (DCX_WINDOW
| DCX_PARENTCLIP
)) Flags
|= DCX_CACHE
;
349 // When GetDC is called with hWnd nz, DCX_CACHE & _WINDOW are clear w _USESTYLE set.
350 if (Flags
& DCX_USESTYLE
)
352 Flags
&= ~(DCX_CLIPCHILDREN
| DCX_CLIPSIBLINGS
| DCX_PARENTCLIP
);
353 if (!(Flags
& DCX_WINDOW
)) // not window rectangle
355 if (Wnd
->pcls
->style
& CS_PARENTDC
)
357 Flags
|= DCX_PARENTCLIP
;
360 if (!(Flags
& DCX_CACHE
) && // Not on the cheap wine list.
361 !(Wnd
->pcls
->style
& CS_OWNDC
) )
363 if (!(Wnd
->pcls
->style
& CS_CLASSDC
))
364 // The window is not POWNED or has any CLASS, so we are looking for cheap wine.
368 if (Wnd
->pcls
->pdce
) hDC
= ((PDCE
)Wnd
->pcls
->pdce
)->hDC
;
369 DPRINT("We have CLASS!!\n");
372 /* else // For Testing!
374 DPRINT1("We have POWNER!!\n");
375 if (Window->Dce) DPRINT1("We have POWNER with DCE!!\n");
378 if (Wnd
->style
& WS_CLIPSIBLINGS
)
380 Flags
|= DCX_CLIPSIBLINGS
;
383 if (Wnd
->style
& WS_CLIPCHILDREN
&&
384 !(Wnd
->style
& WS_MINIMIZE
))
386 Flags
|= DCX_CLIPCHILDREN
;
388 /* If minized with icon in the set, we are forced to be cheap! */
389 if (Wnd
->style
& WS_MINIMIZE
&&
397 if (Wnd
->style
& WS_CLIPSIBLINGS
) Flags
|= DCX_CLIPSIBLINGS
;
402 if (Flags
& DCX_WINDOW
) Flags
&= ~DCX_CLIPCHILDREN
;
404 if (Flags
& DCX_NOCLIPCHILDREN
)
407 Flags
&= ~(DCX_PARENTCLIP
| DCX_CLIPCHILDREN
);
410 Parent
= (Window
? Window
->spwndParent
: NULL
);
412 if (NULL
== Window
|| !(Wnd
->style
& WS_CHILD
) || NULL
== Parent
)
414 Flags
&= ~DCX_PARENTCLIP
;
415 Flags
|= DCX_CLIPSIBLINGS
;
418 /* it seems parent clip is ignored when clipping siblings or children */
419 if (Flags
& (DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
)) Flags
&= ~DCX_PARENTCLIP
;
421 if (Flags
& DCX_PARENTCLIP
)
423 if ((Wnd
->style
& WS_VISIBLE
) &&
424 (Parent
->Wnd
->style
& WS_VISIBLE
))
426 Flags
&= ~DCX_CLIPCHILDREN
;
427 if (Parent
->Wnd
->style
& WS_CLIPSIBLINGS
)
429 Flags
|= DCX_CLIPSIBLINGS
;
434 // Window nz, check to see if we still own this or it is just cheap wine tonight.
435 if (!(Flags
& DCX_CACHE
))
437 if ( Wnd
->head
.pti
!= GetW32ThreadInfo())
438 Flags
|= DCX_CACHE
; // Ah~ Not Powned! Forced to be cheap~
441 DcxFlags
= Flags
& DCX_CACHECOMPAREMASK
;
443 if (Flags
& DCX_CACHE
)
444 { // Scan the cheap wine list for our match.
445 DCE
* DceEmpty
= NULL
;
446 DCE
* DceUnused
= NULL
;
447 KeEnterCriticalRegion();
451 // The reason for this you may ask?
452 // Well, it seems ReactOS calls GetDC with out first creating a desktop DC window!
453 // Need to test for null here. Not sure if this is a bug or a feature.
454 // First time use hax, need to use DceAllocDCE during window display init.
457 // The way I understand this, you can have more than one DC per window.
458 // Only one Owned if one was requested and saved and one Cached.
460 if ((Dce
->DCXFlags
& (DCX_CACHE
| DCX_DCEBUSY
)) == DCX_CACHE
)
463 if (Dce
->DCXFlags
& DCX_DCEEMPTY
)
467 else if (Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
) &&
468 ((Dce
->DCXFlags
& DCX_CACHECOMPAREMASK
) == DcxFlags
))
470 UpdateClipOrigin
= TRUE
;
474 Dce
= (PDCE
)Dce
->List
.Flink
;
475 } while (Dce
!= FirstDce
);
476 KeLeaveCriticalRegion();
478 Dce
= (DceEmpty
== NULL
) ? DceUnused
: DceEmpty
;
482 Dce
= DceAllocDCE(NULL
, DCE_CACHE_DC
);
484 if (!Dce
) return NULL
;
486 Dce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
488 else // If we are here, we are POWNED or having CLASS.
490 KeEnterCriticalRegion();
493 { // Check for Window handle than HDC match for CLASS.
494 if ((Dce
->hwndCurrent
== Window
->hSelf
) ||
497 Dce
= (PDCE
)Dce
->List
.Flink
;
498 } while (Dce
!= FirstDce
);
499 KeLeaveCriticalRegion();
501 if ( (Flags
& (DCX_INTERSECTRGN
|DCX_EXCLUDERGN
)) &&
502 (Dce
->DCXFlags
& (DCX_INTERSECTRGN
|DCX_EXCLUDERGN
)) )
504 DceDeleteClipRgn(Dce
);
507 // First time use hax, need to use DceAllocDCE during window display init.
513 if (!GDIOBJ_ValidateHandle(Dce
->hDC
, GDI_OBJECT_TYPE_DC
))
515 DPRINT1("FIXME: Got DCE with invalid hDC! 0x%x\n", Dce
->hDC
);
516 Dce
->hDC
= DceCreateDisplayDC();
517 /* FIXME: Handle error */
520 Dce
->DCXFlags
= Flags
| DCX_DCEBUSY
;
523 Bump it up! This prevents the random errors in wine dce tests and with
524 proper bits set in DCX_CACHECOMPAREMASK.
526 http://www.reactos.org/archives/public/ros-dev/2008-July/010498.html
527 http://www.reactos.org/archives/public/ros-dev/2008-July/010499.html
529 if ((Dce
!= FirstDce
))
531 RemoveEntryList(&Dce
->List
);
532 InsertHeadList(&FirstDce
->List
, &Dce
->List
);
536 /* Introduced in rev 6691 and modified later. */
537 if ( (Flags
& DCX_INTERSECTUPDATE
) && !ClipRegion
)
539 Flags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
540 Dce
->DCXFlags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
541 ClipRegion
= Window
->hrgnUpdate
;
544 if (ClipRegion
== (HRGN
) 1)
546 if (!(Flags
& DCX_WINDOW
))
548 Dce
->hrgnClip
= IntSysCreateRectRgnIndirect(&Window
->Wnd
->rcClient
);
552 Dce
->hrgnClip
= IntSysCreateRectRgnIndirect(&Window
->Wnd
->rcWindow
);
554 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
556 else if (ClipRegion
!= NULL
)
558 Dce
->hrgnClip
= ClipRegion
;
561 DceSetDrawable(Window
, Dce
->hDC
, Flags
, UpdateClipOrigin
);
563 DceUpdateVisRgn(Dce
, Window
, Flags
);
565 if (Dce
->DCXFlags
& DCX_CACHE
)
567 DPRINT("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %x\n", Dce
->hDC
);
568 // Need to set ownership so Sync dcattr will work.
569 IntGdiSetDCOwnerEx( Dce
->hDC
, GDI_OBJ_HMGR_POWNED
, FALSE
);
570 Dce
->ptiOwner
= GetW32ThreadInfo(); // Set the temp owning
574 Wnd
->ExStyle
& WS_EX_LAYOUTRTL
&&
575 !(Flags
& DCX_KEEPLAYOUT
) )
577 NtGdiSetLayout(Dce
->hDC
, -1, LAYOUT_RTL
);
580 if (Dce
->DCXFlags
& DCX_PROCESSOWNED
)
582 ppi
= PsGetCurrentProcessWin32Process();
583 ppi
->W32PF_flags
|= W32PF_OWNDCCLEANUP
;
584 Dce
->ptiOwner
= NULL
;
591 /***********************************************************************
595 DceFreeDCE(PDCE pdce
, BOOLEAN Force
)
600 if (NULL
== pdce
) return NULL
;
602 ret
= (PDCE
) pdce
->List
.Flink
;
605 SetDCHook(pdce
->hDC
, NULL
, 0L);
608 if (Force
&& !GDIOBJ_OwnedByCurrentProcess(pdce
->hDC
))
610 DPRINT("Change ownership for DCE! -> %x\n" , pdce
);
611 // Note: Windows sets W32PF_OWNDCCLEANUP and moves on.
612 if (!IsObjectDead((HGDIOBJ
) pdce
->hDC
))
614 DC_SetOwnership( pdce
->hDC
, PsGetCurrentProcess());
618 DPRINT1("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce
->hDC
);
623 if (!Hit
) IntGdiDeleteDC(pdce
->hDC
, TRUE
);
625 if (pdce
->hrgnClip
&& ! (pdce
->DCXFlags
& DCX_KEEPCLIPRGN
))
627 REGION_FreeRgnByHandle(pdce
->hrgnClip
);
630 RemoveEntryList(&pdce
->List
);
632 if (IsListEmpty(&pdce
->List
))
634 DPRINT1("List is Empty! DCE! -> %x\n" , pdce
);
639 ExFreePoolWithTag(pdce
, TAG_PDCE
);
645 DceFreeClassDCE(HDC hDC
)
647 PDCE pDCE
= FirstDce
;
648 KeEnterCriticalRegion();
652 if (pDCE
->hDC
== hDC
)
654 pDCE
= DceFreeDCE(pDCE
, FALSE
);
658 pDCE
= (PDCE
)pDCE
->List
.Flink
;
659 } while (pDCE
!= FirstDce
);
660 KeLeaveCriticalRegion();
666 PDCE pDCE
= FirstDce
;
667 KeEnterCriticalRegion();
671 pDCE
= DceFreeDCE(pDCE
, TRUE
);
673 } while (pDCE
!= FirstDce
);
674 KeLeaveCriticalRegion();
679 DceResetActiveDCEs(PWINDOW_OBJECT Window
)
683 PWINDOW_OBJECT CurrentWindow
;
692 if(!pDCE
) return; // Another null test!
696 if (0 == (pDCE
->DCXFlags
& DCX_DCEEMPTY
))
698 if (Window
->hSelf
== pDCE
->hwndCurrent
)
700 CurrentWindow
= Window
;
704 CurrentWindow
= UserGetWindowObject(pDCE
->hwndCurrent
);
705 if (NULL
== CurrentWindow
)
707 pDCE
= (PDCE
) pDCE
->List
.Flink
;
712 if (!GDIOBJ_ValidateHandle(pDCE
->hDC
, GDI_OBJECT_TYPE_DC
) ||
713 (dc
= DC_LockDc(pDCE
->hDC
)) == NULL
)
715 pDCE
= (PDCE
) pDCE
->List
.Flink
;
718 if (Window
== CurrentWindow
|| IntIsChildWindow(Window
, CurrentWindow
))
720 if (pDCE
->DCXFlags
& DCX_WINDOW
)
722 DeltaX
= CurrentWindow
->Wnd
->rcWindow
.left
- dc
->ptlDCOrig
.x
;
723 DeltaY
= CurrentWindow
->Wnd
->rcWindow
.top
- dc
->ptlDCOrig
.y
;
724 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->rcWindow
.left
;
725 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->rcWindow
.top
;
729 DeltaX
= CurrentWindow
->Wnd
->rcClient
.left
- dc
->ptlDCOrig
.x
;
730 DeltaY
= CurrentWindow
->Wnd
->rcClient
.top
- dc
->ptlDCOrig
.y
;
731 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->rcClient
.left
;
732 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->rcClient
.top
;
734 if (NULL
!= dc
->rosdc
.hClipRgn
)
736 NtGdiOffsetRgn(dc
->rosdc
.hClipRgn
, DeltaX
, DeltaY
);
737 CLIPPING_UpdateGCRegion(dc
);
739 if (NULL
!= pDCE
->hrgnClip
)
741 NtGdiOffsetRgn(pDCE
->hrgnClip
, DeltaX
, DeltaY
);
746 DceUpdateVisRgn(pDCE
, CurrentWindow
, pDCE
->DCXFlags
);
748 if (Window
->hSelf
!= pDCE
->hwndCurrent
)
750 // IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
751 // UserDerefObject(CurrentWindow);
754 pDCE
=(PDCE
) pDCE
->List
.Flink
;
755 } while (pDCE
!= FirstDce
);
759 IntWindowFromDC(HDC hDc
)
763 KeEnterCriticalRegion();
769 Ret
= Dce
->hwndCurrent
;
772 Dce
= (PDCE
)Dce
->List
.Flink
;
773 } while (Dce
!= FirstDce
);
774 KeLeaveCriticalRegion();
779 UserReleaseDC(PWINDOW_OBJECT Window
, HDC hDc
, BOOL EndPaint
)
785 DPRINT("%p %p\n", Window
, hDc
);
787 KeEnterCriticalRegion();
797 dce
= (PDCE
) dce
->List
.Flink
;
799 while (dce
!= FirstDce
);
800 KeLeaveCriticalRegion();
802 if ( Hit
&& (dce
->DCXFlags
& DCX_DCEBUSY
))
804 nRet
= DceReleaseDC(dce
, EndPaint
);
811 UserGetWindowDC(PWINDOW_OBJECT Wnd
)
813 return UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
817 UserGethWnd( HDC hdc
, PWNDOBJ
*pwndo
)
823 hWnd
= IntWindowFromDC(hdc
);
825 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
827 pWndgdi
= (WNDGDI
*)IntGetProp(Wnd
, AtomWndObj
);
829 if ( pWndgdi
&& pWndgdi
->Hwnd
== hWnd
)
831 if (pwndo
) *pwndo
= (PWNDOBJ
)pWndgdi
;
838 NtUserGetDCEx(HWND hWnd OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
840 PWINDOW_OBJECT Wnd
=NULL
;
843 DPRINT("Enter NtUserGetDCEx\n");
844 UserEnterExclusive();
846 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
850 RETURN( UserGetDCEx(Wnd
, ClipRegion
, Flags
));
853 DPRINT("Leave NtUserGetDCEx, ret=%i\n",_ret_
);
861 * The NtUserGetWindowDC function retrieves the device context (DC) for the
862 * entire window, including title bar, menus, and scroll bars. A window device
863 * context permits painting anywhere in a window, because the origin of the
864 * device context is the upper-left corner of the window instead of the client
871 NtUserGetWindowDC(HWND hWnd
)
873 return NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
877 NtUserGetDC(HWND hWnd
)
879 DPRINT("NtUGetDC -> %x:%x\n", hWnd
, !hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
881 return NtUserGetDCEx(hWnd
, NULL
, NULL
== hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
885 * Select logical palette into device context.
886 * \param hDC handle to the device context
887 * \param hpal handle to the palette
888 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
889 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
890 * palette colors in the best way.
891 * \return old palette
893 * \todo implement ForceBackground == TRUE
897 NtUserSelectPalette(HDC hDC
,
899 BOOL ForceBackground
)
902 UserEnterExclusive();
903 // Implement window checks
904 oldPal
= GdiSelectPalette( hDC
, hpal
, ForceBackground
);