2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsystems/win32/win32k/ntuser/windc.c
5 * PURPOSE: Keyboard layout 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 PDC defaultDCstate
= NULL
;
23 //static INT DCECount = 0; // Count of DCE in system.
25 #define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
26 DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
28 /* FUNCTIONS *****************************************************************/
31 // This should be moved to dc.c or dcutil.c.
34 DceCreateDisplayDC(VOID
)
37 UNICODE_STRING DriverName
;
38 RtlInitUnicodeString(&DriverName
, L
"DISPLAY");
39 hDC
= IntGdiCreateDC(&DriverName
, NULL
, NULL
, NULL
, FALSE
);
41 // If NULL, first time through! Build the default window dc!
43 if (hDC
&& !defaultDCstate
) // Ultra HAX! Dedicated to GvG!
44 { // This is a cheesy way to do this.
45 PDC dc
= DC_LockDc ( hDC
);
46 defaultDCstate
= ExAllocatePoolWithTag(PagedPool
, sizeof(DC
), TAG_DC
);
47 RtlZeroMemory(defaultDCstate
, sizeof(DC
));
48 IntGdiCopyToSaveState(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
= NtGdiCreateRectRgn(0, 0, 0, 0);
73 DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL
, DCE_TYPE Type
)
79 if (Window
) Wnd
= Window
->Wnd
;
81 if (Wnd
) Class
= Wnd
->Class
;
83 if (Type
== DCE_CLASS_DC
)
86 KeEnterCriticalRegion();
90 if (pdce
->Class
== Class
)
93 KeLeaveCriticalRegion();
96 pdce
= (PDCE
)pdce
->List
.Flink
;
97 } while (pdce
!= FirstDce
);
98 KeLeaveCriticalRegion();
101 pDce
= ExAllocatePoolWithTag(PagedPool
, sizeof(DCE
), TAG_PDCE
);
105 pDce
->hDC
= DceCreateDisplayDC();
108 ExFreePoolWithTag(pDce
, TAG_PDCE
);
112 pDce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
113 pDce
->hClipRgn
= NULL
;
114 pDce
->pProcess
= NULL
;
118 KeEnterCriticalRegion();
119 if (FirstDce
== NULL
)
122 InitializeListHead(&FirstDce
->List
);
125 InsertTailList(&FirstDce
->List
, &pDce
->List
);
126 KeLeaveCriticalRegion();
128 DCU_SetDcUndeletable(pDce
->hDC
);
130 if (Type
== DCE_WINDOW_DC
|| Type
== DCE_CLASS_DC
) //Window DCE have ownership.
131 { // Process should already own it.
132 pDce
->pProcess
= PsGetCurrentProcess();
136 DPRINT("FREE DCATTR!!!! NOT DCE_WINDOW_DC!!!!! hDC-> %x\n", pDce
->hDC
);
137 IntGdiSetDCOwnerEx( pDce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
);
140 if (Type
== DCE_CACHE_DC
)
142 pDce
->DCXFlags
= DCX_CACHE
| DCX_DCEEMPTY
;
146 pDce
->DCXFlags
= DCX_DCEBUSY
;
149 if (Type
== DCE_WINDOW_DC
)
151 if (Wnd
->Style
& WS_CLIPCHILDREN
) pDce
->DCXFlags
|= DCX_CLIPCHILDREN
;
152 if (Wnd
->Style
& WS_CLIPSIBLINGS
) pDce
->DCXFlags
|= DCX_CLIPSIBLINGS
;
160 DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL
, HDC hDC
, ULONG Flags
,
164 DC
*dc
= DC_LockDc(hDC
);
176 if (Flags
& DCX_WINDOW
)
178 dc
->ptlDCOrig
.x
= Wnd
->WindowRect
.left
;
179 dc
->ptlDCOrig
.y
= Wnd
->WindowRect
.top
;
183 dc
->ptlDCOrig
.x
= Wnd
->ClientRect
.left
;
184 dc
->ptlDCOrig
.y
= Wnd
->ClientRect
.top
;
192 DceDeleteClipRgn(DCE
* Dce
)
194 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
196 if (Dce
->DCXFlags
& DCX_KEEPCLIPRGN
)
198 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
200 else if (Dce
->hClipRgn
!= NULL
)
202 NtGdiDeleteObject(Dce
->hClipRgn
);
205 Dce
->hClipRgn
= NULL
;
207 /* make it dirty so that the vis rgn gets recomputed next time */
208 Dce
->DCXFlags
|= DCX_DCEDIRTY
;
212 DceReleaseDC(DCE
* dce
, BOOL EndPaint
)
214 if (DCX_DCEBUSY
!= (dce
->DCXFlags
& (DCX_DCEEMPTY
| DCX_DCEBUSY
)))
219 /* restore previous visible region */
221 if ((dce
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) &&
222 ((dce
->DCXFlags
& DCX_CACHE
) || EndPaint
))
224 DceDeleteClipRgn(dce
);
227 if (dce
->DCXFlags
& DCX_CACHE
)
229 if (!(dce
->DCXFlags
& DCX_NORESETATTRS
))
232 /* make the DC clean so that SetDCState doesn't try to update the vis rgn */
233 IntGdiSetHookFlags(dce
->hDC
, DCHF_VALIDATEVISRGN
);
235 dc
= DC_LockDc ( dce
->hDC
);
237 IntGdiCopyFromSaveState(dc
, defaultDCstate
, dce
->hDC
); // Was SetDCState.
239 dce
->DCXFlags
&= ~DCX_DCEBUSY
;
240 if (dce
->DCXFlags
& DCX_DCEDIRTY
)
242 /* don't keep around invalidated entries
243 * because SetDCState() disables hVisRgn updates
244 * by removing dirty bit. */
245 dce
->hwndCurrent
= 0;
246 dce
->DCXFlags
&= DCX_CACHE
;
247 dce
->DCXFlags
|= DCX_DCEEMPTY
;
251 { // Save Users Dc_Attr.
252 PDC dc
= DC_LockDc(dce
->hDC
);
255 PDC_ATTR Dc_Attr
= dc
->pDc_Attr
;
256 if(Dc_Attr
) MmCopyFromCaller(&dc
->Dc_Attr
, Dc_Attr
, sizeof(DC_ATTR
));
260 DPRINT("Exit!!!!! DCX_CACHE!!!!!! hDC-> %x \n", dce
->hDC
);
261 if (!IntGdiSetDCOwnerEx( dce
->hDC
, GDI_OBJ_HMGR_NONE
, FALSE
))
263 dce
->pProcess
= NULL
; // Reset ownership.
269 DceUpdateVisRgn(DCE
*Dce
, PWINDOW_OBJECT Window
, ULONG Flags
)
271 HANDLE hRgnVisible
= NULL
;
273 PWINDOW_OBJECT DesktopWindow
;
275 if (Flags
& DCX_PARENTCLIP
)
277 PWINDOW_OBJECT Parent
;
280 Parent
= Window
->Parent
;
287 ParentWnd
= Parent
->Wnd
;
289 if (ParentWnd
->Style
& WS_CLIPSIBLINGS
)
291 DcxFlags
= DCX_CLIPSIBLINGS
|
292 (Flags
& ~(DCX_CLIPCHILDREN
| DCX_WINDOW
));
296 DcxFlags
= Flags
& ~(DCX_CLIPSIBLINGS
| DCX_CLIPCHILDREN
| DCX_WINDOW
);
298 hRgnVisible
= DceGetVisRgn(Parent
, DcxFlags
, Window
->hSelf
, Flags
);
300 else if (Window
== NULL
)
302 DesktopWindow
= UserGetWindowObject(IntGetDesktopWindow());
303 if (NULL
!= DesktopWindow
)
305 hRgnVisible
= UnsafeIntCreateRectRgnIndirect(&DesktopWindow
->Wnd
->WindowRect
);
314 hRgnVisible
= DceGetVisRgn(Window
, Flags
, 0, 0);
318 if (Flags
& DCX_INTERSECTRGN
)
320 if(Dce
->hClipRgn
!= NULL
)
322 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_AND
);
326 if(hRgnVisible
!= NULL
)
328 NtGdiDeleteObject(hRgnVisible
);
330 hRgnVisible
= NtGdiCreateRectRgn(0, 0, 0, 0);
334 if (Flags
& DCX_EXCLUDERGN
&& Dce
->hClipRgn
!= NULL
)
336 NtGdiCombineRgn(hRgnVisible
, hRgnVisible
, Dce
->hClipRgn
, RGN_DIFF
);
339 Dce
->DCXFlags
&= ~DCX_DCEDIRTY
;
340 GdiSelectVisRgn(Dce
->hDC
, hRgnVisible
);
344 IntEngWindowChanged(Window
, WOC_RGN_CLIENT
);
347 if (hRgnVisible
!= NULL
)
349 NtGdiDeleteObject(hRgnVisible
);
354 UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
356 PWINDOW_OBJECT Parent
;
359 BOOL UpdateVisRgn
= TRUE
;
360 BOOL UpdateClipOrigin
= FALSE
;
364 { // Do the same as GetDC with a NULL.
365 // Window = UserGetWindowObject(IntGetDesktopWindow());
366 // if (Window) Wnd = Window->Wnd;
368 Flags
&= ~DCX_USESTYLE
;
373 if (NULL
== Window
|| NULL
== Window
->Dce
)
378 if (Flags
& DCX_USESTYLE
)
380 Flags
&= ~(DCX_CLIPCHILDREN
| DCX_CLIPSIBLINGS
| DCX_PARENTCLIP
);
382 if (Wnd
->Style
& WS_CLIPSIBLINGS
)
384 Flags
|= DCX_CLIPSIBLINGS
;
387 if (!(Flags
& DCX_WINDOW
))
389 if (Wnd
->Class
->Style
& CS_PARENTDC
)
391 Flags
|= DCX_PARENTCLIP
;
394 if (Wnd
->Style
& WS_CLIPCHILDREN
&&
395 !(Wnd
->Style
& WS_MINIMIZE
))
397 Flags
|= DCX_CLIPCHILDREN
;
406 if (Flags
& DCX_NOCLIPCHILDREN
)
409 Flags
&= ~(DCX_PARENTCLIP
| DCX_CLIPCHILDREN
);
412 if (Flags
& DCX_WINDOW
)
414 Flags
= (Flags
& ~DCX_CLIPCHILDREN
) | DCX_CACHE
;
417 Parent
= (Window
? Window
->Parent
: NULL
);
419 if (NULL
== Window
|| !(Wnd
->Style
& WS_CHILD
) || NULL
== Parent
)
421 Flags
&= ~DCX_PARENTCLIP
;
423 else if (Flags
& DCX_PARENTCLIP
)
426 if ((Wnd
->Style
& WS_VISIBLE
) &&
427 (Parent
->Wnd
->Style
& WS_VISIBLE
))
429 Flags
&= ~DCX_CLIPCHILDREN
;
430 if (Parent
->Wnd
->Style
& WS_CLIPSIBLINGS
)
432 Flags
|= DCX_CLIPSIBLINGS
;
437 DcxFlags
= Flags
& DCX_CACHECOMPAREMASK
;
439 if (Flags
& DCX_CACHE
)
441 DCE
* DceEmpty
= NULL
;
442 DCE
* DceUnused
= NULL
;
443 KeEnterCriticalRegion();
447 // The reason for this you may ask?
448 // Well, it seems ReactOS calls GetDC with out first creating a desktop DC window!
449 // Need to test for null here. Not sure if this is a bug or a feature.
452 if ((Dce
->DCXFlags
& (DCX_CACHE
| DCX_DCEBUSY
)) == DCX_CACHE
)
455 if (Dce
->DCXFlags
& DCX_DCEEMPTY
)
459 else if (Dce
->hwndCurrent
== (Window
? Window
->hSelf
: NULL
) &&
460 ((Dce
->DCXFlags
& DCX_CACHECOMPAREMASK
) == DcxFlags
))
463 UpdateVisRgn
= FALSE
;
466 UpdateClipOrigin
= TRUE
;
470 Dce
= (PDCE
)Dce
->List
.Flink
;
471 } while (Dce
!= FirstDce
);
472 KeLeaveCriticalRegion();
474 Dce
= (DceEmpty
== NULL
) ? DceUnused
: DceEmpty
;
478 Dce
= DceAllocDCE(NULL
, DCE_CACHE_DC
);
484 if (Dce
->hwndCurrent
== Window
->hSelf
)
486 UpdateVisRgn
= FALSE
; /* updated automatically, via DCHook() */
490 /* we should free dce->clip_rgn here, but Windows apparently doesn't */
491 Dce
->DCXFlags
&= ~(DCX_EXCLUDERGN
| DCX_INTERSECTRGN
);
492 Dce
->hClipRgn
= NULL
;
505 if (!GDIOBJ_ValidateHandle(Dce
->hDC
, GDI_OBJECT_TYPE_DC
))
507 DPRINT1("FIXME: Got DCE with invalid hDC!\n");
508 Dce
->hDC
= DceCreateDisplayDC();
509 /* FIXME: Handle error */
512 Dce
->hwndCurrent
= (Window
? Window
->hSelf
: NULL
);
513 Dce
->DCXFlags
= Flags
| DCX_DCEBUSY
;
515 if (0 == (Flags
& (DCX_EXCLUDERGN
| DCX_INTERSECTRGN
)) && NULL
!= ClipRegion
)
517 if (!(Flags
& DCX_KEEPCLIPRGN
))
518 NtGdiDeleteObject(ClipRegion
);
523 if (NULL
!= Dce
->hClipRgn
)
525 DceDeleteClipRgn(Dce
);
529 if (0 != (Flags
& DCX_INTERSECTUPDATE
) && NULL
== ClipRegion
)
531 Flags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
532 Dce
->DCXFlags
|= DCX_INTERSECTRGN
| DCX_KEEPCLIPRGN
;
533 ClipRegion
= Window
->UpdateRegion
;
536 if (ClipRegion
== (HRGN
) 1)
538 if (!(Flags
& DCX_WINDOW
))
540 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->ClientRect
);
544 Dce
->hClipRgn
= UnsafeIntCreateRectRgnIndirect(&Window
->Wnd
->WindowRect
);
546 Dce
->DCXFlags
&= ~DCX_KEEPCLIPRGN
;
548 else if (ClipRegion
!= NULL
)
550 Dce
->hClipRgn
= ClipRegion
;
553 DceSetDrawable(Window
, Dce
->hDC
, Flags
, UpdateClipOrigin
);
557 DceUpdateVisRgn(Dce
, Window
, Flags
);
560 if (Dce
->DCXFlags
& DCX_CACHE
)
562 DPRINT("ENTER!!!!!! DCX_CACHE!!!!!! hDC-> %x\n", Dce
->hDC
);
563 // Need to set ownership so Sync dcattr will work.
564 IntGdiSetDCOwnerEx( Dce
->hDC
, GDI_OBJ_HMGR_POWNED
, FALSE
);
565 Dce
->pProcess
= PsGetCurrentProcess(); // Set the temp owning process
570 /***********************************************************************
574 DceFreeDCE(PDCE pdce
, BOOLEAN Force
)
578 NTSTATUS Status
= STATUS_SUCCESS
;
580 if (NULL
== pdce
) return NULL
;
582 ret
= (PDCE
) pdce
->List
.Flink
;
585 SetDCHook(pdce
->hDC
, NULL
, 0L);
588 if (Force
&& !GDIOBJ_OwnedByCurrentProcess(pdce
->hDC
))
590 DPRINT1("Change ownership for DCE!\n");
592 if (!IsObjectDead((HGDIOBJ
) pdce
->hDC
))
593 DC_SetOwnership( pdce
->hDC
, PsGetCurrentProcess());
596 DPRINT1("Attempted to change ownership of an DCEhDC 0x%x currently being destroyed!!!\n",pdce
->hDC
);
601 if (!Hit
) IntGdiDeleteDC(pdce
->hDC
, TRUE
);
603 if (pdce
->hClipRgn
&& ! (pdce
->DCXFlags
& DCX_KEEPCLIPRGN
))
605 NtGdiDeleteObject(pdce
->hClipRgn
);
607 // Temp fix until we know where the problem is, most likely in windc.
610 RemoveEntryList(&pdce
->List
);
614 Status
= _SEH_GetExceptionCode();
617 if (!NT_SUCCESS(Status
))
619 SetLastNtError(Status
);
620 DPRINT1("CRASHED DCE! -> %x\n" , pdce
);
621 return 0; // Give it up and bail~!
624 ExFreePoolWithTag(pdce
, TAG_PDCE
);
629 /***********************************************************************
632 * Remove owned DCE and reset unreleased cache DCEs.
635 DceFreeWindowDCE(PWINDOW_OBJECT Window
)
640 KeEnterCriticalRegion();
643 if (pDCE
->hwndCurrent
== Window
->hSelf
)
645 if (!(pDCE
->DCXFlags
& DCX_CACHE
)) /* owned or Class DCE*/
647 if (Window
->Wnd
->Class
->Style
& CS_CLASSDC
||
648 Window
->Wnd
->Style
& CS_CLASSDC
) /* Test Class first */
650 if (pDCE
->DCXFlags
& (DCX_INTERSECTRGN
| DCX_EXCLUDERGN
)) /* Class DCE*/
651 DceDeleteClipRgn(pDCE
);
652 // Update and reset Vis Rgn and clear the dirty bit.
653 // Should release VisRgn than reset it to default.
654 DceUpdateVisRgn(pDCE
, Window
, pDCE
->DCXFlags
);
655 pDCE
->DCXFlags
= DCX_DCEEMPTY
;
656 pDCE
->hwndCurrent
= 0;
658 else if (Window
->Wnd
->Class
->Style
& CS_OWNDC
||
659 Window
->Wnd
->Style
& CS_OWNDC
) /* owned DCE*/
661 pDCE
= DceFreeDCE(pDCE
, FALSE
);
672 if (pDCE
->DCXFlags
& DCX_DCEBUSY
) /* shared cache DCE */
674 /* FIXME: AFAICS we are doing the right thing here so
675 * this should be a DPRINT. But this is best left as an ERR
676 * because the 'application error' is likely to come from
677 * another part of Wine (i.e. it's our fault after all).
678 * We should change this to DPRINT when ReactOS is more stable
681 DPRINT1("[%p] GetDC() without ReleaseDC()!\n", Window
->hSelf
);
682 DceReleaseDC(pDCE
, FALSE
);
684 pDCE
->DCXFlags
|= DCX_DCEEMPTY
;
685 pDCE
->hwndCurrent
= 0;
688 pDCE
= (PDCE
) pDCE
->List
.Flink
;
689 } while (pDCE
!= FirstDce
);
690 KeLeaveCriticalRegion();
696 PDCE pDCE
= FirstDce
;
697 KeEnterCriticalRegion();
701 pDCE
= DceFreeDCE(pDCE
, TRUE
);
703 } while (pDCE
!= FirstDce
);
704 KeLeaveCriticalRegion();
709 DceResetActiveDCEs(PWINDOW_OBJECT Window
)
713 PWINDOW_OBJECT CurrentWindow
;
722 if(!pDCE
) return; // Another null test!
725 if (0 == (pDCE
->DCXFlags
& DCX_DCEEMPTY
))
727 if (Window
->hSelf
== pDCE
->hwndCurrent
)
729 CurrentWindow
= Window
;
733 CurrentWindow
= UserGetWindowObject(pDCE
->hwndCurrent
);
734 if (NULL
== CurrentWindow
)
736 pDCE
= (PDCE
) pDCE
->List
.Flink
;
741 if (!GDIOBJ_ValidateHandle(pDCE
->hDC
, GDI_OBJECT_TYPE_DC
) ||
742 (dc
= DC_LockDc(pDCE
->hDC
)) == NULL
)
744 pDCE
= (PDCE
) pDCE
->List
.Flink
;
747 if (Window
== CurrentWindow
|| IntIsChildWindow(Window
, CurrentWindow
))
749 if (pDCE
->DCXFlags
& DCX_WINDOW
)
751 DeltaX
= CurrentWindow
->Wnd
->WindowRect
.left
- dc
->ptlDCOrig
.x
;
752 DeltaY
= CurrentWindow
->Wnd
->WindowRect
.top
- dc
->ptlDCOrig
.y
;
753 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->WindowRect
.left
;
754 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->WindowRect
.top
;
758 DeltaX
= CurrentWindow
->Wnd
->ClientRect
.left
- dc
->ptlDCOrig
.x
;
759 DeltaY
= CurrentWindow
->Wnd
->ClientRect
.top
- dc
->ptlDCOrig
.y
;
760 dc
->ptlDCOrig
.x
= CurrentWindow
->Wnd
->ClientRect
.left
;
761 dc
->ptlDCOrig
.y
= CurrentWindow
->Wnd
->ClientRect
.top
;
763 if (NULL
!= dc
->w
.hClipRgn
)
765 int FASTCALL
CLIPPING_UpdateGCRegion(DC
* Dc
);
766 NtGdiOffsetRgn(dc
->w
.hClipRgn
, DeltaX
, DeltaY
);
767 CLIPPING_UpdateGCRegion(dc
);
769 if (NULL
!= pDCE
->hClipRgn
)
771 NtGdiOffsetRgn(pDCE
->hClipRgn
, DeltaX
, DeltaY
);
776 DceUpdateVisRgn(pDCE
, CurrentWindow
, pDCE
->DCXFlags
);
778 if (Window
->hSelf
!= pDCE
->hwndCurrent
)
780 // IntEngWindowChanged(CurrentWindow, WOC_RGN_CLIENT);
781 // UserDerefObject(CurrentWindow);
784 pDCE
=(PDCE
) pDCE
->List
.Flink
;
785 } while (pDCE
!= FirstDce
);
790 IntGetDC(PWINDOW_OBJECT Window
)
794 //"hWnd [in] Handle to the window whose DC is to be retrieved.
795 // If this value is NULL, GetDC retrieves the DC for the entire screen."
796 Window
= UserGetWindowObject(IntGetDesktopWindow());
798 return UserGetDCEx(Window
, NULL
, DCX_CACHE
| DCX_WINDOW
);
802 return UserGetDCEx(Window
, NULL
, DCX_USESTYLE
);
806 IntWindowFromDC(HDC hDc
)
810 KeEnterCriticalRegion();
816 Ret
= Dce
->hwndCurrent
;
819 Dce
= (PDCE
)Dce
->List
.Flink
;
820 } while (Dce
!= FirstDce
);
821 KeLeaveCriticalRegion();
826 UserReleaseDC(PWINDOW_OBJECT Window
, HDC hDc
, BOOL EndPaint
)
832 DPRINT("%p %p\n", Window
, hDc
);
834 KeEnterCriticalRegion();
843 dce
= (PDCE
) dce
->List
.Flink
;
845 while (dce
!= FirstDce
);
846 KeLeaveCriticalRegion();
848 if ( Hit
&& (dce
->DCXFlags
& DCX_DCEBUSY
))
850 nRet
= DceReleaseDC(dce
, EndPaint
);
857 UserGetWindowDC(PWINDOW_OBJECT Wnd
)
859 return UserGetDCEx(Wnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
863 NtUserGetDCEx(HWND hWnd OPTIONAL
, HANDLE ClipRegion
, ULONG Flags
)
865 PWINDOW_OBJECT Wnd
=NULL
;
868 DPRINT("Enter NtUserGetDCEx\n");
869 UserEnterExclusive();
871 if (hWnd
&& !(Wnd
= UserGetWindowObject(hWnd
)))
876 RETURN( UserGetDCEx(Wnd
, ClipRegion
, Flags
));
879 DPRINT("Leave NtUserGetDCEx, ret=%i\n",_ret_
);
887 * The NtUserGetWindowDC function retrieves the device context (DC) for the
888 * entire window, including title bar, menus, and scroll bars. A window device
889 * context permits painting anywhere in a window, because the origin of the
890 * device context is the upper-left corner of the window instead of the client
897 NtUserGetWindowDC(HWND hWnd
)
899 return NtUserGetDCEx(hWnd
, 0, DCX_USESTYLE
| DCX_WINDOW
);
903 NtUserGetDC(HWND hWnd
)
905 // We have a problem here! Should call IntGetDC.
906 return NtUserGetDCEx(hWnd
, NULL
, NULL
== hWnd
? DCX_CACHE
| DCX_WINDOW
: DCX_USESTYLE
);
910 * Select logical palette into device context.
911 * \param hDC handle to the device context
912 * \param hpal handle to the palette
913 * \param ForceBackground If this value is FALSE the logical palette will be copied to the device palette only when the applicatioon
914 * is in the foreground. If this value is TRUE then map the colors in the logical palette to the device
915 * palette colors in the best way.
916 * \return old palette
918 * \todo implement ForceBackground == TRUE
920 HPALETTE STDCALL
NtUserSelectPalette(HDC hDC
,
922 BOOL ForceBackground
)
925 HPALETTE oldPal
= NULL
;
928 // FIXME: mark the palette as a [fore\back]ground pal
935 /* Check if this is a valid palette handle */
936 PalGDI
= PALETTE_LockPalette(hpal
);
943 /* Is this a valid palette for this depth? */
944 if ((dc
->w
.bitsPerPixel
<= 8 && PalGDI
->Mode
== PAL_INDEXED
) ||
945 (dc
->w
.bitsPerPixel
> 8 && PalGDI
->Mode
!= PAL_INDEXED
))
947 oldPal
= dc
->DcLevel
.hpal
;
948 dc
->DcLevel
.hpal
= hpal
;
950 else if (8 < dc
->w
.bitsPerPixel
&& PAL_INDEXED
== PalGDI
->Mode
)
952 oldPal
= dc
->DcLevel
.hpal
;
953 dc
->DcLevel
.hpal
= hpal
;
956 PALETTE_UnlockPalette(PalGDI
);