📄 nonclient.c
字号:
/*
* 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 + -