* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-/* INCLUDES *******************************************************************/
-
#include <user32.h>
-#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
-#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);
-
-BOOL WINAPI 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)
{
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, (PDWORD_PTR)&hIcon);
-
- if (!hIcon) hIcon = UserGetProp(hwnd, gpsi->atomIconSmProp);
- if (!hIcon) hIcon = UserGetProp(hwnd, gpsi->atomIconProp);
- if (!hIcon) hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICONSM);
- if (!hIcon) hIcon = (HICON)GetClassLongPtr(hwnd, GCL_HICON);
- if (!hIcon && (GetWindowLongW( hwnd, GWL_STYLE ) & DS_MODALFRAME))
- {
- if (!hIcon) hIcon = gpsi->hIconSmWindows; // Both are IDI_WINLOGO Small
- if (!hIcon) hIcon = gpsi->hIconWindows; // Reg size.
- }
- 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(HWND hWnd, 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:
- {
- HMENU hSysMenu = GetSystemMenu(hWnd, FALSE);
- UINT MenuState = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); /* in case of error MenuState==0xFFFFFFFF */
-
- /* 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) |
- ((!(MenuState & (MF_GRAYED|MF_DISABLED)) && !(GetClassLong(hWnd, GCL_STYLE) & CS_NOCLOSE)) ? 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 = GetWindowLongPtrW(hWnd, GWL_STYLE);
- ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
- UserGetWindowBorders(Style, ExStyle, &WindowBorder, FALSE);
- InflateRect(&WindowRect, -WindowBorder.cx, -WindowBorder.cy);
- UserDrawCaptionButton(hWnd, &WindowRect, Style, ExStyle, hDC, bDown, Type);
-}
-
-// Note from Wine:
-/* MSDN docs are pretty idiotic here, they say app CAN use clipRgn in
- the call to GetDCEx implying that it is allowed not to use it either.
- However, the suggested GetDCEx( , DCX_WINDOW | DCX_INTERSECTRGN)
- will cause clipRgn to be deleted after ReleaseDC().
- Now, how is the "system" supposed to tell what happened?
- */
/*
- * FIXME:
- * - Drawing of WS_BORDER after scrollbars
- * - Correct drawing of size-box
+ RealUserDrawCaption: This function is passed through RegisterUserApiHook to uxtheme
+ to call it when the classic caption is needed to be drawn.
*/
-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 = GetWindowLongPtrW(hWnd, GWL_STYLE);
-
- TRACE("DefWndNCPaint: hWnd %p, hRgn %p, Active %s.\n",
- hWnd, hRgn, Active ? "TRUE" : "FALSE");
-
- hDC = GetDCEx(hWnd, hRgn, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);
- if (hDC == 0)
- {
- ERR("hDC is NULL!\n");
- if (hRgn != HRGN_WINDOW)
- DeleteObject(hRgn);
- return 0;
- }
-
- Parent = GetParent(hWnd);
- ExStyle = GetWindowLongPtrW(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))
- {
- LONG Width =
- (GetSystemMetrics(SM_CXFRAME) - GetSystemMetrics(SM_CXDLGFRAME)) *
- GetSystemMetrics(SM_CXBORDER);
- LONG 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
- {
- TempRect.bottom = TempRect.top + GetSystemMetrics(SM_CYCAPTION) - 1;
- CurrentRect.top += GetSystemMetrics(SM_CYCAPTION);
- }
-
- NtUserDrawCaption(hWnd, hDC, &TempRect, CaptionFlags);
-
- /* Draw buttons */
- if (Style & WS_SYSMENU)
- {
- UserDrawCaptionButton(hWnd, &TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONCLOSE);
- if ((Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX)) && !(ExStyle & WS_EX_TOOLWINDOW))
- {
- UserDrawCaptionButton(hWnd, &TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMIN);
- UserDrawCaptionButton(hWnd, &TempRect, Style, ExStyle, hDC, FALSE, DFCS_CAPTIONMAX);
- }
- }
- if(!(Style & WS_MINIMIZE))
- {
- /* Line under caption */
- PreviousPen = SelectObject(hDC, GetStockObject(DC_PEN));
- SetDCPenColor(hDC, GetSysColor(
- ((ExStyle & (WS_EX_STATICEDGE | WS_EX_CLIENTEDGE |
- WS_EX_DLGMODALFRAME)) == WS_EX_STATICEDGE) ?
- COLOR_WINDOWFRAME : COLOR_3DFACE));
- MoveToEx(hDC, TempRect.left, TempRect.bottom, NULL);
- LineTo(hDC, TempRect.right, TempRect.bottom);
- SelectObject(hDC, PreviousPen);
- }
- }
-
- if(!(Style & WS_MINIMIZE))
- {
- HMENU menu = GetMenu(hWnd);
- /* Draw menu bar */
- if (menu && !(Style & WS_CHILD))
- {
- TempRect = CurrentRect;
- TempRect.bottom = TempRect.top + (UINT)NtUserxSetMenuBarHeight(menu, 0);
- CurrentRect.top += MenuDrawMenuBar(hDC, &TempRect, hWnd, FALSE);
- }
-
- if (ExStyle & WS_EX_CLIENTEDGE)
- {
- DrawEdge(hDC, &CurrentRect, EDGE_SUNKEN, BF_RECT | BF_ADJUST);
- }
-
- /* Draw the scrollbars */
- if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
- IntIsScrollBarVisible(hWnd, OBJID_VSCROLL) && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
- {
- RECT ParentClientRect;
-
- TempRect = CurrentRect;
- if (ExStyle & WS_EX_LEFTSCROLLBAR)
- TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
- else
- TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
- TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
- FillRect(hDC, &TempRect, GetSysColorBrush(COLOR_BTNFACE));
- /* FIXME: Correct drawing of size-box with WS_EX_LEFTSCROLLBAR */
- if(Parent)
- GetClientRect(Parent, &ParentClientRect);
- if (HASSIZEGRIP(Style, ExStyle, GetWindowLongPtrW(Parent, GWL_STYLE), WindowRect, ParentClientRect))
- {
- DrawFrameControl(hDC, &TempRect, DFC_SCROLL, DFCS_SCROLLSIZEGRIP);
- }
- IntDrawScrollBar(hWnd, hDC, SB_VERT);
- IntDrawScrollBar(hWnd, hDC, SB_HORZ);
- }
- else
- {
- if (Style & WS_VSCROLL && IntIsScrollBarVisible(hWnd, OBJID_VSCROLL))
- IntDrawScrollBar(hWnd, hDC, SB_VERT);
- else if (Style & WS_HSCROLL && IntIsScrollBarVisible(hWnd, OBJID_HSCROLL))
- IntDrawScrollBar(hWnd, hDC, SB_HORZ);
- }
- }
-
- ReleaseDC(hWnd, hDC);
- if (hRgn != HRGN_WINDOW)
- DeleteObject(hRgn); // We use DCX_KEEPCLIPRGN
-
- return 0; // For WM_NCPAINT message, return 0.
-}
-
-LRESULT
-DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect)
-{
- LRESULT Result = 0;
- DWORD Style = GetClassLongPtrW(hWnd, GCL_STYLE);
- DWORD ExStyle;
- SIZE WindowBorders;
- RECT OrigRect;
-
- if (Rect == NULL)
- {
- return Result;
- }
- OrigRect = *Rect;
-
- if (CalcSizeStruct)
- {
- if (Style & CS_VREDRAW)
- {
- Result |= WVR_VREDRAW;
- }
- if (Style & CS_HREDRAW)
- {
- Result |= WVR_HREDRAW;
- }
- Result |= WVR_VALIDRECTS;
- }
-
- Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
- ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
-
- if (!(Style & WS_MINIMIZE))
- {
- HMENU menu = GetMenu(hWnd);
-
- if (UserHasWindowEdge(Style, ExStyle))
- {
- UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
- InflateRect(Rect, -WindowBorders.cx, -WindowBorders.cy);
- } else
- if ((ExStyle & WS_EX_STATICEDGE) || (Style & WS_BORDER))
- {
- InflateRect(Rect, -1, -1);
- }
-
- if ((Style & WS_CAPTION) == WS_CAPTION)
- {
- if (ExStyle & WS_EX_TOOLWINDOW)
- Rect->top += GetSystemMetrics(SM_CYSMCAPTION);
- else
- Rect->top += GetSystemMetrics(SM_CYCAPTION);
- }
-
- if (menu && !(Style & WS_CHILD))
- {
- HDC hDC = GetWindowDC(hWnd);
- if(hDC)
- {
- RECT CliRect = *Rect;
- CliRect.bottom -= OrigRect.top;
- CliRect.right -= OrigRect.left;
- CliRect.left -= OrigRect.left;
- CliRect.top -= OrigRect.top;
- Rect->top += MenuDrawMenuBar(hDC, &CliRect, hWnd, TRUE);
- ReleaseDC(hWnd, hDC);
- }
- }
-
- if (ExStyle & WS_EX_CLIENTEDGE)
- {
- InflateRect(Rect, -2 * GetSystemMetrics(SM_CXBORDER),
- -2 * GetSystemMetrics(SM_CYBORDER));
- }
-
- if(Style & (WS_VSCROLL | WS_HSCROLL))
- {
- SCROLLBARINFO sbi;
- SETSCROLLBARINFO ssbi;
-
- sbi.cbSize = sizeof(SCROLLBARINFO);
- if((Style & WS_VSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_VSCROLL, &sbi))
- {
- int i;
- LONG sx = Rect->right;
-
- sx -= GetSystemMetrics(SM_CXVSCROLL);
- for(i = 0; i <= CCHILDREN_SCROLLBAR; i++)
- ssbi.rgstate[i] = sbi.rgstate[i];
- if(sx <= Rect->left)
- ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
- else
- ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN;
- NtUserSetScrollBarInfo(hWnd, OBJID_VSCROLL, &ssbi);
- if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN)
- Style &= ~WS_VSCROLL;
- }
- else
- Style &= ~WS_VSCROLL;
-
- if((Style & WS_HSCROLL) && NtUserGetScrollBarInfo(hWnd, OBJID_HSCROLL, &sbi))
- {
- int i;
- LONG sy = Rect->bottom;
-
- sy -= GetSystemMetrics(SM_CYHSCROLL);
- for(i = 0; i <= CCHILDREN_SCROLLBAR; i++)
- ssbi.rgstate[i] = sbi.rgstate[i];
- if(sy <= Rect->top)
- ssbi.rgstate[0] |= STATE_SYSTEM_OFFSCREEN;
- else
- ssbi.rgstate[0] &= ~STATE_SYSTEM_OFFSCREEN;
- NtUserSetScrollBarInfo(hWnd, OBJID_HSCROLL, &ssbi);
- if(ssbi.rgstate[0] & STATE_SYSTEM_OFFSCREEN)
- Style &= ~WS_HSCROLL;
- }
- else
- Style &= ~WS_HSCROLL;
- }
-
- if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL))
- {
- if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
- Rect->left += GetSystemMetrics(SM_CXVSCROLL);
- else
- Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
- Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
- }
- else
- {
- if (Style & WS_VSCROLL)
- {
- if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
- Rect->left += GetSystemMetrics(SM_CXVSCROLL);
- else
- Rect->right -= GetSystemMetrics(SM_CXVSCROLL);
- }
- else if (Style & WS_HSCROLL)
- Rect->bottom -= GetSystemMetrics(SM_CYHSCROLL);
- }
- if (Rect->top > Rect->bottom)
- Rect->bottom = Rect->top;
- if (Rect->left > Rect->right)
- Rect->right = Rect->left;
- }
- else
- {
- Rect->right = Rect->left;
- Rect->bottom = Rect->top;
- }
-
- return Result;
-}
-
-LRESULT
-DefWndNCActivate(HWND hWnd, WPARAM wParam, LPARAM lParam)
-{
- PWND Wnd = ValidateHwnd(hWnd);
-
- if (!Wnd) return 0;
-
- /* Lotus Notes draws menu descriptions in the caption of its main
- * window. When it wants to restore original "system" view, it just
- * sends WM_NCACTIVATE message to itself. Any optimizations here in
- * attempt to minimize redrawings lead to a not restored caption.
- */
- if (wParam)
- NtUserxSetWindowState(Wnd, WNDSACTIVEFRAME);
- else
- NtUserxClearWindowState(Wnd, WNDSACTIVEFRAME);
-
- if (Wnd->state & WNDS_NONCPAINT)
- return 0;
-
- /* This isn't documented but is reproducible in at least XP SP2 and
- * Outlook 2007 depends on it
- */
- // MSDN:
- // If this parameter is set to -1, DefWindowProc does not repaint the
- // nonclient area to reflect the state change.
- if (lParam != -1)
- {
- DefWndNCPaint(hWnd, HRGN_WINDOW, wParam);
- }
- return TRUE;
-}
-
-/*
- * FIXME:
- * - Check the scrollbar handling
- */
-LRESULT
-DefWndNCHitTest(HWND hWnd, POINT Point)
-{
- RECT WindowRect, ClientRect, OrigWndRect;
- POINT ClientPoint;
- SIZE WindowBorders;
- DWORD Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
- DWORD ExStyle = GetWindowLongPtrW(hWnd, GWL_EXSTYLE);
-
- GetWindowRect(hWnd, &WindowRect);
- if (!PtInRect(&WindowRect, Point))
- {
- return HTNOWHERE;
- }
- OrigWndRect = WindowRect;
-
- if (UserHasWindowEdge(Style, ExStyle))
- {
- LONG XSize, YSize;
-
- UserGetWindowBorders(Style, ExStyle, &WindowBorders, FALSE);
- InflateRect(&WindowRect, -WindowBorders.cx, -WindowBorders.cy);
- XSize = GetSystemMetrics(SM_CXSIZE) * GetSystemMetrics(SM_CXBORDER);
- YSize = GetSystemMetrics(SM_CYSIZE) * GetSystemMetrics(SM_CYBORDER);
- if (!PtInRect(&WindowRect, Point))
- {
- BOOL ThickFrame;
-
- ThickFrame = (Style & WS_THICKFRAME);
- if (Point.y < WindowRect.top)
- {
- if(Style & WS_MINIMIZE)
- return HTCAPTION;
- if(!ThickFrame)
- return HTBORDER;
- if (Point.x < (WindowRect.left + XSize))
- return HTTOPLEFT;
- if (Point.x >= (WindowRect.right - XSize))
- return HTTOPRIGHT;
- return HTTOP;
- }
- if (Point.y >= WindowRect.bottom)
- {
- if(Style & WS_MINIMIZE)
- return HTCAPTION;
- if(!ThickFrame)
- return HTBORDER;
- if (Point.x < (WindowRect.left + XSize))
- return HTBOTTOMLEFT;
- if (Point.x >= (WindowRect.right - XSize))
- return HTBOTTOMRIGHT;
- return HTBOTTOM;
- }
- if (Point.x < WindowRect.left)
- {
- if(Style & WS_MINIMIZE)
- return HTCAPTION;
- if(!ThickFrame)
- return HTBORDER;
- if (Point.y < (WindowRect.top + YSize))
- return HTTOPLEFT;
- if (Point.y >= (WindowRect.bottom - YSize))
- return HTBOTTOMLEFT;
- return HTLEFT;
- }
- if (Point.x >= WindowRect.right)
- {
- if(Style & WS_MINIMIZE)
- return HTCAPTION;
- if(!ThickFrame)
- return HTBORDER;
- if (Point.y < (WindowRect.top + YSize))
- return HTTOPRIGHT;
- if (Point.y >= (WindowRect.bottom - YSize))
- return HTBOTTOMRIGHT;
- return HTRIGHT;
- }
- }
- }
- else
- {
- if (ExStyle & WS_EX_STATICEDGE)
- InflateRect(&WindowRect,
- -GetSystemMetrics(SM_CXBORDER),
- -GetSystemMetrics(SM_CYBORDER));
- if (!PtInRect(&WindowRect, Point))
- return HTBORDER;
- }
-
- if ((Style & WS_CAPTION) == WS_CAPTION)
- {
- if (ExStyle & WS_EX_TOOLWINDOW)
- WindowRect.top += GetSystemMetrics(SM_CYSMCAPTION);
- else
- WindowRect.top += GetSystemMetrics(SM_CYCAPTION);
- if (!PtInRect(&WindowRect, Point))
- {
- if (Style & WS_SYSMENU)
- {
- if (ExStyle & WS_EX_TOOLWINDOW)
- {
- WindowRect.right -= GetSystemMetrics(SM_CXSMSIZE);
- }
- else
- {
- if(!(ExStyle & WS_EX_DLGMODALFRAME))
- WindowRect.left += GetSystemMetrics(SM_CXSIZE);
- WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
- }
- }
- if (Point.x < WindowRect.left)
- return HTSYSMENU;
- if (WindowRect.right <= Point.x)
- return HTCLOSE;
- if (Style & WS_MAXIMIZEBOX || Style & WS_MINIMIZEBOX)
- WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
- if (Point.x >= WindowRect.right)
- return HTMAXBUTTON;
- if (Style & WS_MINIMIZEBOX)
- WindowRect.right -= GetSystemMetrics(SM_CXSIZE);
- if (Point.x >= WindowRect.right)
- return HTMINBUTTON;
- return HTCAPTION;
- }
- }
-
- if(!(Style & WS_MINIMIZE))
- {
- ClientPoint = Point;
- ScreenToClient(hWnd, &ClientPoint);
- GetClientRect(hWnd, &ClientRect);
-
- if (PtInRect(&ClientRect, ClientPoint))
- {
- return HTCLIENT;
- }
-
- if (GetMenu(hWnd) && !(Style & WS_CHILD))
- {
- if (Point.x > 0 && Point.x < WindowRect.right && ClientPoint.y < 0)
- return HTMENU;
- }
-
- if (ExStyle & WS_EX_CLIENTEDGE)
- {
- InflateRect(&WindowRect, -2 * GetSystemMetrics(SM_CXBORDER),
- -2 * GetSystemMetrics(SM_CYBORDER));
- }
-
- if ((Style & WS_VSCROLL) && (Style & WS_HSCROLL) &&
- (WindowRect.bottom - WindowRect.top) > GetSystemMetrics(SM_CYHSCROLL))
- {
- RECT ParentRect, TempRect = WindowRect, TempRect2 = WindowRect;
- HWND Parent = GetParent(hWnd);
-
- TempRect.bottom -= GetSystemMetrics(SM_CYHSCROLL);
- if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
- TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
- else
- TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
- if (PtInRect(&TempRect, Point))
- return HTVSCROLL;
-
- TempRect2.top = TempRect2.bottom - GetSystemMetrics(SM_CYHSCROLL);
- if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
- TempRect2.left += GetSystemMetrics(SM_CXVSCROLL);
- else
- TempRect2.right -= GetSystemMetrics(SM_CXVSCROLL);
- if (PtInRect(&TempRect2, Point))
- return HTHSCROLL;
-
- TempRect.top = TempRect2.top;
- TempRect.bottom = TempRect2.bottom;
- if(Parent)
- GetClientRect(Parent, &ParentRect);
- if (PtInRect(&TempRect, Point) && HASSIZEGRIP(Style, ExStyle,
- GetWindowLongPtrW(Parent, GWL_STYLE), OrigWndRect, ParentRect))
- {
- if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
- return HTBOTTOMLEFT;
- else
- return HTBOTTOMRIGHT;
- }
- }
- else
- {
- if (Style & WS_VSCROLL)
- {
- RECT TempRect = WindowRect;
-
- if ((ExStyle & WS_EX_LEFTSCROLLBAR) != 0)
- TempRect.right = TempRect.left + GetSystemMetrics(SM_CXVSCROLL);
- else
- TempRect.left = TempRect.right - GetSystemMetrics(SM_CXVSCROLL);
- if (PtInRect(&TempRect, Point))
- return HTVSCROLL;
- } else
- if (Style & WS_HSCROLL)
- {
- RECT TempRect = WindowRect;
- TempRect.top = TempRect.bottom - GetSystemMetrics(SM_CYHSCROLL);
- if (PtInRect(&TempRect, Point))
- return HTHSCROLL;
- }
- }
- }
-
- return HTNOWHERE;
-}
-
-VOID
-DefWndDoButton(HWND hWnd, WPARAM wParam)
-{
- MSG Msg;
- HDC WindowDC;
- BOOL Pressed = TRUE, OldState;
- WPARAM SCMsg;
- HMENU hSysMenu;
- ULONG ButtonType;
- DWORD Style;
- UINT MenuState;
-
- Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
- switch (wParam)
- {
- case HTCLOSE:
- hSysMenu = GetSystemMenu(hWnd, FALSE);
- MenuState = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND); /* in case of error MenuState==0xFFFFFFFF */
- if (!(Style & WS_SYSMENU) || (MenuState & (MF_GRAYED|MF_DISABLED)) || (GetClassLongPtrW(hWnd, GCL_STYLE) & CS_NOCLOSE))
- return;
- ButtonType = DFCS_CAPTIONCLOSE;
- SCMsg = SC_CLOSE;
- break;
- case HTMINBUTTON:
- if (!(Style & WS_MINIMIZEBOX))
- return;
- ButtonType = DFCS_CAPTIONMIN;
- SCMsg = ((Style & WS_MINIMIZE) ? SC_RESTORE : SC_MINIMIZE);
- break;
- case HTMAXBUTTON:
- if (!(Style & WS_MAXIMIZEBOX))
- return;
- ButtonType = DFCS_CAPTIONMAX;
- SCMsg = ((Style & WS_MAXIMIZE) ? SC_RESTORE : SC_MAXIMIZE);
- break;
-
- default:
- ASSERT(FALSE);
- return;
- }
-
- /*
- * FIXME: Not sure where to do this, but we must flush the pending
- * window updates when someone clicks on the close button and at
- * the same time the window is overlapped with another one. This
- * looks like a good place for now...
- */
- UpdateWindow(hWnd);
-
- WindowDC = GetWindowDC(hWnd);
- UserDrawCaptionButtonWnd(hWnd, WindowDC, TRUE, ButtonType);
-
- SetCapture(hWnd);
-
- for (;;)
- {
- if (GetMessageW(&Msg, 0, WM_MOUSEFIRST, WM_MOUSELAST) <= 0)
- break;
- if (CallMsgFilterW( &Msg, MSGF_MAX )) continue;
-
- if (Msg.message == WM_LBUTTONUP)
- break;
-
- if (Msg.message != WM_MOUSEMOVE)
- continue;
-
- OldState = Pressed;
- Pressed = (DefWndNCHitTest(hWnd, Msg.pt) == wParam);
- if (Pressed != OldState)
- UserDrawCaptionButtonWnd(hWnd, WindowDC, Pressed, ButtonType);
- }
-
- if (Pressed)
- UserDrawCaptionButtonWnd(hWnd, WindowDC, FALSE, ButtonType);
- ReleaseCapture();
- ReleaseDC(hWnd, WindowDC);
- if (Pressed)
- SendMessageW(hWnd, WM_SYSCOMMAND, SCMsg, MAKELONG(Msg.pt.x,Msg.pt.y));
-}
-
-
-LRESULT
-DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
-{
- PWND Wnd = ValidateHwnd(hWnd);
-
- switch (wParam)
- {
- case HTCAPTION:
- {
- HWND hTopWnd = hWnd, parent;
- while(1)
- {
- if ((GetWindowLongW( hTopWnd, GWL_STYLE ) & (WS_POPUP|WS_CHILD)) != WS_CHILD)
- break;
- parent = GetAncestor( hTopWnd, GA_PARENT );
- if (!parent || parent == GetDesktopWindow()) break;
- hTopWnd = parent;
- }
-
- if ( NtUserCallHwndLock(hTopWnd, HWNDLOCK_ROUTINE_SETFOREGROUNDWINDOWMOUSE) ||
- GetActiveWindow() == hTopWnd)
- {
- SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
- }
- break;
- }
- case HTSYSMENU:
- {
- LONG style = GetWindowLongPtrW( hWnd, GWL_STYLE );
- if (style & WS_SYSMENU)
- {
- if( Wnd && !(style & WS_MINIMIZE) )
- {
- RECT rect;
- HDC hDC = GetWindowDC(hWnd);
- UserGetInsideRectNC(Wnd, &rect);
- UserDrawSysMenuButton(hWnd, hDC, &rect, TRUE);
- ReleaseDC( hWnd, hDC );
- }
- SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU, lParam);
- }
- break;
- }
- case HTMENU:
- {
- SendMessageW(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
- break;
- }
- case HTHSCROLL:
- {
- SendMessageW(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
- break;
- }
- case HTVSCROLL:
- {
- SendMessageW(hWnd, WM_SYSCOMMAND, SC_VSCROLL + HTVSCROLL, lParam);
- break;
- }
- case HTMINBUTTON:
- case HTMAXBUTTON:
- case HTCLOSE:
- {
- DefWndDoButton(hWnd, wParam);
- break;
- }
- case HTLEFT:
- case HTRIGHT:
- case HTTOP:
- case HTBOTTOM:
- case HTTOPLEFT:
- case HTTOPRIGHT:
- case HTBOTTOMLEFT:
- case HTBOTTOMRIGHT:
- {
- /* Old comment:
- * "make sure hittest fits into 0xf and doesn't overlap with HTSYSMENU"
- * This was previously done by setting wParam=SC_SIZE + wParam - 2
- */
- /* But that is not what WinNT does. Instead it sends this. This
- * is easy to differentiate from HTSYSMENU, because HTSYSMENU adds
- * SC_MOUSEMENU into wParam.
- */
- SendMessageW(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - (HTLEFT - WMSZ_LEFT), lParam);
- break;
- }
- case HTBORDER:
- break;
- }
- return(0);
-}
-
-
-LRESULT
-DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam)
-{
- ULONG Style;
-
- Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
- switch(wParam)
- {
- case HTCAPTION:
- {
- /* Maximize/Restore the window */
- if((Style & WS_CAPTION) == WS_CAPTION && (Style & WS_MAXIMIZEBOX))
- {
- SendMessageW(hWnd, WM_SYSCOMMAND, ((Style & (WS_MINIMIZE | WS_MAXIMIZE)) ? SC_RESTORE : SC_MAXIMIZE), 0);
- }
- break;
- }
- case HTSYSMENU:
- {
- HMENU hSysMenu = GetSystemMenu(hWnd, FALSE);
- UINT state = GetMenuState(hSysMenu, SC_CLOSE, MF_BYCOMMAND);
-
- /* If the close item of the sysmenu is disabled or not present do nothing */
- if ((state & (MF_DISABLED | MF_GRAYED)) || (state == 0xFFFFFFFF))
- break;
-
- SendMessageW(hWnd, WM_SYSCOMMAND, SC_CLOSE, lParam);
- break;
- }
- default:
- return DefWndNCLButtonDown(hWnd, wParam, lParam);
- }
- return(0);
-}
-
-/***********************************************************************
- * NC_HandleNCRButtonDown
- *
- * Handle a WM_NCRBUTTONDOWN message. Called from DefWindowProc().
- */
-LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
-{
- MSG msg;
- INT hittest = wParam;
-
- switch (hittest)
- {
- case HTCAPTION:
- case HTSYSMENU:
- if (!GetSystemMenu( hwnd, FALSE )) break;
-
- SetCapture( hwnd );
- for (;;)
- {
- if (!GetMessageW( &msg, 0, WM_MOUSEFIRST, WM_MOUSELAST )) break;
- if (CallMsgFilterW( &msg, MSGF_MAX )) continue;
- if (msg.message == WM_RBUTTONUP)
- {
- hittest = DefWndNCHitTest( hwnd, msg.pt );
- break;
- }
- if (hwnd != GetCapture()) return 0;
- }
- ReleaseCapture();
- if (hittest == HTCAPTION || hittest == HTSYSMENU || hittest == HTHSCROLL || hittest == HTVSCROLL)
- {
- TRACE("Msg pt %x and Msg.lParam %x and lParam %x\n",MAKELONG(msg.pt.x,msg.pt.y),msg.lParam,lParam);
- SendMessageW( hwnd, WM_CONTEXTMENU, (WPARAM)hwnd, MAKELONG(msg.pt.x,msg.pt.y));
- }
- break;
- }
- return 0;
-}
-
-/***********************************************************************
- * NcGetInsideRect
- *
- * Get the 'inside' rectangle of a window, i.e. the whole window rectangle
- * but without the borders (if any).
- * The rectangle is in window coordinates (for drawing with GetWindowDC()).
- */
-static void FASTCALL
-NcGetInsideRect(HWND Wnd, RECT *Rect)
+BOOL WINAPI
+RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags)
{
- DWORD Style;
- DWORD ExStyle;
-
- GetWindowRect(Wnd, Rect);
- Rect->right = Rect->right - Rect->left;
- Rect->left = 0;
- Rect->bottom = Rect->bottom - Rect->top;
- Rect->top = 0;
-
- Style = GetWindowLongPtrW(Wnd, GWL_STYLE);
- if (0 != (Style & WS_ICONIC))
- {
- return;
- }
-
- /* Remove frame from rectangle */
- ExStyle = GetWindowLongPtrW(Wnd, GWL_EXSTYLE);
- if (HAS_THICKFRAME(Style, ExStyle))
- {
- InflateRect(Rect, - GetSystemMetrics(SM_CXFRAME), - GetSystemMetrics(SM_CYFRAME));
- }
- else if (HAS_DLGFRAME(Style, ExStyle))
- {
- InflateRect(Rect, - GetSystemMetrics(SM_CXDLGFRAME), - GetSystemMetrics(SM_CYDLGFRAME));
- }
- else if (HAS_THINFRAME(Style, ExStyle))
- {
- InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
- }
-
- /* We have additional border information if the window
- * is a child (but not an MDI child) */
- if (0 != (Style & WS_CHILD)
- && 0 == (ExStyle & WS_EX_MDICHILD))
- {
- if (0 != (ExStyle & WS_EX_CLIENTEDGE))
- {
- InflateRect(Rect, - GetSystemMetrics(SM_CXEDGE), - GetSystemMetrics(SM_CYEDGE));
- }
- if (0 != (ExStyle & WS_EX_STATICEDGE))
- {
- InflateRect(Rect, - GetSystemMetrics(SM_CXBORDER), - GetSystemMetrics(SM_CYBORDER));
- }
- }
+ ERR("Real DC flags %08x\n",uFlags);
+ return NtUserDrawCaption(hWnd, hDC, lpRc, uFlags);
}
-/***********************************************************************
- * NcGetSysPopupPos
- */
-void FASTCALL
-NcGetSysPopupPos(HWND Wnd, RECT *Rect)
-{
- RECT WindowRect;
-
- if (IsIconic(Wnd))
- {
- GetWindowRect(Wnd, Rect);
- }
- else
- {
- NcGetInsideRect(Wnd, Rect);
- GetWindowRect(Wnd, &WindowRect);
- OffsetRect(Rect, WindowRect.left, WindowRect.top);
- if (0 != (GetWindowLongPtrW(Wnd, GWL_STYLE) & WS_CHILD))
- {
- ClientToScreen(GetParent(Wnd), (POINT *) Rect);
- }
- Rect->right = Rect->left + GetSystemMetrics(SM_CYCAPTION) - 1;
- Rect->bottom = Rect->top + GetSystemMetrics(SM_CYCAPTION) - 1;
- }
-}
/* PUBLIC FUNCTIONS ***********************************************************/