Files
reactos/reactos/lib/user32/windows/defwnd.c
T
2003-10-04 16:04:01 +00:00

2460 lines
64 KiB
C

/* $Id: defwnd.c,v 1.93 2003/10/04 16:04:01 weiden Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/window.c
* PURPOSE: Window management
* PROGRAMMER: Casper S. Hornstrup ([email protected])
* UPDATE HISTORY:
* 06-06-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#include <windows.h>
#include <user32.h>
#include <window.h>
#include <user32/wininternal.h>
#include <string.h>
#include <menu.h>
#include <cursor.h>
#include <winpos.h>
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
static HBITMAP hbSysMenu;
/* TODO: widgets will be cached here.
static HBITMAP hbClose;
static HBITMAP hbCloseD;
static HBITMAP hbMinimize;
static HBITMAP hbMinimizeD;
static HBITMAP hbRestore;
static HBITMAP hbRestoreD;
static HBITMAP hbMaximize;
static HBITMAP hbScrUp;
static HBITMAP hbScrDwn;
static HBITMAP hbScrLeft;
static HBITMAP hbScrRight;
*/
static COLORREF SysColours[] =
{
RGB(224, 224, 224) /* COLOR_SCROLLBAR */,
RGB(58, 110, 165) /* COLOR_BACKGROUND */,
RGB(0, 0, 128) /* COLOR_ACTIVECAPTION */,
RGB(128, 128, 128) /* COLOR_INACTIVECAPTION */,
RGB(192, 192, 192) /* COLOR_MENU */,
RGB(255, 255, 255) /* COLOR_WINDOW */,
RGB(0, 0, 0) /* COLOR_WINDOWFRAME */,
RGB(0, 0, 0) /* COLOR_MENUTEXT */,
RGB(0, 0, 0) /* COLOR_WINDOWTEXT */,
RGB(255, 255, 255) /* COLOR_CAPTIONTEXT */,
RGB(128, 128, 128) /* COLOR_ACTIVEBORDER */,
RGB(255, 255, 255) /* COLOR_INACTIVEBORDER */,
RGB(255, 255, 232) /* COLOR_APPWORKSPACE */,
RGB(224, 224, 224) /* COLOR_HILIGHT */,
RGB(0, 0, 128) /* COLOR_HILIGHTTEXT */,
RGB(192, 192, 192) /* COLOR_BTNFACE */,
RGB(128, 128, 128) /* COLOR_BTNSHADOW */,
RGB(192, 192, 192) /* COLOR_GRAYTEXT */,
RGB(0, 0, 0) /* COLOR_BTNTEXT */,
RGB(192, 192, 192) /* COLOR_INACTIVECAPTIONTEXT */,
RGB(255, 255, 255) /* COLOR_BTNHILIGHT */,
RGB(32, 32, 32) /* COLOR_3DDKSHADOW */,
RGB(192, 192, 192) /* COLOR_3DLIGHT */,
RGB(0, 0, 0) /* COLOR_INFOTEXT */,
RGB(255, 255, 192) /* COLOR_INFOBK */,
RGB(184, 180, 184) /* COLOR_ALTERNATEBTNFACE */,
RGB(0, 0, 255) /* COLOR_HOTLIGHT */,
RGB(16, 132, 208) /* COLOR_GRADIENTACTIVECAPTION */,
RGB(181, 181, 181) /* COLOR_GRADIENTINACTIVECAPTION */,
};
static ATOM AtomInternalPos;
/* Bits in the dwKeyData */
#define KEYDATA_ALT 0x2000
/* FUNCTIONS *****************************************************************/
INT
UIGetFrameSizeX(ULONG uStyle)
{
if ( uStyle & WS_THICKFRAME )
return GetSystemMetrics(SM_CXSIZEFRAME);
else
return GetSystemMetrics(SM_CXFRAME);
}
INT
UIGetFrameSizeY(ULONG uStyle)
{
if (uStyle & WS_THICKFRAME)
return GetSystemMetrics(SM_CYSIZEFRAME);
else
return GetSystemMetrics(SM_CYFRAME);
}
VOID
UserSetupInternalPos(VOID)
{
LPSTR Str = "SysIP";
AtomInternalPos = GlobalAddAtomA(Str);
}
/*
* @implemented
*/
DWORD STDCALL
GetSysColor(int nIndex)
{
return SysColours[nIndex];
}
/*
* @implemented
*/
HPEN STDCALL
GetSysColorPen(int nIndex)
{
static HPEN SysPens[sizeof(SysColours) / sizeof(SysColours[0])];
if (nIndex < 0 || sizeof(SysColours) / sizeof(SysColours[0]) < nIndex)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* FIXME should register this object with DeleteObject() so it
can't be deleted */
if (NULL == SysPens[nIndex])
{
SysPens[nIndex] = CreatePen(PS_SOLID, 1, SysColours[nIndex]);
}
return SysPens[nIndex];
}
/*
* @implemented
*/
HBRUSH STDCALL
GetSysColorBrush(int nIndex)
{
static HBRUSH SysBrushes[sizeof(SysColours) / sizeof(SysColours[0])];
if (nIndex < 0 || sizeof(SysColours) / sizeof(SysColours[0]) < nIndex)
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
/* FIXME should register this object with DeleteObject() so it
can't be deleted */
if (NULL == SysBrushes[nIndex])
{
SysBrushes[nIndex] = (HBRUSH) ((DWORD) CreateSolidBrush(SysColours[nIndex]) | 0x00800000);
}
return SysBrushes[nIndex];
}
/*
* @unimplemented
*/
LRESULT STDCALL
DefFrameProcA( HWND hWnd,
HWND hWndMDIClient,
UINT uMsg,
WPARAM wParam,
LPARAM lParam )
{
UNIMPLEMENTED;
return ((LRESULT)0);
}
/*
* @unimplemented
*/
LRESULT STDCALL
DefFrameProcW(HWND hWnd,
HWND hWndMDIClient,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
UNIMPLEMENTED;
return ((LRESULT)0);
}
PINTERNALPOS
UserGetInternalPos(HWND hWnd)
{
PINTERNALPOS lpPos;
lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
return(lpPos);
}
BOOL
DefWndRedrawIconTitle(HWND hWnd)
{
PINTERNALPOS lpPos = (PINTERNALPOS)GetPropA(hWnd, (LPSTR)(DWORD)AtomInternalPos);
if (lpPos != NULL)
{
if (lpPos->IconTitle != NULL)
{
SendMessageA(lpPos->IconTitle, WM_SHOWWINDOW, TRUE, 0);
InvalidateRect(lpPos->IconTitle, NULL, TRUE);
return(TRUE);
}
}
return(FALSE);
}
BOOL
UserHasMenu(HWND hWnd, ULONG Style)
{
return (!(Style & WS_CHILD) && GetMenu(hWnd) != 0);
}
ULONG
UserHasAnyFrameStyle(ULONG Style, ULONG ExStyle)
{
return ((Style & (WS_THICKFRAME | WS_DLGFRAME | WS_BORDER)) ||
(ExStyle & WS_EX_DLGMODALFRAME) ||
(!(Style & (WS_CHILD | WS_POPUP))));
}
ULONG
UserHasDlgFrameStyle(ULONG Style, ULONG ExStyle)
{
return ((ExStyle & WS_EX_DLGMODALFRAME) ||
((Style & WS_DLGFRAME) && (!(Style & WS_THICKFRAME))));
}
ULONG
UserHasThickFrameStyle(ULONG Style, ULONG ExStyle)
{
return ((Style & WS_THICKFRAME) &&
(!((Style & (WS_DLGFRAME | WS_BORDER)) == WS_DLGFRAME)));
}
ULONG
UserHasThinFrameStyle(ULONG Style, ULONG ExStyle)
{
return ((Style & WS_BORDER) || (!(Style & (WS_CHILD | WS_POPUP))));
}
ULONG
UserHasBigFrameStyle(ULONG Style, ULONG ExStyle)
{
return ((Style & (WS_THICKFRAME | WS_DLGFRAME)) ||
(ExStyle & WS_EX_DLGMODALFRAME));
}
void
UserGetInsideRectNC(HWND hWnd, RECT *rect)
{
RECT WindowRect;
ULONG Style;
ULONG ExStyle;
Style = GetWindowLongW(hWnd, GWL_STYLE);
ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
GetWindowRect(hWnd, &WindowRect);
rect->top = rect->left = 0;
rect->right = WindowRect.right - WindowRect.left;
rect->bottom = WindowRect.bottom - WindowRect.top;
if (Style & WS_ICONIC)
{
return;
}
/* Remove frame from rectangle */
if (UserHasThickFrameStyle(Style, ExStyle ))
{
InflateRect(rect, -GetSystemMetrics(SM_CXFRAME),
-GetSystemMetrics(SM_CYFRAME));
}
else
{
if (UserHasDlgFrameStyle(Style, ExStyle ))
{
InflateRect(rect, -GetSystemMetrics(SM_CXDLGFRAME),
-GetSystemMetrics(SM_CYDLGFRAME));
/* FIXME: this isn't in NC_AdjustRect? why not? */
if (ExStyle & WS_EX_DLGMODALFRAME)
InflateRect( rect, -1, 0 );
}
else
{
if (UserHasThinFrameStyle(Style, ExStyle))
{
InflateRect(rect, -GetSystemMetrics(SM_CXBORDER),
-GetSystemMetrics(SM_CYBORDER));
}
}
}
}
WINBOOL
UserDrawSysMenuButton(HWND hWnd, HDC hDC, LPRECT Rect, BOOL down)
{
HDC hDcMem;
HBITMAP hSavedBitmap;
if (!hbSysMenu)
{
hbSysMenu = (HBITMAP)LoadBitmapW(0, MAKEINTRESOURCEW(OBM_CLOSE));
}
hDcMem = CreateCompatibleDC(hDC);
if (!hDcMem)
{
return FALSE;
}
hSavedBitmap = SelectObject(hDcMem, hbSysMenu);
if (!hSavedBitmap)
{
DeleteDC(hDcMem);
return FALSE;
}
BitBlt(hDC, Rect->left + 2, Rect->top + 3, 16, 14, hDcMem,
(GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD) ?
GetSystemMetrics(SM_CXSIZE): 0, 0, SRCCOPY);
SelectObject(hDcMem, hSavedBitmap);
DeleteDC(hDcMem);
return TRUE;
}
/*
* FIXME:
* Cache bitmaps, then just bitblt instead of calling DFC() (and
* wasting precious CPU cycles) every time
*/
static void
UserDrawCaptionButton(HWND hWnd, HDC hDC, BOOL bDown, ULONG Type)
{
RECT rect;
ULONG ExStyle;
ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
INT iBmpWidth = GetSystemMetrics(SM_CXSIZE) - 2;
INT iBmpHeight = GetSystemMetrics(SM_CYSIZE) - 4;
INT OffsetX = UIGetFrameSizeX(Style);
INT OffsetY = UIGetFrameSizeY(Style);
if (!(Style & WS_SYSMENU))
{
return;
}
ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
GetWindowRect(hWnd, &rect);
rect.right = rect.right - rect.left;
rect.bottom = rect.bottom - rect.top;
rect.left = rect.top = 0;
switch(Type)
{
case DFCS_CAPTIONMIN:
{
if ((ExStyle & WS_EX_TOOLWINDOW) == TRUE)
return; /* ToolWindows don't have min/max buttons */
SetRect(&rect, rect.right - OffsetX - (iBmpWidth * 3) - 4,
OffsetY + 2, rect.right - (iBmpWidth * 2) - OffsetX - 4,
rect.top + iBmpHeight + OffsetY + 2);
DrawFrameControl(hDC, &rect, DFC_CAPTION,
DFCS_CAPTIONMIN | (bDown ? DFCS_PUSHED : 0) |
((Style & WS_MINIMIZEBOX) ? 0 : DFCS_INACTIVE));
break;
}
case DFCS_CAPTIONMAX:
{
if ((ExStyle & WS_EX_TOOLWINDOW) == TRUE)
return; /* ToolWindows don't have min/max buttons */
SetRect(&rect, rect.right - OffsetX - (iBmpWidth * 2) - 4,
OffsetY + 2, rect.right - iBmpWidth - OffsetX - 4,
rect.top + iBmpHeight + OffsetY + 2);
DrawFrameControl(hDC, &rect, DFC_CAPTION,
(IsZoomed(hWnd) ? DFCS_CAPTIONRESTORE : DFCS_CAPTIONMAX) |
(bDown ? DFCS_PUSHED : 0) |
((Style & WS_MAXIMIZEBOX) ? 0 : DFCS_INACTIVE));
break;
}
case DFCS_CAPTIONCLOSE:
{
SetRect(&rect, rect.right - OffsetX - iBmpWidth - 2,
OffsetY + 2, rect.right - OffsetX - 2,
rect.top + iBmpHeight + OffsetY + 2 );
DrawFrameControl(hDC, &rect, DFC_CAPTION,
(DFCS_CAPTIONCLOSE | (bDown ? DFCS_PUSHED : 0) |
((Style & WS_SYSMENU) ? 0 : DFCS_INACTIVE)));
break;
}
}
}
// Enabling this will cause captions to draw smoother, but slower:
// #define DOUBLE_BUFFER_CAPTION
// NOTE: Double buffering appears to be broken for this at the moment
/*
* @implemented
*/
WINBOOL STDCALL
DrawCaption(
HWND hWnd,
HDC hDC,
LPRECT lprc,
UINT uFlags)
{
NONCLIENTMETRICSW nclm;
BOOL result = FALSE;
RECT r = *lprc;
UINT VCenter = 0, Padding = 0, Height;
WCHAR buffer[256];
HFONT hFont = NULL;
HFONT hOldFont = NULL;
HBRUSH OldBrush = NULL;
HDC MemDC = NULL;
int ButtonWidth;
#ifdef DOUBLE_BUFFER_CAPTION
HBITMAP MemBMP = NULL, OldBMP = NULL;
MemDC = CreateCompatibleDC(hDC);
if (! MemDC) goto cleanup;
MemBMP = CreateCompatibleBitmap(hDC, lprc->right - lprc->left, lprc->bottom - lprc->top);
if (! MemBMP) goto cleanup;
OldBMP = SelectObject(MemDC, MemBMP);
if (! OldBMP) goto cleanup;
#else
MemDC = hDC;
OffsetViewportOrgEx(MemDC, lprc->left, lprc->top, NULL);
#endif
// If DC_GRADIENT is specified, a Win 98/2000 style caption gradient should
// be painted. For now, that flag is ignored:
// Windows 98/Me, Windows 2000/XP: When this flag is set, the function uses
// COLOR_GRADIENTACTIVECAPTION (if the DC_ACTIVE flag was set) or
// COLOR_GRADIENTINACTIVECAPTION for the title-bar color.
// Draw the caption background
if (uFlags & DC_INBUTTON)
{
OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_BTNFACE : COLOR_BTNSHADOW) );
if (! OldBrush) goto cleanup;
if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
}
else
{
// DC_GRADIENT check should go here somewhere
OldBrush = SelectObject(MemDC, GetSysColorBrush(uFlags & DC_ACTIVE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION) );
if (! OldBrush) goto cleanup;
if (! PatBlt(MemDC, 0, 0, lprc->right - lprc->left, lprc->bottom - lprc->top, PATCOPY )) goto cleanup;
}
/* Windows behaves like this */
Height = GetSystemMetrics(SM_CYCAPTION) - 1;
VCenter = (lprc->bottom - lprc->top) / 2;
Padding = VCenter - (Height / 2);
r.left = Padding;
r.right = r.left + (lprc->right - lprc->left);
r.top = Padding;
r.bottom = r.top + (Height / 2);
if (uFlags & DC_ICON)
{
// For some reason the icon isn't centered correctly...
r.top --;
UserDrawSysMenuButton(hWnd, MemDC, &r, FALSE);
r.top ++;
}
r.top ++;
r.left += 2;
if ((uFlags & DC_TEXT) && (GetWindowTextW( hWnd, buffer, sizeof(buffer)/sizeof(buffer[0]) )))
{
// Duplicate odd behaviour from Windows:
if ((! uFlags & DC_SMALLCAP) || (uFlags & DC_ICON) || (uFlags & DC_INBUTTON) ||
(! uFlags & DC_ACTIVE))
r.left += GetSystemMetrics(SM_CXSIZE) + Padding;
r.right = (lprc->right - lprc->left);
ButtonWidth = GetSystemMetrics(SM_CXSIZE) - 2;
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
{
r.right -= 3 + ButtonWidth;
if (! (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW))
{
r.right -= 2 + 2 * ButtonWidth;
}
}
r.right -= 2;
nclm.cbSize = sizeof(nclm);
if (! SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICSW), &nclm, 0)) goto cleanup;
if (uFlags & DC_INBUTTON)
SetTextColor(MemDC, SysColours[ uFlags & DC_ACTIVE ? COLOR_BTNTEXT : COLOR_GRAYTEXT]);
else
SetTextColor(MemDC, SysColours[ uFlags & DC_ACTIVE ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT]);
SetBkMode( MemDC, TRANSPARENT );
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_EX_TOOLWINDOW)
// if (uFlags & DC_SMALLCAP) // incorrect
hFont = CreateFontIndirectW(&nclm.lfSmCaptionFont);
else
hFont = CreateFontIndirectW(&nclm.lfCaptionFont);
if (! hFont) goto cleanup;
hOldFont = SelectObject(MemDC, hFont);
if (! hOldFont) goto cleanup;
DrawTextW(MemDC, buffer, wcslen(buffer), &r, DT_VCENTER | DT_END_ELLIPSIS);
// Old method:
// TextOutW(hDC, r.left + (GetSystemMetrics(SM_CXDLGFRAME) * 2), lprc->top + (nclm.lfCaptionFont.lfHeight / 2), buffer, wcslen(buffer));
}
if (uFlags & DC_BUTTONS)
{
// Windows XP draws the caption buttons with DC_BUTTONS
// r.left += GetSystemMetrics(SM_CXSIZE) + 1;
// UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
// r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
// UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
// UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
}
#ifdef DOUBLE_BUFFER_CAPTION
if (! BitBlt(hDC, lprc->left, lprc->top, lprc->right - lprc->left, lprc->bottom - lprc->top,
MemDC, 0, 0, SRCCOPY)) goto cleanup;
#endif
result = TRUE;
cleanup :
if (MemDC)
{
if (OldBrush) SelectObject(MemDC, OldBrush);
if (hOldFont) SelectObject(MemDC, hOldFont);
if (hFont) DeleteObject(hFont);
#ifdef DOUBLE_BUFFER_CAPTION
if (OldBMP) SelectObject(MemDC, OldBMP);
if (MemBMP) DeleteObject(MemBMP);
DeleteDC(MemDC);
#else
OffsetViewportOrgEx(MemDC, -lprc->left, -lprc->top, NULL);
#endif
}
return result;
}
static void
UserDrawCaptionNC (
HDC hDC,
RECT *rect,
HWND hWnd,
DWORD style,
BOOL active )
{
POINT OldPos;
HPEN lPen, oPen;
RECT r = *rect;
UINT Style, capflags = 0;
Style = GetWindowLongW(hWnd, GWL_STYLE);
capflags = DC_ICON | DC_TEXT;
capflags |= (active & DC_ACTIVE);
if (Style & WS_EX_TOOLWINDOW)
capflags |= DC_SMALLCAP;
// Old code:
// PatBlt(hDC,rect->left + GetSystemMetrics(SM_CXFRAME), rect->top +
// GetSystemMetrics(SM_CYFRAME), rect->right - (GetSystemMetrics(SM_CXFRAME) * 2), (rect->top +
// GetSystemMetrics(SM_CYCAPTION)) - 1, PATCOPY );
r.left += GetSystemMetrics(SM_CXFRAME);
r.top += GetSystemMetrics(SM_CYFRAME);
r.right -= GetSystemMetrics(SM_CXFRAME);
r.bottom = r.top + GetSystemMetrics(SM_CYCAPTION) - 1;
// GetSystemMetrics(SM_CYCAPTION)) - 1, PATCOPY );
DrawCaption(hWnd, hDC, &r, capflags);
/* draw line below caption */
lPen = GetSysColorPen(COLOR_MENU);
oPen = SelectObject(hDC, lPen);
MoveToEx(hDC, r.left, r.bottom, &OldPos);
LineTo(hDC, r.right, r.bottom);
MoveToEx(hDC, OldPos.x, OldPos.y, NULL);
SelectObject(hDC, oPen);
r.bottom++;
if (style & WS_SYSMENU)
{
// UserDrawSysMenuButton( hWnd, hDC, FALSE);
r.left += GetSystemMetrics(SM_CXSIZE) + 1;
UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONCLOSE);
r.right -= GetSystemMetrics(SM_CXSMSIZE) + 1;
if(Style & (WS_MAXIMIZEBOX | WS_MINIMIZEBOX))
{
UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMIN);
UserDrawCaptionButton( hWnd, hDC, FALSE, DFCS_CAPTIONMAX);
}
}
}
static VOID
UserDrawFrameNC(HDC hDC, RECT* rect, BOOL dlgFrame, BOOL active)
{
DrawEdge(hDC, rect,EDGE_RAISED, BF_RECT | BF_MIDDLE);
}
void
SCROLL_DrawScrollBar (HWND hWnd, HDC hDC, INT nBar, BOOL arrows, BOOL interior);
VOID
DefWndDoPaintNC(HWND hWnd, HRGN clip)
{
BOOL Active = FALSE;
HDC hDC;
RECT rect, clientrect;
ULONG Style;
ULONG ExStyle;
int wFrame = 0;
if (GetActiveWindow() == hWnd) Active = TRUE;
Style = GetWindowLongW(hWnd, GWL_STYLE);
ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
hDC = GetDCEx(hWnd, (clip > (HRGN)1) ? clip : 0, DCX_USESTYLE | DCX_WINDOW |
((clip > (HRGN)1) ? (DCX_INTERSECTRGN | DCX_KEEPCLIPRGN) : 0));
if (hDC == 0)
{
return;
}
/* FIXME: Test whether we need to draw anything at all. */
GetWindowRect(hWnd, &rect);
rect.right = rect.right - rect.left;
rect.bottom = rect.bottom - rect.top;
rect.top = rect.left = 0;
clientrect = rect;
SelectObject(hDC, GetSysColorPen(COLOR_WINDOWFRAME));
if (UserHasThickFrameStyle(Style, ExStyle))
{
UserDrawFrameNC(hDC, &rect, FALSE, Active);
wFrame = GetSystemMetrics(SM_CXSIZEFRAME);
}
else if (UserHasDlgFrameStyle(Style, ExStyle))
{
UserDrawFrameNC(hDC, &rect, TRUE, Active);
wFrame = GetSystemMetrics(SM_CXDLGFRAME);
}
if (Style & WS_CAPTION)
{
RECT r = rect;
r.bottom = rect.top + GetSystemMetrics(SM_CYSIZE);
rect.top += GetSystemMetrics(SM_CYSIZE) +
GetSystemMetrics(SM_CYBORDER);
UserDrawCaptionNC(hDC, &r, hWnd, Style, Active);
}
/* Draw menu bar. */
if (UserHasMenu(hWnd, Style))
{
RECT r = rect;
r.bottom = rect.top + GetSystemMetrics(SM_CYMENU);
r.left += wFrame;
r.right -= wFrame;
rect.top += MenuDrawMenuBar(hDC, &r, hWnd, FALSE);
}
/* Draw scrollbars */
if (Style & WS_VSCROLL && (clientrect.right - clientrect.left > GetSystemMetrics(SM_CXVSCROLL)))
SCROLL_DrawScrollBar(hWnd, hDC, SB_VERT, TRUE, TRUE);
if (Style & WS_HSCROLL && (clientrect.bottom - clientrect.top > GetSystemMetrics(SM_CYHSCROLL)))
SCROLL_DrawScrollBar(hWnd, hDC, SB_HORZ, TRUE, TRUE);
/* FIXME: Draw size box.*/
ReleaseDC(hWnd, hDC);
}
LRESULT
DefWndPaintNC(HWND hWnd, HRGN clip)
{
if (IsWindowVisible(hWnd))
{
if (IsIconic(hWnd))
{
DefWndRedrawIconTitle(hWnd);
}
else
{
DefWndDoPaintNC(hWnd, clip);
}
}
return(0);
}
LRESULT
DefWndHitTestNC(HWND hWnd, POINT Point)
{
RECT WindowRect;
LONG ScrollXY;
ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
ULONG ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
GetWindowRect(hWnd, &WindowRect);
if (!PtInRect(&WindowRect, Point))
{
return(HTNOWHERE);
}
if (Style & WS_MINIMIZE)
{
return(HTCAPTION);
}
if (UserHasThickFrameStyle(Style, ExStyle))
{
InflateRect(&WindowRect, -GetSystemMetrics(SM_CXFRAME),
-GetSystemMetrics(SM_CYFRAME));
if (!PtInRect(&WindowRect, Point))
{
if (Point.y < WindowRect.top)
{
if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
{
return(HTTOPLEFT);
}
if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
{
return(HTTOPRIGHT);
}
return(HTTOP);
}
if (Point.y >= WindowRect.bottom)
{
if (Point.x < (WindowRect.left + GetSystemMetrics(SM_CXSIZE)))
{
return(HTBOTTOMLEFT);
}
if (Point.x >= (WindowRect.right - GetSystemMetrics(SM_CXSIZE)))
{
return(HTBOTTOMRIGHT);
}
return(HTBOTTOM);
}
if (Point.x < WindowRect.left)
{
if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
{
return(HTTOPLEFT);
}
if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
{
return(HTBOTTOMLEFT);
}
return(HTLEFT);
}
if (Point.x >= WindowRect.right)
{
if (Point.y < (WindowRect.top + GetSystemMetrics(SM_CYSIZE)))
{
return(HTTOPRIGHT);
}
if (Point.y >= (WindowRect.bottom - GetSystemMetrics(SM_CYSIZE)))
{
return(HTBOTTOMRIGHT);
}
return(HTRIGHT);
}
}
}
else
{
if (UserHasDlgFrameStyle(Style, ExStyle))
{
InflateRect(&WindowRect, -GetSystemMetrics(SM_CXDLGFRAME),
-GetSystemMetrics(SM_CYDLGFRAME));
}
else if (UserHasThinFrameStyle(Style, ExStyle))
{
InflateRect(&WindowRect, -GetSystemMetrics(SM_CXBORDER),
-GetSystemMetrics(SM_CYBORDER));
}
if (!PtInRect(&WindowRect, Point))
{
return(HTBORDER);
}
}
if ((Style & WS_CAPTION) == WS_CAPTION)
{
WindowRect.top += (GetSystemMetrics(SM_CYCAPTION) -
GetSystemMetrics(SM_CYBORDER));
if (!PtInRect(&WindowRect, Point))
{
if ((Style & WS_SYSMENU) && !(ExStyle & WS_EX_TOOLWINDOW))
{
WindowRect.left += GetSystemMetrics(SM_CXSIZE);
WindowRect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
}
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);
}
}
ScreenToClient(hWnd, &Point);
GetClientRect(hWnd, &WindowRect);
if (PtInRect(&WindowRect, Point))
{
return(HTCLIENT);
}
if (Style & WS_VSCROLL)
{
ScrollXY = GetSystemMetrics(SM_CXVSCROLL);
if(WindowRect.right - WindowRect.left > ScrollXY)
{
WindowRect.right += ScrollXY;
if (PtInRect(&WindowRect, Point))
{
return(HTVSCROLL);
}
}
}
if (Style & WS_HSCROLL)
{
ScrollXY = GetSystemMetrics(SM_CYHSCROLL);
if(WindowRect.bottom - WindowRect.top > ScrollXY)
{
WindowRect.bottom += ScrollXY;
if (PtInRect(&WindowRect, Point))
{
ScrollXY = GetSystemMetrics(SM_CXVSCROLL);
if ((Style & WS_VSCROLL) && (WindowRect.right - WindowRect.left > ScrollXY) &&
(Point.x >= (WindowRect.right - ScrollXY)))
{
return(HTBOTTOMRIGHT);
}
return(HTHSCROLL);
}
}
}
if (UserHasMenu(hWnd, Style))
{
if (Point.y < 0 && Point.x >= 0 && Point.x <= WindowRect.right)
{
return(HTMENU);
}
}
return(HTNOWHERE);
}
VOID STATIC
DefWndDoButton(HWND hWnd, WPARAM wParam)
{
MSG Msg;
BOOL InBtn = TRUE, HasBtn = FALSE;
ULONG Btn, Style;
WPARAM SCMsg, CurBtn = wParam, OrigBtn = wParam;
Style = GetWindowLongW(hWnd, GWL_STYLE);
switch(wParam)
{
case HTCLOSE:
Btn = DFCS_CAPTIONCLOSE;
SCMsg = SC_CLOSE;
HasBtn = (Style & WS_SYSMENU);
break;
case HTMINBUTTON:
Btn = DFCS_CAPTIONMIN;
SCMsg = SC_MINIMIZE;
HasBtn = (Style & WS_MINIMIZEBOX);
break;
case HTMAXBUTTON:
Btn = DFCS_CAPTIONMAX;
SCMsg = SC_MAXIMIZE;
HasBtn = (Style & WS_MAXIMIZEBOX);
break;
default:
return;
}
if(!HasBtn)
return;
SetCapture(hWnd);
UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), HasBtn , Btn);
while(1)
{
GetMessageW(&Msg, 0, 0, 0);
switch(Msg.message)
{
case WM_NCLBUTTONUP:
case WM_LBUTTONUP:
if(InBtn)
goto done;
else
{
ReleaseCapture();
return;
}
case WM_NCMOUSEMOVE:
case WM_MOUSEMOVE:
CurBtn = DefWndHitTestNC(hWnd, Msg.pt);
if(InBtn != (CurBtn == OrigBtn))
{
UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), (CurBtn == OrigBtn) , Btn);
}
InBtn = CurBtn == OrigBtn;
break;
}
}
done:
UserDrawCaptionButton( hWnd, GetWindowDC(hWnd), FALSE , Btn);
ReleaseCapture();
SendMessageA(hWnd, WM_SYSCOMMAND, SCMsg, 0);
return;
}
VOID STATIC
DefWndDoScrollBarDown(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
POINT Point;
DWORD hit;
Point.x = SLOWORD(lParam);
Point.y = SHIWORD(lParam);
hit = SCROLL_HitTest(hWnd, (wParam == HTHSCROLL) ? SB_HORZ : SB_VERT, Point, FALSE);
if(hit)
DPRINT("SCROLL_HitTest() == 0x%x\n", hit);
SendMessageA(hWnd, WM_SYSCOMMAND, Msg + (UINT)wParam, lParam);
}
LRESULT
DefWndHandleLButtonDownNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
switch (wParam)
{
case HTCAPTION:
{
HWND hTopWnd = GetAncestor(hWnd, GA_ROOT);
if (SetActiveWindow(hTopWnd) || GetActiveWindow() == hTopWnd)
{
SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOVE + HTCAPTION, lParam);
}
break;
}
case HTSYSMENU:
{
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_SYSMENU)
{
if (!(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
{
HDC hDC = GetWindowDC(hWnd);
// UserDrawSysMenuButton(hWnd, hDC, TRUE);
ReleaseDC(hWnd, hDC);
}
SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTSYSMENU,
lParam);
}
break;
}
case HTMENU:
{
SendMessageA(hWnd, WM_SYSCOMMAND, SC_MOUSEMENU + HTMENU, lParam);
break;
}
case HTHSCROLL:
{
DefWndDoScrollBarDown(hWnd, SC_HSCROLL, HTHSCROLL, lParam);
//SendMessageA(hWnd, WM_SYSCOMMAND, SC_HSCROLL + HTHSCROLL, lParam);
break;
}
case HTVSCROLL:
{
DefWndDoScrollBarDown(hWnd, SC_VSCROLL, HTVSCROLL, lParam);
//SendMessageA(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:
{
SendMessageA(hWnd, WM_SYSCOMMAND, SC_SIZE + wParam - 2, lParam);
break;
}
}
return(0);
}
LRESULT
DefWndHandleLButtonDblClkNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
UNIMPLEMENTED;
return(0);
}
LRESULT
DefWndHandleLButtonUpNC(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
UNIMPLEMENTED;
return(0);
}
LRESULT
DefWndHandleActiveNC(HWND hWnd, WPARAM wParam)
{
UNIMPLEMENTED;
return(0);
}
VOID
DefWndSetRedraw(HWND hWnd, WPARAM wParam)
{
UNIMPLEMENTED;
}
LRESULT
DefWndHandleSetCursor(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
/* Not for child windows. */
if (hWnd != (HWND)wParam)
{
return(0);
}
switch(LOWORD(lParam))
{
case HTERROR:
{
WORD Msg = HIWORD(lParam);
if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
Msg == WM_RBUTTONDOWN || Msg == WM_XBUTTONDOWN)
{
MessageBeep(0);
}
break;
}
case HTCLIENT:
{
HICON hCursor = (HICON)GetClassLongW(hWnd, GCL_HCURSOR);
if (hCursor)
{
SetCursor(hCursor);
return(TRUE);
}
return(FALSE);
}
case HTLEFT:
case HTRIGHT:
{
return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZEWE)));
}
case HTTOP:
case HTBOTTOM:
{
return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENS)));
}
case HTTOPLEFT:
case HTBOTTOMRIGHT:
{
return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENWSE)));
}
case HTBOTTOMLEFT:
case HTTOPRIGHT:
{
return((LRESULT)SetCursor(LoadCursorW(0, IDC_SIZENESW)));
}
}
return((LRESULT)SetCursor(LoadCursorW(0, IDC_ARROW)));
}
static LONG
DefWndStartSizeMove(HWND hWnd, WPARAM wParam, POINT *capturePoint)
{
LONG hittest = 0;
POINT pt;
MSG msg;
RECT rectWindow;
ULONG Style = GetWindowLongW(hWnd, GWL_STYLE);
GetWindowRect(hWnd, &rectWindow);
if ((wParam & 0xfff0) == SC_MOVE)
{
/* Move pointer at the center of the caption */
RECT rect;
UserGetInsideRectNC(hWnd, &rect);
if (Style & WS_SYSMENU)
rect.left += GetSystemMetrics(SM_CXSIZE) + 1;
if (Style & WS_MINIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
if (Style & WS_MAXIMIZEBOX)
rect.right -= GetSystemMetrics(SM_CXSIZE) + 1;
pt.x = rectWindow.left + (rect.right - rect.left) / 2;
pt.y = rectWindow.top + rect.top + GetSystemMetrics(SM_CYSIZE)/2;
hittest = HTCAPTION;
*capturePoint = pt;
}
else /* SC_SIZE */
{
while(!hittest)
{
GetMessageW(&msg, NULL, 0, 0);
switch(msg.message)
{
case WM_MOUSEMOVE:
hittest = DefWndHitTestNC(hWnd, msg.pt);
if ((hittest < HTLEFT) || (hittest > HTBOTTOMRIGHT))
hittest = 0;
break;
case WM_LBUTTONUP:
return 0;
case WM_KEYDOWN:
switch(msg.wParam)
{
case VK_UP:
hittest = HTTOP;
pt.x =(rectWindow.left+rectWindow.right)/2;
pt.y = rectWindow.top + GetSystemMetrics(SM_CYFRAME) / 2;
break;
case VK_DOWN:
hittest = HTBOTTOM;
pt.x =(rectWindow.left+rectWindow.right)/2;
pt.y = rectWindow.bottom - GetSystemMetrics(SM_CYFRAME) / 2;
break;
case VK_LEFT:
hittest = HTLEFT;
pt.x = rectWindow.left + GetSystemMetrics(SM_CXFRAME) / 2;
pt.y =(rectWindow.top+rectWindow.bottom)/2;
break;
case VK_RIGHT:
hittest = HTRIGHT;
pt.x = rectWindow.right - GetSystemMetrics(SM_CXFRAME) / 2;
pt.y =(rectWindow.top+rectWindow.bottom)/2;
break;
case VK_RETURN:
case VK_ESCAPE: return 0;
}
}
}
*capturePoint = pt;
}
SetCursorPos( pt.x, pt.y );
DefWndHandleSetCursor(hWnd, (WPARAM)hWnd, MAKELONG(hittest, WM_MOUSEMOVE));
return hittest;
}
#define ON_LEFT_BORDER(hit) \
(((hit) == HTLEFT) || ((hit) == HTTOPLEFT) || ((hit) == HTBOTTOMLEFT))
#define ON_RIGHT_BORDER(hit) \
(((hit) == HTRIGHT) || ((hit) == HTTOPRIGHT) || ((hit) == HTBOTTOMRIGHT))
#define ON_TOP_BORDER(hit) \
(((hit) == HTTOP) || ((hit) == HTTOPLEFT) || ((hit) == HTTOPRIGHT))
#define ON_BOTTOM_BORDER(hit) \
(((hit) == HTBOTTOM) || ((hit) == HTBOTTOMLEFT) || ((hit) == HTBOTTOMRIGHT))
VOID STATIC
UserDrawWindowFrame(HDC hdc, const RECT *rect,
ULONG width, ULONG height, DWORD rop )
{
HBRUSH hbrush = SelectObject( hdc, GetStockObject( GRAY_BRUSH ) );
PatBlt( hdc, rect->left, rect->top,
rect->right - rect->left - width, height, rop );
PatBlt( hdc, rect->left, rect->top + height, width,
rect->bottom - rect->top - height, rop );
PatBlt( hdc, rect->left + width, rect->bottom - 1,
rect->right - rect->left - width, -height, rop );
PatBlt( hdc, rect->right - 1, rect->top, -width,
rect->bottom - rect->top - height, rop );
SelectObject( hdc, hbrush );
}
VOID STATIC
UserDrawMovingFrame(HDC hdc, RECT *rect, BOOL thickframe)
{
if (thickframe)
{
UserDrawWindowFrame(hdc, rect, GetSystemMetrics(SM_CXFRAME),
GetSystemMetrics(SM_CYFRAME), PATINVERT );
}
else DrawFocusRect( hdc, rect );
}
VOID STATIC
DefWndDoSizeMove(HWND hwnd, WORD wParam)
{
MSG msg;
RECT sizingRect, mouseRect, origRect;
HDC hdc;
LONG hittest = (LONG)(wParam & 0x0f);
HCURSOR hDragCursor = 0, hOldCursor = 0;
POINT minTrack, maxTrack;
POINT capturePoint, pt;
ULONG Style = GetWindowLongW(hwnd, GWL_STYLE);
ULONG ExStyle = GetWindowLongW(hwnd, GWL_EXSTYLE);
BOOL thickframe = UserHasThickFrameStyle(Style, ExStyle);
BOOL iconic = Style & WS_MINIMIZE;
BOOL moved = FALSE;
DWORD dwPoint = GetMessagePos();
BOOL DragFullWindows = FALSE;
HWND hWndParent;
SystemParametersInfoA(SPI_GETDRAGFULLWINDOWS, 0, &DragFullWindows, 0);
pt.x = SLOWORD(dwPoint);
pt.y = SHIWORD(dwPoint);
capturePoint = pt;
if (IsZoomed(hwnd) || !IsWindowVisible(hwnd))
{
return;
}
if ((wParam & 0xfff0) == SC_MOVE)
{
if (!hittest)
{
hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
}
if (!hittest)
{
return;
}
}
else /* SC_SIZE */
{
if (!thickframe)
{
return;
}
if (hittest && hittest != HTSYSMENU)
{
hittest += 2;
}
else
{
SetCapture(hwnd);
hittest = DefWndStartSizeMove(hwnd, wParam, &capturePoint);
if (!hittest)
{
ReleaseCapture();
return;
}
}
}
if (Style & WS_CHILD)
{
hWndParent = GetParent(hwnd);
}
/* Get min/max info */
WinPosGetMinMaxInfo(hwnd, NULL, NULL, &minTrack, &maxTrack);
GetWindowRect(hwnd, &sizingRect);
if (Style & WS_CHILD)
{
MapWindowPoints( 0, hWndParent, (LPPOINT)&sizingRect, 2 );
GetClientRect(hWndParent, &mouseRect );
}
else
{
SetRect(&mouseRect, 0, 0, GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN));
}
origRect = sizingRect;
if (ON_LEFT_BORDER(hittest))
{
mouseRect.left = max( mouseRect.left, sizingRect.right-maxTrack.x );
mouseRect.right = min( mouseRect.right, sizingRect.right-minTrack.x );
}
else if (ON_RIGHT_BORDER(hittest))
{
mouseRect.left = max( mouseRect.left, sizingRect.left+minTrack.x );
mouseRect.right = min( mouseRect.right, sizingRect.left+maxTrack.x );
}
if (ON_TOP_BORDER(hittest))
{
mouseRect.top = max( mouseRect.top, sizingRect.bottom-maxTrack.y );
mouseRect.bottom = min( mouseRect.bottom,sizingRect.bottom-minTrack.y);
}
else if (ON_BOTTOM_BORDER(hittest))
{
mouseRect.top = max( mouseRect.top, sizingRect.top+minTrack.y );
mouseRect.bottom = min( mouseRect.bottom, sizingRect.top+maxTrack.y );
}
if (Style & WS_CHILD)
{
MapWindowPoints( hWndParent, 0, (LPPOINT)&mouseRect, 2 );
}
SendMessageA( hwnd, WM_ENTERSIZEMOVE, 0, 0 );
if (GetCapture() != hwnd) SetCapture( hwnd );
if (Style & WS_CHILD)
{
/* Retrieve a default cache DC (without using the window style) */
hdc = GetDCEx(hWndParent, 0, DCX_CACHE);
}
else
{
hdc = GetDC( 0 );
}
if( iconic ) /* create a cursor for dragging */
{
HICON hIcon = (HICON)GetClassLongW(hwnd, GCL_HICON);
if(!hIcon) hIcon = (HICON)SendMessageW( hwnd, WM_QUERYDRAGICON, 0, 0L);
if( hIcon ) hDragCursor = CursorIconToCursor( hIcon, TRUE );
if( !hDragCursor ) iconic = FALSE;
}
/* invert frame if WIN31_LOOK to indicate mouse click on caption */
if( !iconic && !DragFullWindows)
{
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
}
while(1)
{
int dx = 0, dy = 0;
GetMessageW(&msg, 0, 0, 0);
/* Exit on button-up, Return, or Esc */
if ((msg.message == WM_LBUTTONUP) ||
((msg.message == WM_KEYDOWN) &&
((msg.wParam == VK_RETURN) || (msg.wParam == VK_ESCAPE)))) break;
if (msg.message == WM_PAINT)
{
if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
UpdateWindow( msg.hwnd );
if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
continue;
}
if ((msg.message != WM_KEYDOWN) && (msg.message != WM_MOUSEMOVE))
continue; /* We are not interested in other messages */
pt = msg.pt;
if (msg.message == WM_KEYDOWN) switch(msg.wParam)
{
case VK_UP: pt.y -= 8; break;
case VK_DOWN: pt.y += 8; break;
case VK_LEFT: pt.x -= 8; break;
case VK_RIGHT: pt.x += 8; break;
}
pt.x = max( pt.x, mouseRect.left );
pt.x = min( pt.x, mouseRect.right );
pt.y = max( pt.y, mouseRect.top );
pt.y = min( pt.y, mouseRect.bottom );
dx = pt.x - capturePoint.x;
dy = pt.y - capturePoint.y;
if (dx || dy)
{
if( !moved )
{
moved = TRUE;
if( iconic ) /* ok, no system popup tracking */
{
hOldCursor = SetCursor(hDragCursor);
ShowCursor( TRUE );
WinPosShowIconTitle( hwnd, FALSE );
}
}
if (msg.message == WM_KEYDOWN) SetCursorPos( pt.x, pt.y );
else
{
RECT newRect = sizingRect;
WPARAM wpSizingHit = 0;
if (hittest == HTCAPTION) OffsetRect( &newRect, dx, dy );
if (ON_LEFT_BORDER(hittest)) newRect.left += dx;
else if (ON_RIGHT_BORDER(hittest)) newRect.right += dx;
if (ON_TOP_BORDER(hittest)) newRect.top += dy;
else if (ON_BOTTOM_BORDER(hittest)) newRect.bottom += dy;
if(!iconic && !DragFullWindows) UserDrawMovingFrame( hdc, &sizingRect, thickframe );
capturePoint = pt;
/* determine the hit location */
if (hittest >= HTLEFT && hittest <= HTBOTTOMRIGHT)
wpSizingHit = WMSZ_LEFT + (hittest - HTLEFT);
SendMessageA( hwnd, WM_SIZING, wpSizingHit, (LPARAM)&newRect );
if (!iconic)
{
if(!DragFullWindows)
UserDrawMovingFrame( hdc, &newRect, thickframe );
else {
/* To avoid any deadlocks, all the locks on the windows
structures must be suspended before the SetWindowPos */
SetWindowPos( hwnd, 0, newRect.left, newRect.top,
newRect.right - newRect.left,
newRect.bottom - newRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
}
}
sizingRect = newRect;
}
}
}
ReleaseCapture();
if( iconic )
{
if( moved ) /* restore cursors, show icon title later on */
{
ShowCursor( FALSE );
SetCursor( hOldCursor );
}
DestroyCursor( hDragCursor );
}
else if(!DragFullWindows)
UserDrawMovingFrame( hdc, &sizingRect, thickframe );
if (Style & WS_CHILD)
ReleaseDC( hWndParent, hdc );
else
ReleaseDC( 0, hdc );
SendMessageA( hwnd, WM_EXITSIZEMOVE, 0, 0 );
SendMessageA( hwnd, WM_SETVISIBLE, !IsIconic(hwnd), 0L);
/* window moved or resized */
if (moved)
{
/* if the moving/resizing isn't canceled call SetWindowPos
* with the new position or the new size of the window
*/
if (!((msg.message == WM_KEYDOWN) && (msg.wParam == VK_ESCAPE)) )
{
/* NOTE: SWP_NOACTIVATE prevents document window activation in Word 6 */
if(!DragFullWindows)
SetWindowPos( hwnd, 0, sizingRect.left, sizingRect.top,
sizingRect.right - sizingRect.left,
sizingRect.bottom - sizingRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
}
else { /* restore previous size/position */
if(DragFullWindows)
SetWindowPos( hwnd, 0, origRect.left, origRect.top,
origRect.right - origRect.left,
origRect.bottom - origRect.top,
( hittest == HTCAPTION ) ? SWP_NOSIZE : 0 );
}
}
if( IsWindow(hwnd) )
if( Style & WS_MINIMIZE )
{
/* Single click brings up the system menu when iconized */
if( !moved )
{
if( Style & WS_SYSMENU )
SendMessageA( hwnd, WM_SYSCOMMAND,
SC_MOUSEMENU + HTSYSMENU, MAKELONG(pt.x,pt.y));
}
else WinPosShowIconTitle( hwnd, TRUE );
}
}
LRESULT
DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, POINT Pt)
{
switch (wParam & 0xfff0)
{
case SC_MOVE:
case SC_SIZE:
DefWndDoSizeMove(hWnd, wParam);
break;
case SC_CLOSE:
SendMessageA(hWnd, WM_CLOSE, 0, 0);
break;
case SC_MOUSEMENU:
MenuTrackMouseMenuBar(hWnd, wParam, Pt);
break;
case SC_KEYMENU:
MenuTrackKbdMenuBar(hWnd, wParam, Pt.x);
break;
default:
/* FIXME: Implement */
UNIMPLEMENTED;
break;
}
return(0);
}
VOID
DefWndAdjustRect(HWND hWnd, RECT* Rect, ULONG Style, BOOL Menu, ULONG ExStyle)
{
if (Style & WS_ICONIC)
{
return;
}
if (UserHasThickFrameStyle(Style, ExStyle))
{
InflateRect(Rect, GetSystemMetrics(SM_CXFRAME),
GetSystemMetrics(SM_CYFRAME));
}
else if (UserHasDlgFrameStyle(Style, ExStyle))
{
InflateRect(Rect, GetSystemMetrics(SM_CXDLGFRAME),
GetSystemMetrics(SM_CYDLGFRAME));
}
else if (UserHasThinFrameStyle(Style, ExStyle))
{
InflateRect(Rect, GetSystemMetrics(SM_CXBORDER),
GetSystemMetrics(SM_CYBORDER));
}
if (Style & WS_CAPTION)
{
Rect->top -= GetSystemMetrics(SM_CYCAPTION);
}
if (Menu)
{
//Rect->top -= GetSystemMetrics(SM_CYMENU);
Rect->top -= MenuGetMenuBarHeight(hWnd, Rect->right - Rect->left, -Rect->left, -Rect->top);
}
}
LRESULT STDCALL
DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT* Rect)
{
LRESULT Result = 0;
LONG ScrollXY;
NCCALCSIZE_PARAMS *SizeStruct = (NCCALCSIZE_PARAMS *)Rect;
RECT NewRect, TmpRect = {0, 0, 0, 0};
ULONG ExStyle = GetWindowLongW(hWnd, GWL_EXSTYLE);
LONG Style = GetClassLongW(hWnd, GCL_STYLE);
if (Style & CS_VREDRAW)
{
Result |= WVR_VREDRAW;
}
if (Style & CS_HREDRAW)
{
Result |= WVR_HREDRAW;
}
Style = GetWindowLongW(hWnd, GWL_STYLE);
if (!(Style & WS_MINIMIZE))
{
DefWndAdjustRect(hWnd, &TmpRect, Style, UserHasMenu(hWnd, Style), ExStyle);
if(CalcSizeStruct)
{
Rect = &(SizeStruct->rgrc[0]);
}
else
{
Result = 0;
}
NewRect.left = Rect->left - TmpRect.left;
NewRect.top = Rect->top - TmpRect.top;
NewRect.right = Rect->right - TmpRect.right;
NewRect.bottom = Rect->bottom - TmpRect.bottom;
if(NewRect.top > NewRect.bottom)
NewRect.bottom = NewRect.top;
if(NewRect.left > NewRect.right)
NewRect.right = NewRect.left;
if (Style & WS_VSCROLL)
{
ScrollXY = GetSystemMetrics(SM_CXVSCROLL);
if(NewRect.right - NewRect.left > ScrollXY)
{
NewRect.right -= ScrollXY + 1;
if (UserHasAnyFrameStyle(Style, ExStyle))
{
NewRect.right++;
}
}
}
if (Style & WS_HSCROLL)
{
ScrollXY = GetSystemMetrics(SM_CYHSCROLL);
if(NewRect.bottom - NewRect.top > ScrollXY)
{
NewRect.bottom -= ScrollXY + 1;
if (UserHasAnyFrameStyle(Style, ExStyle))
{
NewRect.bottom++;
}
}
}
Rect->left = NewRect.left;
Rect->top = NewRect.top;
Rect->right = NewRect.right;
Rect->bottom = NewRect.bottom;
}
return Result;
}
LRESULT
DefWndHandleWindowPosChanging(HWND hWnd, WINDOWPOS* Pos)
{
POINT maxSize, minTrack;
LONG style = GetWindowLongA(hWnd, GWL_STYLE);
if (Pos->flags & SWP_NOSIZE) return 0;
if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
{
WinPosGetMinMaxInfo(hWnd, &maxSize, NULL, &minTrack, NULL);
Pos->cx = min(Pos->cx, maxSize.x);
Pos->cy = min(Pos->cy, maxSize.y);
if (!(style & WS_MINIMIZE))
{
if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
}
}
return 0;
}
/* Undocumented flags. */
#define SWP_NOCLIENTMOVE 0x0800
#define SWP_NOCLIENTSIZE 0x1000
LRESULT
DefWndHandleWindowPosChanged(HWND hWnd, WINDOWPOS* Pos)
{
RECT Rect;
GetClientRect(hWnd, &Rect);
MapWindowPoints(hWnd, (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD ?
GetParent(hWnd) : NULL), (LPPOINT) &Rect, 2);
if (! (Pos->flags & SWP_NOCLIENTMOVE))
{
SendMessageW(hWnd, WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
}
if (! (Pos->flags & SWP_NOCLIENTSIZE))
{
WPARAM wp = SIZE_RESTORED;
if (IsZoomed(hWnd))
{
wp = SIZE_MAXIMIZED;
}
else if (IsIconic(hWnd))
{
wp = SIZE_MINIMIZED;
}
SendMessageW(hWnd, WM_SIZE, wp,
MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
}
return 0;
}
/***********************************************************************
* DefWndControlColor
*
* Default colors for control painting.
*/
static HBRUSH
DefWndControlColor(HDC hDC, UINT ctlType)
{
if (CTLCOLOR_SCROLLBAR == ctlType)
{
HBRUSH hb = GetSysColorBrush(COLOR_SCROLLBAR);
COLORREF bk = GetSysColor(COLOR_3DHILIGHT);
SetTextColor(hDC, GetSysColor(COLOR_3DFACE));
SetBkColor(hDC, bk);
/* if COLOR_WINDOW happens to be the same as COLOR_3DHILIGHT
* we better use 0x55aa bitmap brush to make scrollbar's background
* look different from the window background.
*/
if (bk == GetSysColor(COLOR_WINDOW))
{
#if 0 /* FIXME */
return CACHE_GetPattern55AABrush();
#else
return NULL;
#endif
}
UnrealizeObject(hb);
return hb;
}
SetTextColor(hDC, GetSysColor(COLOR_WINDOWTEXT));
if ((CTLCOLOR_EDIT == ctlType) || (CTLCOLOR_LISTBOX == ctlType))
{
SetBkColor(hDC, GetSysColor(COLOR_WINDOW));
}
else
{
SetBkColor(hDC, GetSysColor(COLOR_3DFACE));
return GetSysColorBrush(COLOR_3DFACE);
}
return GetSysColorBrush(COLOR_WINDOW);
}
LRESULT STDCALL
User32DefWindowProc(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam,
BOOL bUnicode)
{
switch (Msg)
{
case WM_NCPAINT:
{
return (DefWndPaintNC(hWnd, (HRGN)wParam));
}
case WM_NCCALCSIZE:
{
return (DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam));
}
case WM_WINDOWPOSCHANGING:
{
return (DefWndHandleWindowPosChanging(hWnd, (WINDOWPOS*)lParam));
}
case WM_WINDOWPOSCHANGED:
{
return (DefWndHandleWindowPosChanged(hWnd, (WINDOWPOS*)lParam));
}
case WM_NCHITTEST:
{
POINT Point;
Point.x = SLOWORD(lParam);
Point.y = SHIWORD(lParam);
return (DefWndHitTestNC(hWnd, Point));
}
case WM_NCLBUTTONDOWN:
{
return (DefWndHandleLButtonDownNC(hWnd, wParam, lParam));
}
case WM_NCLBUTTONUP:
{
return (DefWndHandleLButtonUpNC(hWnd, wParam, lParam));
}
case WM_LBUTTONDBLCLK:
case WM_NCLBUTTONDBLCLK:
{
return (DefWndHandleLButtonDblClkNC(hWnd, wParam, lParam));
}
case WM_NCRBUTTONDOWN:
{
if (wParam == HTCAPTION)
{
SetCapture(hWnd);
}
break;
}
case WM_RBUTTONUP:
{
POINT Pt;
if (hWnd == GetCapture())
{
ReleaseCapture();
}
Pt.x = SLOWORD(lParam);
Pt.y = SHIWORD(lParam);
ClientToScreen(hWnd, &Pt);
lParam = MAKELPARAM(Pt.x, Pt.y);
if (bUnicode)
{
SendMessageW(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
}
else
{
SendMessageA(hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, lParam);
}
break;
}
case WM_CONTEXTMENU:
{
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
{
if (bUnicode)
{
SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
}
else
{
SendMessageA(GetParent(hWnd), WM_CONTEXTMENU, wParam, lParam);
}
}
else
{
LONG HitCode;
POINT Pt;
Pt.x = SLOWORD(lParam);
Pt.y = SHIWORD(lParam);
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
{
ScreenToClient(GetParent(hWnd), &Pt);
}
HitCode = DefWndHitTestNC(hWnd, Pt);
if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
{
TrackPopupMenu(GetSystemMenu(hWnd, FALSE),
TPM_LEFTBUTTON | TPM_RIGHTBUTTON,
Pt.x, Pt.y, 0, hWnd, NULL);
}
}
break;
}
case WM_NCACTIVATE:
{
return (DefWndHandleActiveNC(hWnd, wParam));
}
case WM_PRINT:
{
/* FIXME: Implement. */
return (0);
}
case WM_PAINTICON:
case WM_PAINT:
{
PAINTSTRUCT Ps;
HDC hDC = BeginPaint(hWnd, &Ps);
if (hDC)
{
HICON hIcon;
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE &&
(hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON)) != NULL)
{
RECT WindowRect;
INT x, y;
GetWindowRect(hWnd, &WindowRect);
x = (WindowRect.right - WindowRect.left -
GetSystemMetrics(SM_CXICON)) / 2;
y = (WindowRect.bottom - WindowRect.top -
GetSystemMetrics(SM_CYICON)) / 2;
DrawIcon(hDC, x, y, hIcon);
}
if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_CLIENTEDGE)
{
RECT WindowRect;
GetClientRect(hWnd, &WindowRect);
DrawEdge(hDC, &WindowRect, EDGE_SUNKEN, BF_RECT);
}
EndPaint(hWnd, &Ps);
}
return (0);
}
case WM_SYNCPAINT:
{
HRGN hRgn;
hRgn = CreateRectRgn(0, 0, 0, 0);
if (GetUpdateRgn(hWnd, hRgn, FALSE) != NULLREGION)
{
RedrawWindow(hWnd, NULL, hRgn,
RDW_ERASENOW | RDW_ERASE | RDW_FRAME |
RDW_ALLCHILDREN);
}
DeleteObject(hRgn);
return (0);
}
case WM_SETREDRAW:
{
DefWndSetRedraw(hWnd, wParam);
return (0);
}
case WM_CLOSE:
{
DestroyWindow(hWnd);
return (0);
}
case WM_MOUSEACTIVATE:
{
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
{
LONG Ret;
if (bUnicode)
{
Ret = SendMessageW(GetParent(hWnd), WM_MOUSEACTIVATE,
wParam, lParam);
}
else
{
Ret = SendMessageA(GetParent(hWnd), WM_MOUSEACTIVATE,
wParam, lParam);
}
if (Ret)
{
return (Ret);
}
}
return ((LOWORD(lParam) >= HTCLIENT) ? MA_ACTIVATE : MA_NOACTIVATE);
}
case WM_ACTIVATE:
{
/* Check if the window is minimized. */
if (LOWORD(lParam) != WA_INACTIVE &&
!(GetWindowLongW(hWnd, GWL_STYLE) & WS_MINIMIZE))
{
SetFocus(hWnd);
}
break;
}
case WM_MOUSEWHEEL:
{
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
{
if (bUnicode)
{
return (SendMessageW(GetParent(hWnd), WM_MOUSEWHEEL,
wParam, lParam));
}
else
{
return (SendMessageA(GetParent(hWnd), WM_MOUSEWHEEL,
wParam, lParam));
}
}
break;
}
case WM_ERASEBKGND:
case WM_ICONERASEBKGND:
{
RECT Rect;
HBRUSH hBrush = (HBRUSH)GetClassLongW(hWnd, GCL_HBRBACKGROUND);
if (NULL == hBrush)
{
return 0;
}
if (0 == (((DWORD) hBrush) & 0xffff0000))
{
hBrush = GetSysColorBrush((DWORD) hBrush - 1);
}
GetClipBox((HDC)wParam, &Rect);
FillRect((HDC)wParam, &Rect, hBrush);
return (1);
}
case WM_CTLCOLORMSGBOX:
case WM_CTLCOLOREDIT:
case WM_CTLCOLORLISTBOX:
case WM_CTLCOLORBTN:
case WM_CTLCOLORDLG:
case WM_CTLCOLORSTATIC:
case WM_CTLCOLORSCROLLBAR:
return (LRESULT) DefWndControlColor((HDC)wParam, Msg - WM_CTLCOLORMSGBOX);
case WM_SETCURSOR:
{
if (GetWindowLongW(hWnd, GWL_STYLE) & WS_CHILD)
{
if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
{
BOOL bResult;
if (bUnicode)
{
bResult = SendMessageW(GetParent(hWnd), WM_SETCURSOR,
wParam, lParam);
}
else
{
bResult = SendMessageA(GetParent(hWnd), WM_SETCURSOR,
wParam, lParam);
}
if (bResult)
{
return(TRUE);
}
}
}
return (DefWndHandleSetCursor(hWnd, wParam, lParam));
}
case WM_SYSCOMMAND:
{
POINT Pt;
Pt.x = SLOWORD(lParam);
Pt.y = SHIWORD(lParam);
return (DefWndHandleSysCommand(hWnd, wParam, Pt));
}
/* FIXME: Handle key messages. */
/*
case WM_KEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_SYSCHAR:
*/
/* FIXME: This is also incomplete. */
case WM_SYSKEYDOWN:
{
if (HIWORD(lParam) & KEYDATA_ALT)
{
if (wParam == VK_F4) /* Try to close the window */
{
HWND top = GetAncestor(hWnd, GA_ROOT);
if (!(GetClassLongW(top, GCL_STYLE) & CS_NOCLOSE))
{
if (bUnicode)
PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
else
PostMessageA(top, WM_SYSCOMMAND, SC_CLOSE, 0);
}
}
}
break;
}
case WM_SHOWWINDOW:
{
LONG Style;
if (!lParam)
return 0;
Style = GetWindowLongW(hWnd, GWL_STYLE);
if (!(Style & WS_POPUP))
return 0;
if ((Style & WS_VISIBLE) && wParam)
return 0;
if (!(Style & WS_VISIBLE) && !wParam)
return 0;
if (!GetWindow(hWnd, GW_OWNER))
return 0;
ShowWindow(hWnd, wParam ? SW_SHOWNA : SW_HIDE);
break;
}
case WM_CANCELMODE:
{
/* FIXME: Check for a desktop. */
if (GetCapture() == hWnd)
{
ReleaseCapture();
}
break;
}
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
return (-1);
case WM_DROPOBJECT:
/* FIXME: Implement this. */
break;
case WM_QUERYDROPOBJECT:
{
if (GetWindowLongW(hWnd, GWL_EXSTYLE) & WS_EX_ACCEPTFILES)
{
return(1);
}
break;
}
case WM_QUERYDRAGICON:
{
UINT Len;
HICON hIcon;
hIcon = (HICON)GetClassLongW(hWnd, GCL_HICON);
if (hIcon)
{
return ((LRESULT)hIcon);
}
for (Len = 1; Len < 64; Len++)
{
if ((hIcon = LoadIconW(NULL, MAKEINTRESOURCEW(Len))) != NULL)
{
return((LRESULT)hIcon);
}
}
return ((LRESULT)LoadIconW(0, IDI_APPLICATION));
}
/* FIXME: WM_ISACTIVEICON */
case WM_NOTIFYFORMAT:
{
if (IsWindowUnicode(hWnd))
{
return(NFR_UNICODE);
}
else
{
return(NFR_ANSI);
}
}
case WM_SETICON:
{
INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
HICON hOldIcon = (HICON)GetClassLongW(hWnd, Index);
SetClassLongW(hWnd, Index, lParam);
SetWindowPos(hWnd, 0, 0, 0, 0, 0,
SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOMOVE |
SWP_NOACTIVATE | SWP_NOZORDER);
return ((LRESULT)hOldIcon);
}
case WM_GETICON:
{
INT Index = (wParam != 0) ? GCL_HICON : GCL_HICONSM;
return (GetClassLongW(hWnd, Index));
}
case WM_HELP:
{
if (bUnicode)
{
SendMessageW(GetParent(hWnd), Msg, wParam, lParam);
}
else
{
SendMessageA(GetParent(hWnd), Msg, wParam, lParam);
}
break;
}
case WM_QUERYOPEN:
case WM_QUERYENDSESSION:
{
return (1);
}
}
return 0;
}
LRESULT STDCALL
DefWindowProcA(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
static LPSTR WindowTextAtom = 0;
PSTR WindowText;
switch (Msg)
{
case WM_NCCREATE:
{
CREATESTRUCTA *Cs = (CREATESTRUCTA*)lParam;
if (HIWORD(Cs->lpszName))
{
if (0 == WindowTextAtom)
{
WindowTextAtom =
(LPSTR)(ULONG)GlobalAddAtomA("USER32!WindowTextAtomA");
}
WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
strlen(Cs->lpszName) * sizeof(CHAR));
strcpy(WindowText, Cs->lpszName);
SetPropA(hWnd, WindowTextAtom, WindowText);
}
return (1);
}
case WM_GETTEXTLENGTH:
{
if (WindowTextAtom == 0 ||
(WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
{
return(0);
}
return (strlen(WindowText));
}
case WM_GETTEXT:
{
if (WindowTextAtom == 0 ||
(WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
{
if (wParam > 1)
{
*((PSTR)lParam) = '\0';
}
return (0);
}
strncpy((LPSTR)lParam, WindowText, wParam);
return (min(wParam, strlen(WindowText)));
}
case WM_SETTEXT:
{
if (0 == WindowTextAtom)
{
WindowTextAtom =
(LPSTR)(DWORD)GlobalAddAtomA("USER32!WindowTextAtomA");
}
if (WindowTextAtom != 0 &&
(WindowText = GetPropA(hWnd, WindowTextAtom)) == NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
}
WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
(strlen((PSTR)lParam) + 1) * sizeof(CHAR));
strcpy(WindowText, (PSTR)lParam);
SetPropA(hWnd, WindowTextAtom, WindowText);
if (0 != (GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION))
{
DefWndPaintNC(hWnd, (HRGN) 1);
}
return (1);
}
/*
FIXME: Implement these.
case WM_IME_CHAR:
case WM_IME_KEYDOWN:
case WM_IME_KEYUP:
case WM_IME_STARTCOMPOSITION:
case WM_IME_COMPOSITION:
case WM_IME_ENDCOMPOSITION:
case WM_IME_SELECT:
case WM_IME_SETCONTEXT:
*/
case WM_NCDESTROY:
{
if (WindowTextAtom != 0 &&
(WindowText = RemovePropA(hWnd, WindowTextAtom)) == NULL)
{
RtlFreeHeap(GetProcessHeap(), 0, WindowText);
}
return(0);
}
}
return User32DefWindowProc(hWnd, Msg, wParam, lParam, FALSE);
}
LRESULT STDCALL
DefWindowProcW(HWND hWnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam)
{
static LPWSTR WindowTextAtom = 0;
PWSTR WindowText;
switch (Msg)
{
case WM_NCCREATE:
{
CREATESTRUCTW* CreateStruct = (CREATESTRUCTW*)lParam;
if (HIWORD(CreateStruct->lpszName))
{
if (0 == WindowTextAtom)
{
WindowTextAtom =
(LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
}
WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
wcslen(CreateStruct->lpszName) * sizeof(WCHAR));
wcscpy(WindowText, CreateStruct->lpszName);
SetPropW(hWnd, WindowTextAtom, WindowText);
}
return (1);
}
case WM_GETTEXTLENGTH:
{
if (WindowTextAtom == 0 ||
(WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
{
return(0);
}
return (wcslen(WindowText));
}
case WM_GETTEXT:
{
if (WindowTextAtom == 0 ||
(WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
{
if (wParam > 1)
{
((PWSTR)lParam) = '\0';
}
return (0);
}
wcsncpy((PWSTR)lParam, WindowText, wParam);
return (min(wParam, wcslen(WindowText)));
}
case WM_SETTEXT:
{
if (WindowTextAtom == 0)
{
WindowTextAtom =
(LPWSTR)(DWORD)GlobalAddAtomW(L"USER32!WindowTextAtomW");
}
if (WindowTextAtom != 0 &&
(WindowText = GetPropW(hWnd, WindowTextAtom)) == NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
}
WindowText = RtlAllocateHeap(RtlGetProcessHeap(), 0,
(wcslen((PWSTR)lParam) + 1) * sizeof(WCHAR));
wcscpy(WindowText, (PWSTR)lParam);
SetPropW(hWnd, WindowTextAtom, WindowText);
if ((GetWindowLongW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
{
DefWndPaintNC(hWnd, (HRGN)1);
}
return (1);
}
case WM_IME_CHAR:
{
SendMessageW(hWnd, WM_CHAR, wParam, lParam);
return (0);
}
case WM_IME_SETCONTEXT:
{
/* FIXME */
return (0);
}
case WM_NCDESTROY:
{
if (WindowTextAtom != 0 &&
(WindowText = RemovePropW(hWnd, WindowTextAtom)) == NULL)
{
RtlFreeHeap(RtlGetProcessHeap(), 0, WindowText);
}
return (0);
}
}
return User32DefWindowProc(hWnd, Msg, wParam, lParam, TRUE);
}