mirror of
https://github.com/reactos/reactos.git
synced 2024-08-29 22:58:34 +00:00
![Denis Malikov](/assets/img/avatar_default.png)
InternalPos.NormalRect is a key data for detecting whether a window was snapped. Keeping it after restore affecting next snap actions. CORE-16477
1300 lines
40 KiB
C
1300 lines
40 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Win32k subsystem
|
|
* PURPOSE: Miscellaneous User functions
|
|
* FILE: win32ss/user/ntuser/defwnd.c
|
|
* PROGRAMER:
|
|
*/
|
|
|
|
#include <win32k.h>
|
|
#include <windowsx.h>
|
|
|
|
DBG_DEFAULT_CHANNEL(UserDefwnd);
|
|
|
|
INT WINAPI DrawTextExWorker( HDC hdc, LPWSTR str, INT i_count,
|
|
LPRECT rect, UINT flags, LPDRAWTEXTPARAMS dtp );
|
|
|
|
INT WINAPI DrawTextW( HDC hdc, LPCWSTR str, INT count, LPRECT rect, UINT flags )
|
|
{
|
|
DRAWTEXTPARAMS dtp;
|
|
|
|
memset (&dtp, 0, sizeof(dtp));
|
|
dtp.cbSize = sizeof(dtp);
|
|
if (flags & DT_TABSTOP)
|
|
{
|
|
dtp.iTabLength = (flags >> 8) & 0xff;
|
|
flags &= 0xffff00ff;
|
|
}
|
|
return DrawTextExWorker(hdc, (LPWSTR)str, count, rect, flags, &dtp);
|
|
}
|
|
|
|
|
|
HBRUSH FASTCALL
|
|
DefWndControlColor(HDC hDC, UINT ctlType)
|
|
{
|
|
if (ctlType == CTLCOLOR_SCROLLBAR)
|
|
{
|
|
HBRUSH hb = IntGetSysColorBrush(COLOR_SCROLLBAR);
|
|
COLORREF bk = IntGetSysColor(COLOR_3DHILIGHT);
|
|
IntGdiSetTextColor(hDC, IntGetSysColor(COLOR_3DFACE));
|
|
IntGdiSetBkColor(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 == IntGetSysColor(COLOR_WINDOW))
|
|
return gpsi->hbrGray;
|
|
|
|
NtGdiUnrealizeObject( hb );
|
|
return hb;
|
|
}
|
|
|
|
IntGdiSetTextColor(hDC, IntGetSysColor(COLOR_WINDOWTEXT));
|
|
|
|
if ((ctlType == CTLCOLOR_EDIT) || (ctlType == CTLCOLOR_LISTBOX))
|
|
{
|
|
IntGdiSetBkColor(hDC, IntGetSysColor(COLOR_WINDOW));
|
|
}
|
|
else
|
|
{
|
|
IntGdiSetBkColor(hDC, IntGetSysColor(COLOR_3DFACE));
|
|
return IntGetSysColorBrush(COLOR_3DFACE);
|
|
}
|
|
|
|
return IntGetSysColorBrush(COLOR_WINDOW);
|
|
}
|
|
|
|
LRESULT FASTCALL
|
|
DefWndHandleWindowPosChanging(PWND pWnd, WINDOWPOS* Pos)
|
|
{
|
|
POINT maxTrack, minTrack;
|
|
LONG style = pWnd->style;
|
|
|
|
if (Pos->flags & SWP_NOSIZE) return 0;
|
|
if ((style & WS_THICKFRAME) || ((style & (WS_POPUP | WS_CHILD)) == 0))
|
|
{
|
|
co_WinPosGetMinMaxInfo(pWnd, NULL, NULL, &minTrack, &maxTrack);
|
|
Pos->cx = min(Pos->cx, maxTrack.x);
|
|
Pos->cy = min(Pos->cy, maxTrack.y);
|
|
if (!(style & WS_MINIMIZE))
|
|
{
|
|
if (Pos->cx < minTrack.x) Pos->cx = minTrack.x;
|
|
if (Pos->cy < minTrack.y) Pos->cy = minTrack.y;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Pos->cx = max(Pos->cx, 0);
|
|
Pos->cy = max(Pos->cy, 0);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
LRESULT FASTCALL
|
|
DefWndHandleWindowPosChanged(PWND pWnd, WINDOWPOS* Pos)
|
|
{
|
|
RECT Rect;
|
|
LONG style = pWnd->style;
|
|
|
|
IntGetClientRect(pWnd, &Rect);
|
|
IntMapWindowPoints(pWnd, (style & WS_CHILD ? IntGetParent(pWnd) : NULL), (LPPOINT) &Rect, 2);
|
|
|
|
if (!(Pos->flags & SWP_NOCLIENTMOVE))
|
|
{
|
|
co_IntSendMessage(UserHMGetHandle(pWnd), WM_MOVE, 0, MAKELONG(Rect.left, Rect.top));
|
|
}
|
|
|
|
if (!(Pos->flags & SWP_NOCLIENTSIZE) || (Pos->flags & SWP_STATECHANGED))
|
|
{
|
|
if (style & WS_MINIMIZE) co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, SIZE_MINIMIZED, 0 );
|
|
else
|
|
{
|
|
WPARAM wp = (style & WS_MAXIMIZE) ? SIZE_MAXIMIZED : SIZE_RESTORED;
|
|
co_IntSendMessage(UserHMGetHandle(pWnd), WM_SIZE, wp, MAKELONG(Rect.right - Rect.left, Rect.bottom - Rect.top));
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Handle a WM_SYSCOMMAND message. Called from DefWindowProc().
|
|
//
|
|
LRESULT FASTCALL
|
|
DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LRESULT lResult = 0;
|
|
BOOL Hook = FALSE;
|
|
|
|
if (ISITHOOKED(WH_CBT) || (pWnd->head.rpdesk->pDeskInfo->fsHooks & HOOKID_TO_FLAG(WH_CBT)))
|
|
{
|
|
Hook = TRUE;
|
|
lResult = co_HOOK_CallHooks(WH_CBT, HCBT_SYSCOMMAND, wParam, lParam);
|
|
|
|
if (lResult) return lResult;
|
|
}
|
|
|
|
switch (wParam & 0xfff0)
|
|
{
|
|
case SC_MOVE:
|
|
case SC_SIZE:
|
|
DefWndDoSizeMove(pWnd, wParam);
|
|
break;
|
|
|
|
case SC_MINIMIZE:
|
|
if (UserHMGetHandle(pWnd) == UserGetActiveWindow())
|
|
IntShowOwnedPopups(pWnd,FALSE); // This is done in ShowWindow! Need to retest!
|
|
co_WinPosShowWindow( pWnd, SW_MINIMIZE );
|
|
break;
|
|
|
|
case SC_MAXIMIZE:
|
|
if (((pWnd->style & WS_MINIMIZE) != 0) && UserHMGetHandle(pWnd) == UserGetActiveWindow())
|
|
IntShowOwnedPopups(pWnd,TRUE);
|
|
co_WinPosShowWindow( pWnd, SW_MAXIMIZE );
|
|
break;
|
|
|
|
case SC_RESTORE:
|
|
if (((pWnd->style & WS_MINIMIZE) != 0) && UserHMGetHandle(pWnd) == UserGetActiveWindow())
|
|
IntShowOwnedPopups(pWnd,TRUE);
|
|
co_WinPosShowWindow( pWnd, SW_RESTORE );
|
|
break;
|
|
|
|
case SC_CLOSE:
|
|
return co_IntSendMessage(UserHMGetHandle(pWnd), WM_CLOSE, 0, 0);
|
|
|
|
case SC_SCREENSAVE:
|
|
ERR("Screensaver Called!\n");
|
|
UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_START_SCREENSAVE, 0); // always lParam 0 == not Secure
|
|
break;
|
|
|
|
case SC_HOTKEY:
|
|
{
|
|
USER_REFERENCE_ENTRY Ref;
|
|
|
|
pWnd = ValidateHwndNoErr((HWND)lParam);
|
|
if (pWnd)
|
|
{
|
|
if (pWnd->spwndLastActive)
|
|
{
|
|
pWnd = pWnd->spwndLastActive;
|
|
}
|
|
UserRefObjectCo(pWnd, &Ref);
|
|
co_IntSetForegroundWindow(pWnd);
|
|
UserDerefObjectCo(pWnd);
|
|
if (pWnd->style & WS_MINIMIZE)
|
|
{
|
|
UserPostMessage(UserHMGetHandle(pWnd), WM_SYSCOMMAND, SC_RESTORE, 0);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
// case SC_DEFAULT:
|
|
case SC_MOUSEMENU:
|
|
{
|
|
POINT Pt;
|
|
Pt.x = (short)LOWORD(lParam);
|
|
Pt.y = (short)HIWORD(lParam);
|
|
MENU_TrackMouseMenuBar(pWnd, wParam & 0x000f, Pt);
|
|
}
|
|
break;
|
|
|
|
case SC_KEYMENU:
|
|
MENU_TrackKbdMenuBar(pWnd, wParam, (WCHAR)lParam);
|
|
break;
|
|
|
|
|
|
default:
|
|
// We do not support anything else here so we should return normal even when sending a hook.
|
|
return 0;
|
|
}
|
|
|
|
return(Hook ? 1 : 0); // Don't call us again from user space.
|
|
}
|
|
|
|
PWND FASTCALL
|
|
co_IntFindChildWindowToOwner(PWND Root, PWND Owner)
|
|
{
|
|
PWND Ret;
|
|
PWND Child, OwnerWnd;
|
|
|
|
for(Child = Root->spwndChild; Child; Child = Child->spwndNext)
|
|
{
|
|
OwnerWnd = Child->spwndOwner;
|
|
if(!OwnerWnd)
|
|
continue;
|
|
|
|
if (!(Child->style & WS_POPUP) ||
|
|
!(Child->style & WS_VISIBLE) ||
|
|
/* Fixes CMD pop up properties window from having foreground. */
|
|
Owner->head.pti->MessageQueue != Child->head.pti->MessageQueue)
|
|
continue;
|
|
|
|
if(OwnerWnd == Owner)
|
|
{
|
|
Ret = Child;
|
|
return Ret;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
LRESULT
|
|
DefWndHandleSetCursor(PWND pWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
PWND pwndPopUP = NULL;
|
|
WORD Msg = HIWORD(lParam);
|
|
|
|
/* Not for child windows. */
|
|
if (UserHMGetHandle(pWnd) != (HWND)wParam)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
switch((short)LOWORD(lParam))
|
|
{
|
|
case HTERROR:
|
|
{
|
|
//// This is the real fix for CORE-6129! This was a "Code hole".
|
|
USER_REFERENCE_ENTRY Ref;
|
|
|
|
if (Msg == WM_LBUTTONDOWN)
|
|
{
|
|
// Find a pop up window to bring active.
|
|
pwndPopUP = co_IntFindChildWindowToOwner(UserGetDesktopWindow(), pWnd);
|
|
if (pwndPopUP)
|
|
{
|
|
// Not a child pop up from desktop.
|
|
if ( pwndPopUP != UserGetDesktopWindow()->spwndChild )
|
|
{
|
|
// Get original active window.
|
|
PWND pwndOrigActive = gpqForeground->spwndActive;
|
|
|
|
co_WinPosSetWindowPos(pWnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
|
|
|
UserRefObjectCo(pwndPopUP, &Ref);
|
|
//UserSetActiveWindow(pwndPopUP);
|
|
co_IntSetForegroundWindow(pwndPopUP); // HACK
|
|
UserDerefObjectCo(pwndPopUP);
|
|
|
|
// If the change was made, break out.
|
|
if (pwndOrigActive != gpqForeground->spwndActive)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
////
|
|
if (Msg == WM_LBUTTONDOWN || Msg == WM_MBUTTONDOWN ||
|
|
Msg == WM_RBUTTONDOWN || Msg == WM_XBUTTONDOWN)
|
|
{
|
|
if (pwndPopUP)
|
|
{
|
|
FLASHWINFO fwi =
|
|
{sizeof(FLASHWINFO),
|
|
UserHMGetHandle(pwndPopUP),
|
|
FLASHW_ALL,
|
|
gspv.dwForegroundFlashCount,
|
|
(gpsi->dtCaretBlink >> 3)};
|
|
|
|
// Now shake that window!
|
|
IntFlashWindowEx(pwndPopUP, &fwi);
|
|
}
|
|
UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case HTCLIENT:
|
|
{
|
|
if (pWnd->pcls->spcur)
|
|
{
|
|
IntSystemSetCursor(pWnd->pcls->spcur);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
case HTLEFT:
|
|
case HTRIGHT:
|
|
{
|
|
if (pWnd->style & WS_MAXIMIZE)
|
|
{
|
|
break;
|
|
}
|
|
IntSystemSetCursor(SYSTEMCUR(SIZEWE));
|
|
return TRUE;
|
|
}
|
|
|
|
case HTTOP:
|
|
case HTBOTTOM:
|
|
{
|
|
if (pWnd->style & WS_MAXIMIZE)
|
|
{
|
|
break;
|
|
}
|
|
IntSystemSetCursor(SYSTEMCUR(SIZENS));
|
|
return TRUE;
|
|
}
|
|
|
|
case HTTOPLEFT:
|
|
case HTBOTTOMRIGHT:
|
|
{
|
|
if (pWnd->style & WS_MAXIMIZE)
|
|
{
|
|
break;
|
|
}
|
|
IntSystemSetCursor(SYSTEMCUR(SIZENWSE));
|
|
return TRUE;
|
|
}
|
|
|
|
case HTBOTTOMLEFT:
|
|
case HTTOPRIGHT:
|
|
{
|
|
if (pWnd->style & WS_MAXIMIZE)
|
|
{
|
|
break;
|
|
}
|
|
IntSystemSetCursor(SYSTEMCUR(SIZENESW));
|
|
return TRUE;
|
|
}
|
|
}
|
|
IntSystemSetCursor(SYSTEMCUR(ARROW));
|
|
return FALSE;
|
|
}
|
|
|
|
VOID FASTCALL DefWndPrint( PWND pwnd, HDC hdc, ULONG uFlags)
|
|
{
|
|
/*
|
|
* Visibility flag.
|
|
*/
|
|
if ( (uFlags & PRF_CHECKVISIBLE) &&
|
|
!IntIsWindowVisible(pwnd) )
|
|
return;
|
|
|
|
/*
|
|
* Unimplemented flags.
|
|
*/
|
|
if ( (uFlags & PRF_CHILDREN) ||
|
|
(uFlags & PRF_OWNED) ||
|
|
(uFlags & PRF_NONCLIENT) )
|
|
{
|
|
FIXME("WM_PRINT message with unsupported flags\n");
|
|
}
|
|
|
|
/*
|
|
* Background
|
|
*/
|
|
if ( uFlags & PRF_ERASEBKGND)
|
|
co_IntSendMessage(UserHMGetHandle(pwnd), WM_ERASEBKGND, (WPARAM)hdc, 0);
|
|
|
|
/*
|
|
* Client area
|
|
*/
|
|
if ( uFlags & PRF_CLIENT)
|
|
co_IntSendMessage(UserHMGetHandle(pwnd), WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
|
|
}
|
|
|
|
BOOL
|
|
UserPaintCaption(PWND pWnd, INT Flags)
|
|
{
|
|
BOOL Ret = FALSE;
|
|
|
|
if ( (pWnd->style & WS_VISIBLE) && ((pWnd->style & WS_CAPTION) == WS_CAPTION) )
|
|
{
|
|
if (pWnd->state & WNDS_HASCAPTION && pWnd->head.pti->MessageQueue == gpqForeground)
|
|
Flags |= DC_ACTIVE;
|
|
/*
|
|
* When themes are not enabled we can go on and paint the non client area.
|
|
* However if we do that with themes enabled we will draw a classic frame.
|
|
* This is solved by sending a themes specific message to notify the themes
|
|
* engine that the caption needs to be redrawn
|
|
*/
|
|
if (gpsi->dwSRVIFlags & SRVINFO_APIHOOK)
|
|
{
|
|
/*
|
|
* This will cause uxtheme to either paint the themed caption or call
|
|
* RealUserDrawCaption in order to draw the classic caption when themes
|
|
* are disabled but the themes service is enabled
|
|
*/
|
|
TRACE("UDCB Flags %08x\n", Flags);
|
|
co_IntSendMessage(UserHMGetHandle(pWnd), WM_NCUAHDRAWCAPTION, Flags, 0);
|
|
}
|
|
else
|
|
{
|
|
HDC hDC = UserGetDCEx(pWnd, NULL, DCX_WINDOW|DCX_USESTYLE);
|
|
UserDrawCaptionBar(pWnd, hDC, Flags | DC_FRAME); // DCFRAME added as fix for CORE-10855.
|
|
UserReleaseDC(pWnd, hDC, FALSE);
|
|
}
|
|
Ret = TRUE;
|
|
}
|
|
// Support window tray
|
|
return Ret;
|
|
}
|
|
|
|
// WM_SETICON
|
|
LRESULT FASTCALL
|
|
DefWndSetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HICON hIcon, hIconSmall, hIconOld;
|
|
|
|
if ( wParam > ICON_SMALL2 )
|
|
{
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
hIconSmall = UserGetProp(pWnd, gpsi->atomIconSmProp, TRUE);
|
|
hIcon = UserGetProp(pWnd, gpsi->atomIconProp, TRUE);
|
|
|
|
hIconOld = wParam == ICON_BIG ? hIcon : hIconSmall;
|
|
|
|
switch(wParam)
|
|
{
|
|
case ICON_BIG:
|
|
hIcon = (HICON)lParam;
|
|
break;
|
|
case ICON_SMALL:
|
|
hIconSmall = (HICON)lParam;
|
|
break;
|
|
case ICON_SMALL2:
|
|
ERR("FIXME: Set ICON_SMALL2 support!\n");
|
|
default:
|
|
break;
|
|
}
|
|
|
|
UserSetProp(pWnd, gpsi->atomIconProp, hIcon, TRUE);
|
|
UserSetProp(pWnd, gpsi->atomIconSmProp, hIconSmall, TRUE);
|
|
|
|
if ((pWnd->style & WS_CAPTION ) == WS_CAPTION)
|
|
UserPaintCaption(pWnd, DC_ICON);
|
|
|
|
return (LRESULT)hIconOld;
|
|
}
|
|
|
|
LRESULT FASTCALL
|
|
DefWndGetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HICON hIconRet;
|
|
if ( wParam > ICON_SMALL2 )
|
|
{
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
switch(wParam)
|
|
{
|
|
case ICON_BIG:
|
|
hIconRet = UserGetProp(pWnd, gpsi->atomIconProp, TRUE);
|
|
break;
|
|
case ICON_SMALL:
|
|
case ICON_SMALL2:
|
|
hIconRet = UserGetProp(pWnd, gpsi->atomIconSmProp, TRUE);
|
|
break;
|
|
DEFAULT_UNREACHABLE;
|
|
}
|
|
return (LRESULT)hIconRet;
|
|
}
|
|
|
|
VOID FASTCALL
|
|
DefWndScreenshot(PWND pWnd)
|
|
{
|
|
RECT rect;
|
|
HDC hdc;
|
|
INT w;
|
|
INT h;
|
|
HBITMAP hbitmap;
|
|
HDC hdc2;
|
|
SETCLIPBDATA scd = {FALSE, FALSE};
|
|
|
|
UserOpenClipboard(UserHMGetHandle(pWnd));
|
|
UserEmptyClipboard();
|
|
|
|
hdc = UserGetWindowDC(pWnd);
|
|
IntGetWindowRect(pWnd, &rect);
|
|
w = rect.right - rect.left;
|
|
h = rect.bottom - rect.top;
|
|
|
|
hbitmap = NtGdiCreateCompatibleBitmap(hdc, w, h);
|
|
hdc2 = NtGdiCreateCompatibleDC(hdc);
|
|
NtGdiSelectBitmap(hdc2, hbitmap);
|
|
|
|
NtGdiBitBlt(hdc2, 0, 0, w, h, hdc, 0, 0, SRCCOPY, 0, 0);
|
|
|
|
UserSetClipboardData(CF_BITMAP, hbitmap, &scd);
|
|
|
|
UserReleaseDC(pWnd, hdc, FALSE);
|
|
UserReleaseDC(pWnd, hdc2, FALSE);
|
|
|
|
UserCloseClipboard();
|
|
}
|
|
|
|
/*
|
|
Win32k counterpart of User DefWindowProc
|
|
*/
|
|
LRESULT FASTCALL
|
|
IntDefWindowProc(
|
|
PWND Wnd,
|
|
UINT Msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
BOOL Ansi)
|
|
{
|
|
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
|
|
LRESULT lResult = 0;
|
|
USER_REFERENCE_ENTRY Ref;
|
|
BOOL IsTaskBar;
|
|
DWORD Style;
|
|
DWORD ExStyle;
|
|
|
|
if (Msg > WM_USER) return 0;
|
|
|
|
switch (Msg)
|
|
{
|
|
case WM_DEVICECHANGE:
|
|
return TRUE;
|
|
|
|
case WM_GETTEXTLENGTH:
|
|
{
|
|
PWSTR buf;
|
|
ULONG len;
|
|
|
|
if (Wnd != NULL && Wnd->strName.Length != 0)
|
|
{
|
|
buf = Wnd->strName.Buffer;
|
|
if (buf != NULL &&
|
|
NT_SUCCESS(RtlUnicodeToMultiByteSize(&len,
|
|
buf,
|
|
Wnd->strName.Length)))
|
|
{
|
|
lResult = (LRESULT) (Wnd->strName.Length / sizeof(WCHAR));
|
|
}
|
|
}
|
|
else lResult = 0L;
|
|
|
|
break;
|
|
}
|
|
|
|
case WM_GETTEXT: // FIXME: Handle Ansi
|
|
{
|
|
PWSTR buf = NULL;
|
|
PWSTR outbuf = (PWSTR)lParam;
|
|
|
|
if (Wnd != NULL && wParam != 0)
|
|
{
|
|
if (Wnd->strName.Buffer != NULL)
|
|
buf = Wnd->strName.Buffer;
|
|
else
|
|
outbuf[0] = L'\0';
|
|
|
|
if (buf != NULL)
|
|
{
|
|
if (Wnd->strName.Length != 0)
|
|
{
|
|
lResult = min(Wnd->strName.Length / sizeof(WCHAR), wParam - 1);
|
|
RtlCopyMemory(outbuf,
|
|
buf,
|
|
lResult * sizeof(WCHAR));
|
|
outbuf[lResult] = L'\0';
|
|
}
|
|
else
|
|
outbuf[0] = L'\0';
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_SETTEXT: // FIXME: Handle Ansi
|
|
{
|
|
DefSetText(Wnd, (PCWSTR)lParam);
|
|
|
|
if ((Wnd->style & WS_CAPTION) == WS_CAPTION)
|
|
UserPaintCaption(Wnd, DC_TEXT);
|
|
IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, Wnd, OBJID_WINDOW, CHILDID_SELF, 0);
|
|
lResult = 1;
|
|
break;
|
|
}
|
|
|
|
case WM_SYSCOMMAND:
|
|
{
|
|
TRACE("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam );
|
|
lResult = DefWndHandleSysCommand(Wnd, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_SHOWWINDOW:
|
|
{
|
|
if ((Wnd->style & WS_VISIBLE) && wParam) break;
|
|
if (!(Wnd->style & WS_VISIBLE) && !wParam) break;
|
|
if (!Wnd->spwndOwner) break;
|
|
if (LOWORD(lParam))
|
|
{
|
|
co_WinPosShowWindow(Wnd, wParam ? SW_SHOWNOACTIVATE : SW_HIDE);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_CLIENTSHUTDOWN:
|
|
return IntClientShutdown(Wnd, wParam, lParam);
|
|
|
|
case WM_APPCOMMAND:
|
|
if ( (Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
|
|
Wnd != co_GetDesktopWindow(Wnd) )
|
|
{
|
|
if (!co_HOOK_CallHooks(WH_SHELL, HSHELL_APPCOMMAND, wParam, lParam))
|
|
co_IntShellHookNotify(HSHELL_APPCOMMAND, wParam, lParam);
|
|
break;
|
|
}
|
|
UserRefObjectCo(Wnd->spwndParent, &Ref);
|
|
lResult = co_IntSendMessage(UserHMGetHandle(Wnd->spwndParent), WM_APPCOMMAND, wParam, lParam);
|
|
UserDerefObjectCo(Wnd->spwndParent);
|
|
break;
|
|
|
|
case WM_KEYF1:
|
|
{
|
|
HELPINFO hi;
|
|
HMENU hMenu = UlongToHandle(Wnd->IDMenu);
|
|
PWND pwndActive = MENU_IsMenuActive();
|
|
hi.cbSize = sizeof(HELPINFO);
|
|
hi.MousePos = gpsi->ptCursor;
|
|
hi.iContextType = HELPINFO_MENUITEM;
|
|
hi.hItemHandle = pwndActive ? UserHMGetHandle(pwndActive) : UserHMGetHandle(Wnd);
|
|
hi.iCtrlId = (Wnd->style & (WS_POPUP|WS_CHILD)) == WS_CHILD ? IntMenuItemFromPoint(Wnd, hMenu, hi.MousePos) : 0;
|
|
hi.dwContextId = IntGetWindowContextHelpId(Wnd);
|
|
|
|
co_IntSendMessage( UserHMGetHandle(Wnd), WM_HELP, 0, (LPARAM)&hi );
|
|
break;
|
|
}
|
|
|
|
case WM_SETICON:
|
|
{
|
|
return DefWndSetIcon(Wnd, wParam, lParam);
|
|
}
|
|
|
|
case WM_GETICON:
|
|
{
|
|
return DefWndGetIcon(Wnd, wParam, lParam);
|
|
}
|
|
|
|
case WM_HELP:
|
|
{
|
|
PWND Parent = IntGetParent(Wnd);
|
|
co_IntSendMessage(UserHMGetHandle(Parent), Msg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_LBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_MBUTTONDOWN:
|
|
pti->MessageQueue->QF_flags &= ~(QF_FMENUSTATUS|QF_FMENUSTATUSBREAK);
|
|
break;
|
|
|
|
case WM_NCLBUTTONDOWN:
|
|
return NC_HandleNCLButtonDown(Wnd, wParam, lParam);
|
|
|
|
case WM_NCRBUTTONDOWN:
|
|
return NC_HandleNCRButtonDown(Wnd, wParam, lParam);
|
|
|
|
case WM_LBUTTONDBLCLK:
|
|
return NC_HandleNCLButtonDblClk(Wnd, HTCLIENT, lParam);
|
|
|
|
case WM_NCLBUTTONDBLCLK:
|
|
return NC_HandleNCLButtonDblClk(Wnd, wParam, lParam);
|
|
|
|
case WM_RBUTTONUP:
|
|
{
|
|
POINT Pt;
|
|
|
|
Pt.x = GET_X_LPARAM(lParam);
|
|
Pt.y = GET_Y_LPARAM(lParam);
|
|
IntClientToScreen(Wnd, &Pt);
|
|
lParam = MAKELPARAM(Pt.x, Pt.y);
|
|
co_IntSendMessage(UserHMGetHandle(Wnd), WM_CONTEXTMENU, (WPARAM)UserHMGetHandle(Wnd), lParam);
|
|
break;
|
|
}
|
|
|
|
case WM_NCRBUTTONUP:
|
|
/*
|
|
* FIXME : we must NOT send WM_CONTEXTMENU on a WM_NCRBUTTONUP (checked
|
|
* in Windows), but what _should_ we do? According to MSDN :
|
|
* "If it is appropriate to do so, the system sends the WM_SYSCOMMAND
|
|
* message to the window". When is it appropriate?
|
|
*/
|
|
ERR("WM_NCRBUTTONUP\n");
|
|
break;
|
|
|
|
case WM_XBUTTONUP:
|
|
case WM_NCXBUTTONUP:
|
|
if (HIWORD(wParam) == XBUTTON1 || HIWORD(wParam) == XBUTTON2)
|
|
{
|
|
co_IntSendMessage(UserHMGetHandle(Wnd), WM_APPCOMMAND, (WPARAM)UserHMGetHandle(Wnd),
|
|
MAKELPARAM(LOWORD(wParam), FAPPCOMMAND_MOUSE | HIWORD(wParam)));
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_CONTEXTMENU:
|
|
{
|
|
if (Wnd->style & WS_CHILD)
|
|
{
|
|
co_IntSendMessage(UserHMGetHandle(IntGetParent(Wnd)), Msg, wParam, lParam);
|
|
}
|
|
else
|
|
{
|
|
POINT Pt;
|
|
LONG_PTR Style;
|
|
LONG HitCode;
|
|
|
|
Style = Wnd->style;
|
|
|
|
Pt.x = GET_X_LPARAM(lParam);
|
|
Pt.y = GET_Y_LPARAM(lParam);
|
|
if (Style & WS_CHILD)
|
|
{
|
|
IntScreenToClient(IntGetParent(Wnd), &Pt);
|
|
}
|
|
|
|
HitCode = GetNCHitEx(Wnd, Pt);
|
|
|
|
if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
|
|
{
|
|
PMENU SystemMenu;
|
|
UINT Flags;
|
|
|
|
if((SystemMenu = IntGetSystemMenu(Wnd, FALSE)))
|
|
{
|
|
MENU_InitSysMenuPopup(SystemMenu, Wnd->style, Wnd->pcls->style, HitCode);
|
|
|
|
if(HitCode == HTCAPTION)
|
|
Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
|
|
else
|
|
Flags = TPM_LEFTBUTTON;
|
|
|
|
IntTrackPopupMenuEx(SystemMenu, Flags|TPM_SYSTEM_MENU, Pt.x, Pt.y, Wnd, NULL);
|
|
}
|
|
}
|
|
if (HitCode == HTHSCROLL || HitCode == HTVSCROLL)
|
|
{
|
|
WARN("Scroll Menu Not Supported\n");
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_KEYDOWN:
|
|
if (wParam == VK_F10)
|
|
{
|
|
pti->MessageQueue->QF_flags |= QF_FF10STATUS;
|
|
|
|
if (UserGetKeyState(VK_SHIFT) & 0x8000)
|
|
{
|
|
co_IntSendMessage(UserHMGetHandle(Wnd), WM_CONTEXTMENU, (WPARAM)UserHMGetHandle(Wnd), MAKELPARAM(-1, -1));
|
|
}
|
|
}
|
|
if (IS_KEY_DOWN(gafAsyncKeyState, VK_LWIN) || IS_KEY_DOWN(gafAsyncKeyState, VK_RWIN))
|
|
{
|
|
HWND hwndTop = UserGetForegroundWindow();
|
|
PWND topWnd = UserGetWindowObject(hwndTop);
|
|
|
|
/* Test for typical TaskBar ExStyle Values */
|
|
ExStyle = (topWnd->ExStyle & WS_EX_TOOLWINDOW);
|
|
TRACE("ExStyle is '%x'.\n", ExStyle);
|
|
|
|
/* Test for typical TaskBar Style Values */
|
|
Style = (topWnd->style & (WS_POPUP | WS_VISIBLE |
|
|
WS_CLIPSIBLINGS | WS_CLIPCHILDREN));
|
|
TRACE("Style is '%x'.\n", Style);
|
|
|
|
/* Test for masked typical TaskBar Style and ExStyles to detect TaskBar */
|
|
IsTaskBar = (Style == (WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN))
|
|
&& (ExStyle == WS_EX_TOOLWINDOW);
|
|
TRACE("This %s the TaskBar.\n", IsTaskBar ? "is" : "is not");
|
|
|
|
if (topWnd && !IsTaskBar) /* Second test is so we are not touching the Taskbar */
|
|
{
|
|
if ((topWnd->style & WS_THICKFRAME) == 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (wParam == VK_DOWN)
|
|
{
|
|
if (topWnd->style & WS_MAXIMIZE)
|
|
{
|
|
co_IntSendMessage(hwndTop, WM_SYSCOMMAND, SC_RESTORE, lParam);
|
|
|
|
/* "Normal size" must be erased after restoring, otherwise it will block next side snap actions */
|
|
RECTL_vSetEmptyRect(&topWnd->InternalPos.NormalRect);
|
|
}
|
|
else
|
|
{
|
|
co_IntSendMessage(hwndTop, WM_SYSCOMMAND, SC_MINIMIZE, lParam);
|
|
}
|
|
}
|
|
else if (wParam == VK_UP)
|
|
{
|
|
RECT currentRect;
|
|
if ((topWnd->InternalPos.NormalRect.right == topWnd->InternalPos.NormalRect.left) ||
|
|
(topWnd->InternalPos.NormalRect.top == topWnd->InternalPos.NormalRect.bottom))
|
|
{
|
|
currentRect = topWnd->rcWindow;
|
|
}
|
|
else
|
|
{
|
|
currentRect = topWnd->InternalPos.NormalRect;
|
|
}
|
|
co_IntSendMessage(hwndTop, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
|
|
|
|
// save normal rect if maximazing snapped window
|
|
topWnd->InternalPos.NormalRect = currentRect;
|
|
}
|
|
else if (wParam == VK_LEFT || wParam == VK_RIGHT)
|
|
{
|
|
RECT snapRect, normalRect, windowRect;
|
|
BOOL snapped;
|
|
normalRect = topWnd->InternalPos.NormalRect;
|
|
snapped = (normalRect.left != 0 && normalRect.right != 0 &&
|
|
normalRect.top != 0 && normalRect.bottom != 0);
|
|
|
|
if (topWnd->style & WS_MAXIMIZE)
|
|
{
|
|
co_IntSendMessage(hwndTop, WM_SYSCOMMAND, SC_RESTORE, lParam);
|
|
snapped = FALSE;
|
|
}
|
|
windowRect = topWnd->rcWindow;
|
|
|
|
UserSystemParametersInfo(SPI_GETWORKAREA, 0, &snapRect, 0);
|
|
if (wParam == VK_LEFT)
|
|
{
|
|
snapRect.right = (snapRect.left + snapRect.right) / 2;
|
|
}
|
|
else // VK_RIGHT
|
|
{
|
|
snapRect.left = (snapRect.left + snapRect.right) / 2;
|
|
}
|
|
|
|
if (snapped)
|
|
{
|
|
// if window was snapped but moved to other location - restore normal size
|
|
if (!IntEqualRect(&snapRect, &windowRect))
|
|
{
|
|
RECT empty = {0, 0, 0, 0};
|
|
co_WinPosSetWindowPos(topWnd,
|
|
0,
|
|
normalRect.left,
|
|
normalRect.top,
|
|
normalRect.right - normalRect.left,
|
|
normalRect.bottom - normalRect.top,
|
|
0);
|
|
topWnd->InternalPos.NormalRect = empty;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
co_WinPosSetWindowPos(topWnd,
|
|
0,
|
|
snapRect.left,
|
|
snapRect.top,
|
|
snapRect.right - snapRect.left,
|
|
snapRect.bottom - snapRect.top,
|
|
0);
|
|
topWnd->InternalPos.NormalRect = windowRect;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_SYSKEYDOWN:
|
|
{
|
|
if (HIWORD(lParam) & KF_ALTDOWN)
|
|
{ /* Previous state, if the key was down before this message,
|
|
this is a cheap way to ignore autorepeat keys. */
|
|
if ( !(HIWORD(lParam) & KF_REPEAT) )
|
|
{
|
|
if ( ( wParam == VK_MENU ||
|
|
wParam == VK_LMENU ||
|
|
wParam == VK_RMENU ) && !(pti->MessageQueue->QF_flags & QF_FMENUSTATUS)) //iMenuSysKey )
|
|
pti->MessageQueue->QF_flags |= QF_FMENUSTATUS; //iMenuSysKey = 1;
|
|
else
|
|
pti->MessageQueue->QF_flags &= ~QF_FMENUSTATUS; //iMenuSysKey = 0;
|
|
}
|
|
|
|
pti->MessageQueue->QF_flags &= ~QF_FF10STATUS; //iF10Key = 0;
|
|
|
|
if (wParam == VK_F4) /* Try to close the window */
|
|
{
|
|
PWND top = UserGetAncestor(Wnd, GA_ROOT);
|
|
if (!(top->style & CS_NOCLOSE))
|
|
UserPostMessage(UserHMGetHandle(top), WM_SYSCOMMAND, SC_CLOSE, 0);
|
|
}
|
|
else if (wParam == VK_SNAPSHOT) // Alt-VK_SNAPSHOT?
|
|
{
|
|
PWND pwnd = Wnd;
|
|
while (IntGetParent(pwnd) != NULL)
|
|
{
|
|
pwnd = IntGetParent(pwnd);
|
|
}
|
|
ERR("DefWndScreenshot\n");
|
|
DefWndScreenshot(pwnd);
|
|
}
|
|
else if ( wParam == VK_ESCAPE || wParam == VK_TAB ) // Alt-Tab/ESC Alt-Shift-Tab/ESC
|
|
{
|
|
WPARAM wParamTmp;
|
|
HWND Active = UserGetActiveWindow(); // Noticed MDI problem.
|
|
if (!Active)
|
|
{
|
|
FIXME("WM_SYSKEYDOWN VK_ESCAPE no active\n");
|
|
break;
|
|
}
|
|
wParamTmp = UserGetKeyState(VK_SHIFT) & 0x8000 ? SC_PREVWINDOW : SC_NEXTWINDOW;
|
|
co_IntSendMessage( Active, WM_SYSCOMMAND, wParamTmp, wParam );
|
|
}
|
|
}
|
|
else if( wParam == VK_F10 )
|
|
{
|
|
if (UserGetKeyState(VK_SHIFT) & 0x8000)
|
|
co_IntSendMessage( UserHMGetHandle(Wnd), WM_CONTEXTMENU, (WPARAM)UserHMGetHandle(Wnd), MAKELPARAM(-1, -1) );
|
|
pti->MessageQueue->QF_flags |= QF_FF10STATUS; //iF10Key = 1;
|
|
}
|
|
else if( wParam == VK_ESCAPE && (UserGetKeyState(VK_SHIFT) & 0x8000))
|
|
co_IntSendMessage( UserHMGetHandle(Wnd), WM_SYSCOMMAND, SC_KEYMENU, ' ' );
|
|
break;
|
|
}
|
|
|
|
case WM_KEYUP:
|
|
case WM_SYSKEYUP:
|
|
{
|
|
/* Press and release F10 or ALT */
|
|
if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
|
|
&& (pti->MessageQueue->QF_flags & (QF_FMENUSTATUS|QF_FMENUSTATUSBREAK)) == QF_FMENUSTATUS /*iMenuSysKey*/) ||
|
|
((wParam == VK_F10) && pti->MessageQueue->QF_flags & QF_FF10STATUS /*iF10Key*/))
|
|
co_IntSendMessage( UserHMGetHandle(UserGetAncestor( Wnd, GA_ROOT )), WM_SYSCOMMAND, SC_KEYMENU, 0L );
|
|
pti->MessageQueue->QF_flags &= ~(QF_FMENUSTATUS|QF_FMENUSTATUSBREAK|QF_FF10STATUS); //iMenuSysKey = iF10Key = 0;
|
|
break;
|
|
}
|
|
|
|
case WM_SYSCHAR:
|
|
{
|
|
pti->MessageQueue->QF_flags &= ~(QF_FMENUSTATUS|QF_FMENUSTATUSBREAK); //iMenuSysKey = 0;
|
|
if (wParam == VK_RETURN && (Wnd->style & WS_MINIMIZE) != 0)
|
|
{
|
|
UserPostMessage( UserHMGetHandle(Wnd), WM_SYSCOMMAND, SC_RESTORE, 0L );
|
|
break;
|
|
}
|
|
if ((HIWORD(lParam) & KF_ALTDOWN) && wParam)
|
|
{
|
|
if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
|
|
if (wParam == VK_SPACE && Wnd->style & WS_CHILD)
|
|
co_IntSendMessage( UserHMGetHandle(IntGetParent(Wnd)), Msg, wParam, lParam );
|
|
else
|
|
co_IntSendMessage( UserHMGetHandle(Wnd), WM_SYSCOMMAND, SC_KEYMENU, wParam );
|
|
}
|
|
else /* check for Ctrl-Esc */
|
|
if (wParam != VK_ESCAPE) UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, 0); //MessageBeep(0);
|
|
break;
|
|
}
|
|
|
|
case WM_CANCELMODE:
|
|
{
|
|
pti->MessageQueue->QF_flags &= ~(QF_FMENUSTATUS|QF_FMENUSTATUSBREAK);
|
|
|
|
MENU_EndMenu( Wnd );
|
|
if (IntGetCaptureWindow() == UserHMGetHandle(Wnd))
|
|
{
|
|
IntReleaseCapture();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case WM_CLOSE:
|
|
co_UserDestroyWindow(Wnd);
|
|
break;
|
|
|
|
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_CTLCOLOR:
|
|
return (LRESULT) DefWndControlColor((HDC)wParam, HIWORD(lParam));
|
|
|
|
case WM_SETCURSOR:
|
|
{
|
|
if (Wnd->style & WS_CHILD)
|
|
{
|
|
/* with the exception of the border around a resizable wnd,
|
|
* give the parent first chance to set the cursor */
|
|
if (LOWORD(lParam) < HTLEFT || LOWORD(lParam) > HTBOTTOMRIGHT)
|
|
{
|
|
PWND parent = Wnd->spwndParent;//IntGetParent( Wnd );
|
|
if (parent != UserGetDesktopWindow() &&
|
|
co_IntSendMessage( UserHMGetHandle(parent), WM_SETCURSOR, wParam, lParam))
|
|
return TRUE;
|
|
}
|
|
}
|
|
return DefWndHandleSetCursor(Wnd, wParam, lParam);
|
|
}
|
|
|
|
case WM_MOUSEACTIVATE:
|
|
if (Wnd->style & WS_CHILD)
|
|
{
|
|
LONG Ret;
|
|
HWND hwndParent;
|
|
PWND pwndParent = IntGetParent(Wnd);
|
|
hwndParent = pwndParent ? UserHMGetHandle(pwndParent) : NULL;
|
|
if (hwndParent) Ret = co_IntSendMessage(hwndParent, WM_MOUSEACTIVATE, wParam, lParam);
|
|
if (Ret) return (Ret);
|
|
}
|
|
return ( (HIWORD(lParam) == WM_LBUTTONDOWN && LOWORD(lParam) == HTCAPTION) ? MA_NOACTIVATE : MA_ACTIVATE );
|
|
|
|
case WM_ACTIVATE:
|
|
/* The default action in Windows is to set the keyboard focus to
|
|
* the window, if it's being activated and not minimized */
|
|
if (LOWORD(wParam) != WA_INACTIVE &&
|
|
!(Wnd->style & WS_MINIMIZE))
|
|
{
|
|
//ERR("WM_ACTIVATE %p\n",hWnd);
|
|
co_UserSetFocus(Wnd);
|
|
}
|
|
break;
|
|
|
|
case WM_MOUSEWHEEL:
|
|
if (Wnd->style & WS_CHILD)
|
|
{
|
|
HWND hwndParent;
|
|
PWND pwndParent = IntGetParent(Wnd);
|
|
hwndParent = pwndParent ? UserHMGetHandle(pwndParent) : NULL;
|
|
return co_IntSendMessage( hwndParent, WM_MOUSEWHEEL, wParam, lParam);
|
|
}
|
|
break;
|
|
|
|
case WM_ERASEBKGND:
|
|
case WM_ICONERASEBKGND:
|
|
{
|
|
RECT Rect;
|
|
HBRUSH hBrush = Wnd->pcls->hbrBackground;
|
|
if (!hBrush) return 0;
|
|
if (hBrush <= (HBRUSH)COLOR_MENUBAR)
|
|
{
|
|
hBrush = IntGetSysColorBrush(HandleToUlong(hBrush));
|
|
}
|
|
if (Wnd->pcls->style & CS_PARENTDC)
|
|
{
|
|
/* can't use GetClipBox with a parent DC or we fill the whole parent */
|
|
IntGetClientRect(Wnd, &Rect);
|
|
GreDPtoLP((HDC)wParam, (LPPOINT)&Rect, 2);
|
|
}
|
|
else
|
|
{
|
|
GdiGetClipBox((HDC)wParam, &Rect);
|
|
}
|
|
FillRect((HDC)wParam, &Rect, hBrush);
|
|
return (1);
|
|
}
|
|
|
|
case WM_GETHOTKEY:
|
|
//ERR("WM_GETHOTKEY\n");
|
|
return DefWndGetHotKey(Wnd);
|
|
case WM_SETHOTKEY:
|
|
//ERR("WM_SETHOTKEY\n");
|
|
return DefWndSetHotKey(Wnd, wParam);
|
|
|
|
case WM_NCHITTEST:
|
|
{
|
|
POINT Point;
|
|
Point.x = GET_X_LPARAM(lParam);
|
|
Point.y = GET_Y_LPARAM(lParam);
|
|
return GetNCHitEx(Wnd, Point);
|
|
}
|
|
|
|
case WM_PRINT:
|
|
{
|
|
DefWndPrint(Wnd, (HDC)wParam, lParam);
|
|
return (0);
|
|
}
|
|
|
|
case WM_SYSCOLORCHANGE:
|
|
{
|
|
/* force to redraw non-client area */
|
|
UserPaintCaption(Wnd, DC_NC);
|
|
/* Use InvalidateRect to redraw client area, enable
|
|
* erase to redraw all subcontrols otherwise send the
|
|
* WM_SYSCOLORCHANGE to child windows/controls is required
|
|
*/
|
|
co_UserRedrawWindow( Wnd, NULL, NULL, RDW_ALLCHILDREN|RDW_INVALIDATE|RDW_ERASE);
|
|
return (0);
|
|
}
|
|
|
|
case WM_PAINTICON:
|
|
case WM_PAINT:
|
|
{
|
|
PAINTSTRUCT Ps;
|
|
HDC hDC;
|
|
|
|
/* If already in Paint and Client area is not empty just return. */
|
|
if (Wnd->state2 & WNDS2_STARTPAINT && !RECTL_bIsEmptyRect(&Wnd->rcClient))
|
|
{
|
|
ERR("In Paint and Client area is not empty!\n");
|
|
return 0;
|
|
}
|
|
|
|
hDC = IntBeginPaint(Wnd, &Ps);
|
|
if (hDC)
|
|
{
|
|
if (((Wnd->style & WS_MINIMIZE) != 0) && (Wnd->pcls->spicn))
|
|
{
|
|
RECT ClientRect;
|
|
INT x, y;
|
|
|
|
ERR("Doing Paint and Client area is empty!\n");
|
|
IntGetClientRect(Wnd, &ClientRect);
|
|
x = (ClientRect.right - ClientRect.left - UserGetSystemMetrics(SM_CXICON)) / 2;
|
|
y = (ClientRect.bottom - ClientRect.top - UserGetSystemMetrics(SM_CYICON)) / 2;
|
|
UserReferenceObject(Wnd->pcls->spicn);
|
|
UserDrawIconEx(hDC, x, y, Wnd->pcls->spicn, 0, 0, 0, 0, DI_NORMAL | DI_COMPAT | DI_DEFAULTSIZE);
|
|
UserDereferenceObject(Wnd->pcls->spicn);
|
|
}
|
|
|
|
IntEndPaint(Wnd, &Ps);
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
case WM_SYNCPAINT:
|
|
{
|
|
HRGN hRgn;
|
|
Wnd->state &= ~WNDS_SYNCPAINTPENDING;
|
|
TRACE("WM_SYNCPAINT\n");
|
|
hRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
|
|
if (hRgn)
|
|
{
|
|
if (co_UserGetUpdateRgn(Wnd, hRgn, FALSE) != NULLREGION)
|
|
{
|
|
PREGION pRgn = REGION_LockRgn(hRgn);
|
|
if (pRgn) REGION_UnlockRgn(pRgn);
|
|
if (!wParam)
|
|
wParam = (RDW_ERASENOW | RDW_ERASE | RDW_FRAME | RDW_ALLCHILDREN);
|
|
co_UserRedrawWindow(Wnd, NULL, pRgn, wParam);
|
|
}
|
|
GreDeleteObject(hRgn);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
case WM_SETREDRAW:
|
|
if (wParam)
|
|
{
|
|
if (!(Wnd->style & WS_VISIBLE))
|
|
{
|
|
IntSetStyle( Wnd, WS_VISIBLE, 0 );
|
|
Wnd->state |= WNDS_SENDNCPAINT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (Wnd->style & WS_VISIBLE)
|
|
{
|
|
co_UserRedrawWindow( Wnd, NULL, NULL, RDW_ALLCHILDREN | RDW_VALIDATE );
|
|
IntSetStyle( Wnd, 0, WS_VISIBLE );
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
case WM_WINDOWPOSCHANGING:
|
|
{
|
|
return (DefWndHandleWindowPosChanging(Wnd, (WINDOWPOS*)lParam));
|
|
}
|
|
|
|
case WM_WINDOWPOSCHANGED:
|
|
{
|
|
return (DefWndHandleWindowPosChanged(Wnd, (WINDOWPOS*)lParam));
|
|
}
|
|
|
|
case WM_NCCALCSIZE:
|
|
{
|
|
return NC_HandleNCCalcSize( Wnd, wParam, (RECTL *)lParam, FALSE );
|
|
}
|
|
|
|
case WM_NCACTIVATE:
|
|
{
|
|
return NC_HandleNCActivate( Wnd, wParam, lParam );
|
|
}
|
|
|
|
//
|
|
// NC Paint mode.
|
|
//
|
|
case WM_NCPAINT:
|
|
{
|
|
HDC hDC = UserGetDCEx(Wnd, (HRGN)wParam, DCX_WINDOW | DCX_INTERSECTRGN | DCX_USESTYLE | DCX_KEEPCLIPRGN);
|
|
Wnd->state |= WNDS_FORCEMENUDRAW;
|
|
NC_DoNCPaint(Wnd, hDC, -1);
|
|
Wnd->state &= ~WNDS_FORCEMENUDRAW;
|
|
UserReleaseDC(Wnd, hDC, FALSE);
|
|
return 0;
|
|
}
|
|
//
|
|
// Draw Caption mode.
|
|
//
|
|
// wParam are DC_* flags.
|
|
//
|
|
case WM_NCUAHDRAWCAPTION:
|
|
{
|
|
HDC hDC = UserGetDCEx(Wnd, NULL, DCX_WINDOW|DCX_USESTYLE);
|
|
TRACE("WM_NCUAHDRAWCAPTION: wParam DC_ flags %08x\n",wParam);
|
|
UserDrawCaptionBar(Wnd, hDC, wParam | DC_FRAME); // Include DC_FRAME to comp for drawing glitch.
|
|
UserReleaseDC(Wnd, hDC, FALSE);
|
|
return 0;
|
|
}
|
|
//
|
|
// Draw Frame mode.
|
|
//
|
|
// wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
|
|
//
|
|
case WM_NCUAHDRAWFRAME:
|
|
{
|
|
TRACE("WM_NCUAHDRAWFRAME: wParam hDC %p lParam DC_ flags %08x\n",wParam,lParam);
|
|
NC_DoNCPaint(Wnd, (HDC)wParam, lParam|DC_NC);
|
|
return 0;
|
|
}
|
|
|
|
/* ReactOS only. */
|
|
case WM_CBT:
|
|
{
|
|
switch (wParam)
|
|
{
|
|
case HCBT_MOVESIZE:
|
|
{
|
|
RECTL rt;
|
|
|
|
if (lParam)
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead((PVOID)lParam,
|
|
sizeof(RECT),
|
|
1);
|
|
|
|
RtlCopyMemory(&rt,
|
|
(PVOID)lParam,
|
|
sizeof(RECT));
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
lResult = 1;
|
|
}
|
|
_SEH2_END;
|
|
}
|
|
if (!lResult)
|
|
lResult = co_HOOK_CallHooks(WH_CBT, HCBT_MOVESIZE, (WPARAM)Wnd->head.h, lParam ? (LPARAM)&rt : 0);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return lResult;
|
|
}
|
|
|
|
/* EOF */
|