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

📄 nonclient.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * ReactOS User32 Library
 * - Window non-client area management
 *
 * Copyright (C) 2003 ReactOS Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; see the file COPYING.LIB.
 * If not, write to the Free Software Foundation,
 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* INCLUDES *******************************************************************/

#include <user32.h>

#include <wine/debug.h>

#define HAS_DLGFRAME(Style, ExStyle) \
            (((ExStyle) & WS_EX_DLGMODALFRAME) || \
            (((Style) & WS_DLGFRAME) && (!((Style) & (WS_THICKFRAME | WS_MINIMIZE)))))

#define HAS_THICKFRAME(Style, ExStyle) \
            (((Style) & WS_THICKFRAME) && !((Style) & WS_MINIMIZE) && \
            (!(((Style) & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)))

#define HAS_THINFRAME(Style, ExStyle) \
            (((Style) & (WS_BORDER | WS_MINIMIZE)) || (!((Style) & (WS_CHILD | WS_POPUP))))

#define HASSIZEGRIP(Style, ExStyle, ParentStyle, WindowRect, ParentClientRect) \
            ((!(Style & WS_CHILD) && (Style & WS_THICKFRAME) && !(Style & WS_MAXIMIZE))  || \
             ((Style & WS_CHILD) && (ParentStyle & WS_THICKFRAME) && !(ParentStyle & WS_MAXIMIZE) && \
             (WindowRect.right - WindowRect.left == ParentClientRect.right) && \
             (WindowRect.bottom - WindowRect.top == ParentClientRect.bottom)))

#ifndef STATE_SYSTEM_OFFSCREEN
#define STATE_SYSTEM_OFFSCREEN	0x00010000
#endif

/*
 * FIXME: This should be moved to a header
 */
VOID
IntDrawScrollBar(HWND hWnd, HDC hDC, INT nBar);
DWORD
IntScrollHitTest(HWND hWnd, INT nBar, POINT pt, BOOL bDragging);
HPEN STDCALL
GetSysColorPen(int nIndex);

BOOL STDCALL GdiGradientFill(HDC,PTRIVERTEX,ULONG,PVOID,ULONG,ULONG);

extern ATOM AtomInternalPos;

/* PRIVATE FUNCTIONS **********************************************************/

BOOL
IntIsScrollBarVisible(HWND hWnd, INT hBar)
{
  SCROLLBARINFO sbi;
  sbi.cbSize = sizeof(SCROLLBARINFO);
  if(!NtUserGetScrollBarInfo(hWnd, hBar, &sbi))
    return FALSE;

  return !(sbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN);
}

BOOL
UserHasWindowEdge(DWORD Style, DWORD ExStyle)
{
   if (Style & WS_MINIMIZE)
      return TRUE;
   if (ExStyle & WS_EX_DLGMODALFRAME)
      return TRUE;
   if (ExStyle & WS_EX_STATICEDGE)
      return FALSE;
   if (Style & WS_THICKFRAME)
      return TRUE;
   Style &= WS_CAPTION;
   if (Style == WS_DLGFRAME || Style == WS_CAPTION)
      return TRUE;
   return FALSE;
}

VOID
UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
{
   DWORD Border = 0;

   if (UserHasWindowEdge(Style, ExStyle))
      Border += 2;
   else if (ExStyle & WS_EX_STATICEDGE)
      Border += 1;
   if ((ExStyle & WS_EX_CLIENTEDGE) && WithClient)
      Border += 2;
   if (Style & WS_CAPTION || ExStyle & WS_EX_DLGMODALFRAME)
      Border ++;
   Size->cx = Size->cy = Border;
   if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
   {
      Size->cx += GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME);
      Size->cy += GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME);
   }
   Size->cx *= GetSystemMetrics(SM_CXBORDER);
   Size->cy *= GetSystemMetrics(SM_CYBORDER);
}

BOOL
UserHasMenu(HWND hWnd, ULONG Style)
{
   return (!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
}

HICON
UserGetWindowIcon(HWND hwnd)
{
   HICON hIcon = 0;

   SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL2, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon);

   if (!hIcon)
      SendMessageTimeout(hwnd, WM_GETICON, ICON_SMALL, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon);

   if (!hIcon)
      SendMessageTimeout(hwnd, WM_GETICON, ICON_BIG, 0, SMTO_ABORTIFHUNG, 1000, (LPDWORD)&hIcon);

   if (!hIcon)
      hIcon = (HICON)GetClassLong(hwnd, GCL_HICONSM);

   if (!hIcon)
      hIcon = (HICON)GetClassLong(hwnd, GCL_HICON);

   return hIcon;
}

BOOL
UserDrawSysMenuButton(HWND hWnd, HDC hDC, LPRECT Rect, BOOL Down)
{
   HICON WindowIcon;

   if ((WindowIcon = UserGetWindowIcon(hWnd)))
   {
      return DrawIconEx(hDC, Rect->left + 2, Rect->top + 2, WindowIcon,
                        GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON),
                        0, NULL, DI_NORMAL);
   }

   return FALSE;
}

/*
 * FIXME:
 * - Cache bitmaps, then just bitblt instead of calling DFC() (and
 *   wasting precious CPU cycles) every time
 * - Center the buttons verticaly in the rect
 */
VOID
UserDrawCaptionButton(LPRECT Rect, DWORD Style, DWORD ExStyle, HDC hDC, BOOL bDown, ULONG Type)
{
   RECT TempRect;

   if (!(Style & WS_SYSMENU))
   {
      return;
   }

   TempRect = *Rect;

   switch (Type)
   {
      case DFCS_CAPTIONMIN:
      {
         if (ExStyle & WS_EX_TOOLWINDOW)
            return; /* ToolWindows don't have min/max buttons */

         if (Style & WS_SYSMENU)
             TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
         if (Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
             TempRect.right -= GetSystemMetrics(SM_CXSIZE) - 2;
         TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
         TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
         TempRect.top += 2;
         TempRect.right -= 1;

         DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
                          ((Style & WS_MINIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMIN) |
                          (bDown ? DFCS_PUSHED : 0) |
                          ((Style & WS_MINIMIZEBOX) ? 0 : DFCS_INACTIVE));
         break;
      }
      case DFCS_CAPTIONMAX:
      {
         if (ExStyle & WS_EX_TOOLWINDOW)
             return; /* ToolWindows don't have min/max buttons */

         if (Style & WS_SYSMENU)
             TempRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
         TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE) + 1;
         TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
         TempRect.top += 2;
         TempRect.right -= 1;

         DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
                          ((Style & WS_MAXIMIZE) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
                          (bDown ? DFCS_PUSHED : 0) |
                          ((Style & WS_MAXIMIZEBOX) ? 0 : DFCS_INACTIVE));
         break;
      }
      case DFCS_CAPTIONCLOSE:
      {
         /* FIXME: A tool window has a smaller Close button */

         if (ExStyle & WS_EX_TOOLWINDOW)
         {
            TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSMSIZE);
            TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMSIZE) - 2;
         }
         else
         {
            TempRect.left = TempRect.right - GetSystemMetrics(SM_CXSIZE);
            TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSIZE) - 2;
         }
         TempRect.top += 2;
         TempRect.right -= 2;

         DrawFrameControl(hDC, &TempRect, DFC_CAPTION,
                          (DFCS_CAPTIONCLOSE | (bDown ? DFCS_PUSHED : 0) |
                          ((Style & WS_SYSMENU) ? 0 : DFCS_INACTIVE)));
         break;
      }
   }
}

VOID
UserDrawCaptionButtonWnd(HWND hWnd, HDC hDC, BOOL bDown, ULONG Type)
{
   RECT WindowRect;
   SIZE WindowBorder;
   DWORD Style, ExStyle;

   GetWindowRect(hWnd, &WindowRect);
   WindowRect.right -= WindowRect.left;
   WindowRect.bottom -= WindowRect.top;
   WindowRect.left = WindowRect.top = 0;
   Style = GetWindowLongW(hWnd, GWL_STYLE);
   ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
   UserGetWindowBorders(Style, ExStyle, &WindowBorder, FALSE);
   InflateRect(&WindowRect, -WindowBorder.cx, -WindowBorder.cy);
   UserDrawCaptionButton(&WindowRect, Style, ExStyle, hDC, bDown, Type);
}

/*
 * FIXME:
 * - Drawing of WS_BORDER after scrollbars
 * - Correct drawing of size-box
 */
LRESULT
DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active)
{
   HDC hDC;
   DWORD Style, ExStyle;
   HWND Parent;
   RECT ClientRect, WindowRect, CurrentRect, TempRect;

   if (!IsWindowVisible(hWnd))
      return 0;

   Style = GetWindowLongW(hWnd, GWL_STYLE);

   hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | 0x10000);
   if (hDC == 0)
   {
      return 0;
   }

   Parent = GetParent(hWnd);
   ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
   if (Active == -1)
   {
      if (ExStyle & WS_EX_MDICHILD)
      {
         Active = IsChild(GetForegroundWindow(), hWnd);
         if (Active)
            Active = (hWnd == (HWND)SendMessageW(Parent, WM_MDIGETACTIVE, 0, 0));
      }
      else
      {
         Active = (GetForegroundWindow() == hWnd);
      }
   }
   GetWindowRect(hWnd, &WindowRect);
   GetClientRect(hWnd, &ClientRect);

   CurrentRect.top = CurrentRect.left = 0;
   CurrentRect.right = WindowRect.right - WindowRect.left;
   CurrentRect.bottom = WindowRect.bottom - WindowRect.top;

   /* Draw outer edge */
   if (UserHasWindowEdge(Style, ExStyle))
   {
      DrawEdge(hDC, &CurrentRect, EDGE_RAISED, BF_RECT | BF_ADJUST);
   } else
   if (ExStyle & WS_EX_STATICEDGE)
   {
#if 0
      DrawEdge(hDC, &CurrentRect, BDR_SUNKENINNER, BF_RECT | BF_ADJUST | BF_FLAT);
#else
      SelectObject(hDC, GetSysColorBrush(COLOR_BTNSHADOW));
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, 1, PATCOPY);
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);

      SelectObject(hDC, GetSysColorBrush(COLOR_BTNHIGHLIGHT));
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, 1, PATCOPY);
      PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, 1, CurrentRect.bottom - CurrentRect.top, PATCOPY);

      InflateRect(&CurrentRect, -1, -1);
#endif
   }

   /* Firstly the "thick" frame */
   if ((Style & WS_THICKFRAME) && !(Style & WS_MINIMIZE))
   {
      DWORD Width =
         (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
         GetSystemMetrics(SM_CXBORDER);
      DWORD Height =
         (GetSystemMetrics(SM_CYFRAME) - GetSystemMetrics(SM_CYDLGFRAME)) *
         GetSystemMetrics(SM_CYBORDER);

      SelectObject(hDC, GetSysColorBrush(Active ? COLOR_ACTIVEBORDER :
         COLOR_INACTIVEBORDER));

      /* Draw frame */
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#ifdef __REACTOS__
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#else
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#endif

      InflateRect(&CurrentRect, -Width, -Height);
   }

   /* Now the other bit of the frame */
   if (Style & (WS_DLGFRAME | WS_BORDER) || ExStyle & WS_EX_DLGMODALFRAME)
   {
      DWORD Width = GetSystemMetrics(SM_CXBORDER);
      DWORD Height = GetSystemMetrics(SM_CYBORDER);

      SelectObject(hDC, GetSysColorBrush(
         (ExStyle & (WS_EX_DLGMODALFRAME | WS_EX_CLIENTEDGE)) ? COLOR_3DFACE :
         (ExStyle & WS_EX_STATICEDGE) ? COLOR_WINDOWFRAME :
         (Style & (WS_DLGFRAME | WS_THICKFRAME)) ? COLOR_3DFACE :
         COLOR_WINDOWFRAME));

      /* Draw frame */
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, CurrentRect.right - CurrentRect.left, Height, PATCOPY);
      PatBlt(hDC, CurrentRect.left, CurrentRect.top, Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#ifdef __REACTOS__
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom - 1, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right - 1, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#else
      PatBlt(hDC, CurrentRect.left, CurrentRect.bottom, CurrentRect.right - CurrentRect.left, -Height, PATCOPY);
      PatBlt(hDC, CurrentRect.right, CurrentRect.top, -Width, CurrentRect.bottom - CurrentRect.top, PATCOPY);
#endif

      InflateRect(&CurrentRect, -Width, -Height);
   }

   /* Draw caption */
   if ((Style & WS_CAPTION) == WS_CAPTION)
   {
      DWORD CaptionFlags = DC_ICON | DC_TEXT | DC_BUTTONS;
      HPEN PreviousPen;
      BOOL Gradient = FALSE;

      if(SystemParametersInfoW(SPI_GETGRADIENTCAPTIONS, 0, &Gradient, 0) && Gradient)
      {
        CaptionFlags |= DC_GRADIENT;
      }

      TempRect = CurrentRect;

      if (Active)
      {
         CaptionFlags |= DC_ACTIVE;
      }

      if (ExStyle & WS_EX_TOOLWINDOW)
      {
         CaptionFlags |= DC_SMALLCAP;
         TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYSMCAPTION) - 1;
         CurrentRect.top += GetSystemMetrics(SM_CYSMCAPTION);
      }
      else
      {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -