📄 winpos.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: winpos.c 27763 2007-07-20 22:59:21Z tkreuzer $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Windows
* FILE: subsys/win32k/ntuser/window.c
* PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISION HISTORY:
* 06-06-2001 CSH NtGdid
*/
/* INCLUDES ******************************************************************/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
VOID FASTCALL
co_IntPaintWindows(PWINDOW_OBJECT Window, ULONG Flags, BOOL Recurse);
BOOL FASTCALL
IntValidateParent(PWINDOW_OBJECT Child, HRGN hValidateRgn, BOOL Recurse);
/* GLOBALS *******************************************************************/
#define MINMAX_NOSWP (0x00010000)
#define SWP_EX_NOCOPY 0x0001
#define SWP_EX_PAINTSELF 0x0002
#define SWP_AGG_NOGEOMETRYCHANGE \
(SWP_NOSIZE | SWP_NOMOVE | SWP_NOCLIENTSIZE | SWP_NOCLIENTMOVE)
#define SWP_AGG_NOPOSCHANGE \
(SWP_AGG_NOGEOMETRYCHANGE | SWP_NOZORDER)
#define SWP_AGG_STATUSFLAGS \
(SWP_AGG_NOPOSCHANGE | SWP_FRAMECHANGED | SWP_HIDEWINDOW | SWP_SHOWWINDOW)
/* FUNCTIONS *****************************************************************/
BOOL FASTCALL
IntGetClientOrigin(PWINDOW_OBJECT Window OPTIONAL, LPPOINT Point)
{
Window = Window ? Window : UserGetWindowObject(IntGetDesktopWindow());
if (Window == NULL)
{
Point->x = Point->y = 0;
return FALSE;
}
Point->x = Window->ClientRect.left;
Point->y = Window->ClientRect.top;
return TRUE;
}
BOOL FASTCALL
UserGetClientOrigin(PWINDOW_OBJECT Window, LPPOINT Point)
{
BOOL Ret;
POINT pt;
NTSTATUS Status;
if(!Point)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
Ret = IntGetClientOrigin(Window, &pt);
if(!Ret)
{
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
Status = MmCopyToCaller(Point, &pt, sizeof(POINT));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
return FALSE;
}
return Ret;
}
BOOL STDCALL
NtUserGetClientOrigin(HWND hWnd, LPPOINT Point)
{
DECLARE_RETURN(BOOL);
PWINDOW_OBJECT Window;
DPRINT("Enter NtUserGetClientOrigin\n");
UserEnterShared();
if (!(Window = UserGetWindowObject(hWnd)))
RETURN(FALSE);
RETURN(UserGetClientOrigin(Window, Point));
CLEANUP:
DPRINT("Leave NtUserGetClientOrigin, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
}
/*******************************************************************
* can_activate_window
*
* Check if we can activate the specified window.
*/
static
BOOL FASTCALL can_activate_window( PWINDOW_OBJECT Wnd OPTIONAL)
{
LONG style;
if (!Wnd) return FALSE;
style = Wnd->Style;
if (!(style & WS_VISIBLE) &&
Wnd->OwnerThread->ThreadsProcess != CsrProcess) return FALSE;
if ((style & (WS_POPUP|WS_CHILD)) == WS_CHILD) return FALSE;
return !(style & WS_DISABLED);
}
/*******************************************************************
* WinPosActivateOtherWindow
*
* Activates window other than pWnd.
*/
VOID FASTCALL
co_WinPosActivateOtherWindow(PWINDOW_OBJECT Window)
{
PWINDOW_OBJECT WndTo = NULL;
HWND Fg;
USER_REFERENCE_ENTRY Ref;
ASSERT_REFS_CO(Window);
if (IntIsDesktopWindow(Window))
{
IntSetFocusMessageQueue(NULL);
return;
}
/* If this is popup window, try to activate the owner first. */
if ((Window->Style & WS_POPUP) && (WndTo = IntGetOwner(Window)))
{
WndTo = UserGetAncestor( WndTo, GA_ROOT );
if (can_activate_window(WndTo)) goto done;
}
/* Pick a next top-level window. */
/* FIXME: Search for non-tooltip windows first. */
WndTo = Window;
for (;;)
{
if (!(WndTo = WndTo->NextSibling)) break;
if (can_activate_window( WndTo )) break;
}
done:
if (WndTo) UserRefObjectCo(WndTo, &Ref);
Fg = UserGetForegroundWindow();
if ((!Fg || Window->hSelf == Fg) && WndTo)//fixme: ok if WndTo is NULL??
{
/* fixme: wine can pass WndTo=NULL to co_IntSetForegroundWindow. hmm */
if (co_IntSetForegroundWindow(WndTo))
{
UserDerefObjectCo(WndTo);
return;
}
}
if (!co_IntSetActiveWindow(WndTo)) /* ok for WndTo to be NULL here */
co_IntSetActiveWindow(0);
if (WndTo) UserDerefObjectCo(WndTo);
}
UINT
FASTCALL
co_WinPosArrangeIconicWindows(PWINDOW_OBJECT parent)
{
RECT rectParent;
INT i, x, y, xspacing, yspacing;
HWND *List = IntWinListChildren(parent);
ASSERT_REFS_CO(parent);
IntGetClientRect( parent, &rectParent );
x = rectParent.left;
y = rectParent.bottom;
xspacing = UserGetSystemMetrics(SM_CXMINSPACING);
yspacing = UserGetSystemMetrics(SM_CYMINSPACING);
DPRINT("X:%d Y:%d XS:%d YS:%d\n",x,y,xspacing,yspacing);
for( i = 0; List[i]; i++)
{
PWINDOW_OBJECT WndChild;
if (!(WndChild = UserGetWindowObject(List[i])))
continue;
if((WndChild->Style & WS_MINIMIZE) != 0 )
{
USER_REFERENCE_ENTRY Ref;
UserRefObjectCo(WndChild, &Ref);
co_WinPosSetWindowPos(WndChild, 0, x + UserGetSystemMetrics(SM_CXBORDER),
y - yspacing - UserGetSystemMetrics(SM_CYBORDER)
, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );
UserDerefObjectCo(WndChild);
if (x <= rectParent.right - xspacing)
x += xspacing;
else
{
x = rectParent.left;
y -= yspacing;
}
}
}
ExFreePool(List);
return yspacing;
}
VOID static FASTCALL
WinPosFindIconPos(PWINDOW_OBJECT Window, POINT *Pos)
{
/* FIXME */
}
PINTERNALPOS FASTCALL
WinPosInitInternalPos(PWINDOW_OBJECT Window, POINT *pt, PRECT RestoreRect)
{
PWINDOW_OBJECT Parent;
UINT XInc, YInc;
if (Window->InternalPos == NULL)
{
RECT WorkArea;
PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop; /* Or rather get it from the window? */
Parent = Window->Parent;
if(Parent)
{
if(IntIsDesktopWindow(Parent))
IntGetDesktopWorkArea(Desktop, &WorkArea);
else
WorkArea = Parent->ClientRect;
}
else
IntGetDesktopWorkArea(Desktop, &WorkArea);
Window->InternalPos = ExAllocatePoolWithTag(PagedPool, sizeof(INTERNALPOS), TAG_WININTLIST);
if(!Window->InternalPos)
{
DPRINT1("Failed to allocate INTERNALPOS structure for window 0x%x\n", Window->hSelf);
return NULL;
}
Window->InternalPos->NormalRect = Window->WindowRect;
IntGetWindowBorderMeasures(Window, &XInc, &YInc);
Window->InternalPos->MaxPos.x = WorkArea.left - XInc;
Window->InternalPos->MaxPos.y = WorkArea.top - YInc;
Window->InternalPos->IconPos.x = WorkArea.left;
Window->InternalPos->IconPos.y = WorkArea.bottom - UserGetSystemMetrics(SM_CYMINIMIZED);
}
if (Window->Style & WS_MINIMIZE)
{
Window->InternalPos->IconPos = *pt;
}
else if (Window->Style & WS_MAXIMIZE)
{
Window->InternalPos->MaxPos = *pt;
}
else if (RestoreRect != NULL)
{
Window->InternalPos->NormalRect = *RestoreRect;
}
return(Window->InternalPos);
}
UINT FASTCALL
co_WinPosMinMaximize(PWINDOW_OBJECT Window, UINT ShowFlag, RECT* NewPos)
{
POINT Size;
PINTERNALPOS InternalPos;
UINT SwpFlags = 0;
ASSERT_REFS_CO(Window);
Size.x = Window->WindowRect.left;
Size.y = Window->WindowRect.top;
InternalPos = WinPosInitInternalPos(Window, &Size, &Window->WindowRect);
if (InternalPos)
{
if (Window->Style & WS_MINIMIZE)
{
if (!co_IntSendMessage(Window->hSelf, WM_QUERYOPEN, 0, 0))
{
return(SWP_NOSIZE | SWP_NOMOVE);
}
SwpFlags |= SWP_NOCOPYBITS;
}
switch (ShowFlag)
{
case SW_MINIMIZE:
{
if (Window->Style & WS_MAXIMIZE)
{
Window->Flags |= WINDOWOBJECT_RESTOREMAX;
Window->Style &= ~WS_MAXIMIZE;
}
else
{
Window->Flags &= ~WINDOWOBJECT_RESTOREMAX;
}
co_UserRedrawWindow(Window, NULL, 0, RDW_VALIDATE | RDW_NOERASE |
RDW_NOINTERNALPAINT);
Window->Style |= WS_MINIMIZE;
WinPosFindIconPos(Window, &InternalPos->IconPos);
IntGdiSetRect(NewPos, InternalPos->IconPos.x, InternalPos->IconPos.y,
UserGetSystemMetrics(SM_CXMINIMIZED),
UserGetSystemMetrics(SM_CYMINIMIZED));
SwpFlags |= SWP_NOCOPYBITS;
break;
}
case SW_MAXIMIZE:
{
co_WinPosGetMinMaxInfo(Window, &Size, &InternalPos->MaxPos,
NULL, NULL);
DPRINT("Maximize: %d,%d %dx%d\n",
InternalPos->MaxPos.x, InternalPos->MaxPos.y, Size.x, Size.y);
if (Window->Style & WS_MINIMIZE)
{
Window->Style &= ~WS_MINIMIZE;
}
Window->Style |= WS_MAXIMIZE;
IntGdiSetRect(NewPos, InternalPos->MaxPos.x, InternalPos->MaxPos.y,
Size.x, Size.y);
break;
}
case SW_RESTORE:
{
if (Window->Style & WS_MINIMIZE)
{
Window->Style &= ~WS_MINIMIZE;
if (Window->Flags & WINDOWOBJECT_RESTOREMAX)
{
co_WinPosGetMinMaxInfo(Window, &Size,
&InternalPos->MaxPos, NULL, NULL);
Window->Style |= WS_MAXIMIZE;
IntGdiSetRect(NewPos, InternalPos->MaxPos.x,
InternalPos->MaxPos.y, Size.x, Size.y);
break;
}
else
{
*NewPos = InternalPos->NormalRect;
NewPos->right -= NewPos->left;
NewPos->bottom -= NewPos->top;
break;
}
}
else
{
if (!(Window->Style & WS_MAXIMIZE))
{
return 0;
}
Window->Style &= ~WS_MAXIMIZE;
*NewPos = InternalPos->NormalRect;
NewPos->right -= NewPos->left;
NewPos->bottom -= NewPos->top;
break;
}
}
}
}
else
{
SwpFlags |= SWP_NOSIZE | SWP_NOMOVE;
}
return(SwpFlags);
}
static
VOID FASTCALL
WinPosFillMinMaxInfoStruct(PWINDOW_OBJECT Window, MINMAXINFO *Info)
{
UINT XInc, YInc;
RECT WorkArea;
PDESKTOP_OBJECT Desktop = PsGetCurrentThreadWin32Thread()->Desktop; /* Or rather get it from the window? */
IntGetDesktopWorkArea(Desktop, &WorkArea);
/* Get default values. */
Info->ptMinTrackSize.x = UserGetSystemMetrics(SM_CXMINTRACK);
Info->ptMinTrackSize.y = UserGetSystemMetrics(SM_CYMINTRACK);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -