📄 windc.c
字号:
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: windc.c 28434 2007-08-20 19:50:07Z cfinck $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Window classes
* FILE: subsys/win32k/ntuser/class.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
/* NOTE - I think we should store this per window station (including gdi objects) */
static PDCE FirstDce = NULL;
static HDC defaultDCstate = NULL;
//static INT DCECount = 0;
#define DCX_CACHECOMPAREMASK (DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | \
DCX_CACHE | DCX_WINDOW | DCX_PARENTCLIP)
/* FUNCTIONS *****************************************************************/
HDC FASTCALL
DceCreateDisplayDC(VOID)
{
HDC hDC;
UNICODE_STRING DriverName;
RtlInitUnicodeString(&DriverName, L"DISPLAY");
hDC = IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE);
return hDC;
}
VOID FASTCALL
DceInit(VOID)
{
}
static
HRGN FASTCALL
DceGetVisRgn(PWINDOW_OBJECT Window, ULONG Flags, HWND hWndChild, ULONG CFlags)
{
HRGN VisRgn;
VisRgn = VIS_ComputeVisibleRegion(Window,
0 == (Flags & DCX_WINDOW),
0 != (Flags & DCX_CLIPCHILDREN),
0 != (Flags & DCX_CLIPSIBLINGS));
if (VisRgn == NULL)
VisRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
return VisRgn;
}
/*
* NtUserGetWindowDC
*
* The NtUserGetWindowDC function retrieves the device context (DC) for the
* entire window, including title bar, menus, and scroll bars. A window device
* context permits painting anywhere in a window, because the origin of the
* device context is the upper-left corner of the window instead of the client
* area.
*
* Status
* @implemented
*/
DWORD STDCALL
NtUserGetWindowDC(HWND hWnd)
{
return (DWORD)NtUserGetDCEx(hWnd, 0, DCX_USESTYLE | DCX_WINDOW);
}
DWORD FASTCALL
UserGetWindowDC(PWINDOW_OBJECT Wnd)
{
return (DWORD)UserGetDCEx(Wnd, 0, DCX_USESTYLE | DCX_WINDOW);
}
HDC STDCALL
NtUserGetDC(HWND hWnd)
{
return NtUserGetDCEx(hWnd, NULL, NULL == hWnd ? DCX_CACHE | DCX_WINDOW : DCX_USESTYLE);
}
PDCE FASTCALL
DceAllocDCE(PWINDOW_OBJECT Window OPTIONAL, DCE_TYPE Type)
{
PDCE pDce;
pDce = ExAllocatePoolWithTag(PagedPool, sizeof(DCE), TAG_PDCE);
if(!pDce)
return NULL;
pDce->hDC = DceCreateDisplayDC();
if(!pDce->hDC)
{
ExFreePoolWithTag(pDce, TAG_PDCE);
return NULL;
}
if (NULL == defaultDCstate) // Ultra HAX! Dedicated to GvG!
{ // This is a cheesy way to do this.
// But, due to the right way of creating gdi handles there is no choice.
defaultDCstate = IntGdiGetDCState(pDce->hDC);
DC_SetOwnership( defaultDCstate, NULL);
}
pDce->hwndCurrent = (Window ? Window->hSelf : NULL);
pDce->hClipRgn = NULL;
pDce->pProcess = NULL;
KeEnterCriticalRegion();
pDce->next = FirstDce;
FirstDce = pDce;
KeLeaveCriticalRegion();
if (Type == DCE_WINDOW_DC) //Window DCE have ownership.
{
DC_SetOwnership(pDce->hDC, PsGetCurrentProcess());
pDce->pProcess = PsGetCurrentProcess();
}
else
{
DC_SetOwnership(pDce->hDC, NULL); // This hDC is inaccessible!
}
if (Type != DCE_CACHE_DC)
{
pDce->DCXFlags = DCX_DCEBUSY;
if (Window)
{
if (Window->Style & WS_CLIPCHILDREN)
{
pDce->DCXFlags |= DCX_CLIPCHILDREN;
}
if (Window->Style & WS_CLIPSIBLINGS)
{
pDce->DCXFlags |= DCX_CLIPSIBLINGS;
}
}
}
else
{
pDce->DCXFlags = DCX_CACHE | DCX_DCEEMPTY;
}
return(pDce);
}
VOID static STDCALL
DceSetDrawable(PWINDOW_OBJECT Window OPTIONAL, HDC hDC, ULONG Flags,
BOOL SetClipOrigin)
{
DC *dc = DC_LockDc(hDC);
if(!dc)
return;
if (Window == NULL)
{
dc->w.DCOrgX = 0;
dc->w.DCOrgY = 0;
}
else
{
if (Flags & DCX_WINDOW)
{
dc->w.DCOrgX = Window->WindowRect.left;
dc->w.DCOrgY = Window->WindowRect.top;
}
else
{
dc->w.DCOrgX = Window->ClientRect.left;
dc->w.DCOrgY = Window->ClientRect.top;
}
}
DC_UnlockDc(dc);
}
static VOID FASTCALL
DceDeleteClipRgn(DCE* Dce)
{
Dce->DCXFlags &= ~(DCX_EXCLUDERGN | DCX_INTERSECTRGN);
if (Dce->DCXFlags & DCX_KEEPCLIPRGN )
{
Dce->DCXFlags &= ~DCX_KEEPCLIPRGN;
}
else if (Dce->hClipRgn != NULL)
{
NtGdiDeleteObject(Dce->hClipRgn);
}
Dce->hClipRgn = NULL;
/* make it dirty so that the vis rgn gets recomputed next time */
Dce->DCXFlags |= DCX_DCEDIRTY;
}
static INT FASTCALL
DceReleaseDC(DCE* dce, BOOL EndPaint)
{
if (DCX_DCEBUSY != (dce->DCXFlags & (DCX_DCEEMPTY | DCX_DCEBUSY)))
{
return 0;
}
/* restore previous visible region */
if ((dce->DCXFlags & (DCX_INTERSECTRGN | DCX_EXCLUDERGN)) &&
((dce->DCXFlags & DCX_CACHE) || EndPaint))
{
DceDeleteClipRgn(dce);
}
if (dce->DCXFlags & DCX_CACHE)
{
/* make the DC clean so that SetDCState doesn't try to update the vis rgn */
IntGdiSetHookFlags(dce->hDC, DCHF_VALIDATEVISRGN);
if( dce->pProcess ) // Attempt to fix Dc_Attr problem.
DC_SetOwnership( defaultDCstate, dce->pProcess);
else
DC_SetOwnership( defaultDCstate, PsGetCurrentProcess());
IntGdiSetDCState(dce->hDC, defaultDCstate);
DC_SetOwnership( defaultDCstate, NULL); // Return default dc state to inaccessible mode.
dce->DCXFlags &= ~DCX_DCEBUSY;
if (dce->DCXFlags & DCX_DCEDIRTY)
{
/* don't keep around invalidated entries
* because SetDCState() disables hVisRgn updates
* by removing dirty bit. */
dce->hwndCurrent = 0;
dce->DCXFlags &= DCX_CACHE;
dce->DCXFlags |= DCX_DCEEMPTY;
}
}
return 1;
}
static VOID FASTCALL
DceUpdateVisRgn(DCE *Dce, PWINDOW_OBJECT Window, ULONG Flags)
{
HANDLE hRgnVisible = NULL;
ULONG DcxFlags;
PWINDOW_OBJECT DesktopWindow;
if (Flags & DCX_PARENTCLIP)
{
PWINDOW_OBJECT Parent;
Parent = Window->Parent;
if(!Parent)
{
hRgnVisible = NULL;
goto noparent;
}
if (Parent->Style & WS_CLIPSIBLINGS)
{
DcxFlags = DCX_CLIPSIBLINGS |
(Flags & ~(DCX_CLIPCHILDREN | DCX_WINDOW));
}
else
{
DcxFlags = Flags & ~(DCX_CLIPSIBLINGS | DCX_CLIPCHILDREN | DCX_WINDOW);
}
hRgnVisible = DceGetVisRgn(Parent, DcxFlags, Window->hSelf, Flags);
}
else if (Window == NULL)
{
DesktopWindow = UserGetWindowObject(IntGetDesktopWindow());
if (NULL != DesktopWindow)
{
hRgnVisible = UnsafeIntCreateRectRgnIndirect(&DesktopWindow->WindowRect);
}
else
{
hRgnVisible = NULL;
}
}
else
{
hRgnVisible = DceGetVisRgn(Window, Flags, 0, 0);
}
noparent:
if (Flags & DCX_INTERSECTRGN)
{
if(Dce->hClipRgn != NULL)
{
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_AND);
}
else
{
if(hRgnVisible != NULL)
{
NtGdiDeleteObject(hRgnVisible);
}
hRgnVisible = NtGdiCreateRectRgn(0, 0, 0, 0);
}
}
if (Flags & DCX_EXCLUDERGN && Dce->hClipRgn != NULL)
{
NtGdiCombineRgn(hRgnVisible, hRgnVisible, Dce->hClipRgn, RGN_DIFF);
}
Dce->DCXFlags &= ~DCX_DCEDIRTY;
IntGdiSelectVisRgn(Dce->hDC, hRgnVisible);
if (Window != NULL)
{
IntEngWindowChanged(Window, WOC_RGN_CLIENT);
}
if (hRgnVisible != NULL)
{
NtGdiDeleteObject(hRgnVisible);
}
}
HDC FASTCALL
UserGetDCEx(PWINDOW_OBJECT Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
{
PWINDOW_OBJECT Parent;
ULONG DcxFlags;
DCE* Dce;
BOOL UpdateVisRgn = TRUE;
BOOL UpdateClipOrigin = FALSE;
if (NULL == Window)
{
Flags &= ~DCX_USESTYLE;
}
if (NULL == Window || NULL == Window->Dce)
{
Flags |= DCX_CACHE;
}
if (Flags & DCX_USESTYLE)
{
Flags &= ~(DCX_CLIPCHILDREN | DCX_CLIPSIBLINGS | DCX_PARENTCLIP);
if (Window->Style & WS_CLIPSIBLINGS)
{
Flags |= DCX_CLIPSIBLINGS;
}
if (!(Flags & DCX_WINDOW))
{
if (Window->Class->Style & CS_PARENTDC)
{
Flags |= DCX_PARENTCLIP;
}
if (Window->Style & WS_CLIPCHILDREN &&
!(Window->Style & WS_MINIMIZE))
{
Flags |= DCX_CLIPCHILDREN;
}
}
else
{
Flags |= DCX_CACHE;
}
}
if (Flags & DCX_NOCLIPCHILDREN)
{
Flags |= DCX_CACHE;
Flags |= ~(DCX_PARENTCLIP | DCX_CLIPCHILDREN);
}
if (Flags & DCX_WINDOW)
{
Flags = (Flags & ~DCX_CLIPCHILDREN) | DCX_CACHE;
}
Parent = (Window ? Window->Parent : NULL);
if (NULL == Window || !(Window->Style & WS_CHILD) || NULL == Parent)
{
Flags &= ~DCX_PARENTCLIP;
}
else if (Flags & DCX_PARENTCLIP)
{
Flags |= DCX_CACHE;
if ((Window->Style & WS_VISIBLE) &&
(Parent->Style & WS_VISIBLE))
{
Flags &= ~DCX_CLIPCHILDREN;
if (Parent->Style & WS_CLIPSIBLINGS)
{
Flags |= DCX_CLIPSIBLINGS;
}
}
}
DcxFlags = Flags & DCX_CACHECOMPAREMASK;
if (Flags & DCX_CACHE)
{
DCE* DceEmpty = NULL;
DCE* DceUnused = NULL;
KeEnterCriticalRegion();
for (Dce = FirstDce; Dce != NULL; Dce = Dce->next)
{
if ((Dce->DCXFlags & (DCX_CACHE | DCX_DCEBUSY)) == DCX_CACHE)
{
DceUnused = Dce;
if (Dce->DCXFlags & DCX_DCEEMPTY)
{
DceEmpty = Dce;
}
else if (Dce->hwndCurrent == (Window ? Window->hSelf : NULL) &&
((Dce->DCXFlags & DCX_CACHECOMPAREMASK) == DcxFlags))
{
#if 0 /* FIXME */
UpdateVisRgn = FALSE;
#endif
UpdateClipOrigin = TRUE;
break;
}
}
}
KeLeaveCriticalRegion();
if (Dce == NULL)
{
Dce = (DceEmpty == NULL) ? DceUnused : DceEmpty;
}
if (Dce == NULL)
{
Dce = DceAllocDCE(NULL, DCE_CACHE_DC);
}
}
else
{
Dce = Window->Dce;
if (NULL != Dce && Dce->hwndCurrent == (Window ? Window->hSelf : NULL))
{
UpdateVisRgn = FALSE; /* updated automatically, via DCHook() */
}
#if 1 /* FIXME */
UpdateVisRgn = TRUE;
#endif
}
if (NULL == Dce)
{
return(NULL);
}
Dce->hwndCurrent = (Window ? Window->hSelf : NULL);
Dce->DCXFlags = Flags | DCX_DCEBUSY;
if (0 == (Flags & (DCX_EXCLUDERGN | DCX_INTERSECTRGN)) && NULL != ClipRegion)
{
if (Flags & DCX_KEEPCLIPRGN)
NtGdiDeleteObject(ClipRegion);
ClipRegion = NULL;
}
#if 0
if (NULL != Dce->hClipRgn)
{
DceDeleteClipRgn(Dce);
Dce->hClipRgn = NULL;
}
#endif
if (0 != (Flags & DCX_INTERSECTUPDATE) && NULL == ClipRegion)
{
Flags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN;
Dce->DCXFlags |= DCX_INTERSECTRGN | DCX_KEEPCLIPRGN;
ClipRegion = Window->UpdateRegion;
}
if (ClipRegion == (HRGN) 1)
{
if (!(Flags & DCX_WINDOW))
{
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->ClientRect);
}
else
{
Dce->hClipRgn = UnsafeIntCreateRectRgnIndirect(&Window->WindowRect);
}
}
else if (ClipRegion != NULL)
{
Dce->hClipRgn = ClipRegion;
}
DceSetDrawable(Window, Dce->hDC, Flags, UpdateClipOrigin);
// if (UpdateVisRgn)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -