⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 winpos.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *  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 + -