[Win32SS|UxTheme]

- Move Menu to server side. See CORE-7797 and CORE-8299.
- This was for speed while moving windows about the desktop and fixed test results too.

svn path=/trunk/; revision=68904
This commit is contained in:
James Tabor 2015-09-01 22:10:13 +00:00
parent eebbf23330
commit 6dfa71c487
41 changed files with 7700 additions and 6800 deletions

View file

@ -1070,7 +1070,13 @@ ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndPr
{
case WM_NCPAINT:
return ThemeHandleNCPaint(hWnd, (HRGN)wParam);
//
// WM_NCUAHDRAWCAPTION : wParam are DC_* flags.
//
case WM_NCUAHDRAWCAPTION:
//
// WM_NCUAHDRAWFRAME : wParam is HDC, lParam are DC_ACTIVE and or DC_REDRAWHUNGWND.
//
case WM_NCUAHDRAWFRAME:
case WM_NCACTIVATE:
ThemeHandleNCPaint(hWnd, (HRGN)1);

View file

@ -186,12 +186,6 @@ ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if(!IsAppThemed())
{
if (Msg == WM_NCUAHDRAWCAPTION)
{
user32ApiHook.DrawCaption(hWnd, NULL, NULL, 0);
return 0;
}
return user32ApiHook.DefWindowProcW(hWnd,
Msg,
wParam,
@ -210,12 +204,6 @@ ThemeDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
if(!IsAppThemed())
{
if (Msg == WM_NCUAHDRAWCAPTION)
{
user32ApiHook.DrawCaption(hWnd, NULL, NULL, 0);
return 0;
}
return user32ApiHook.DefWindowProcA(hWnd,
Msg,
wParam,

View file

@ -43,6 +43,7 @@ extern "C" {
#define WM_LBTRACKPOINT 0x00000131
#define LB_CARETON 0x000001a3
#define LB_CARETOFF 0x000001a4
#define MN_SETHMENU 0x000001e0
#define WM_DROPOBJECT 0x0000022A
#define WM_QUERYDROPOBJECT 0x0000022B
#define WM_BEGINDRAG 0x0000022C
@ -60,6 +61,9 @@ extern "C" {
#define DCX_KEEPLAYOUT 0x40000000
#define DCX_PROCESSOWNED 0x80000000
/* Non SDK TPM types.*/
#define TPM_SYSTEM_MENU 0x00000200
/* NtUserCreateWindowEx dwFlags bits. */
#define NUCWE_ANSI 0x00000001
#define NUCWE_SIDEBYSIDE 0x40000000
@ -132,7 +136,20 @@ extern "C" {
//
// Undocumented flags for DrawCaptionTemp
//
#define DC_NOVISIBLE 0x0800
#define DC_NOSENDMSG 0x2000
#define DC_FRAME 0x8000 // Missing from WinUser.H!
#define DC_DRAWCAPTIONMD 0x10000000
#define DC_REDRAWHUNGWND 0x20000000
#define DC_DRAWFRAMEMD 0x80000000
//
// Undocumented states for DrawFrameControl
//
#define DFCS_MENUARROWUP 0x0008
#define DFCS_MENUARROWDOWN 0x0010
#define STARTF_SCRNSAVER 0x80000000

View file

@ -149,6 +149,7 @@ list(APPEND SOURCE
user/ntuser/winpos.c
user/ntuser/winsta.c
user/ntuser/object.c
user/rtl/text.c
gdi/ntgdi/arc.c
gdi/ntgdi/bezier.c
gdi/ntgdi/bitblt.c

View file

@ -375,6 +375,9 @@ typedef struct tagMENULIST
/* Hack */
#define MNF_SYSMENU 0x0200
/* (other FocusedItem values give the position of the focused item) */
#define NO_SELECTED_ITEM 0xffff
typedef struct tagMENU
{
PROCDESKHEAD head;
@ -3515,58 +3518,6 @@ NtUserGetMonitorInfo(
/* Should be done in usermode */
/* (other FocusedItem values give the position of the focused item) */
#define NO_SELECTED_ITEM 0xffff
typedef struct tagROSMENUINFO
{
/* ----------- MENUINFO ----------- */
DWORD cbSize;
DWORD fMask;
DWORD dwStyle;
UINT cyMax;
HBRUSH hbrBack;
DWORD dwContextHelpID;
ULONG_PTR dwMenuData;
/* ----------- Extra ----------- */
ULONG fFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */
UINT iItem; /* Currently focused item */
UINT cItems; /* Number of items in the menu */
WORD cxMenu; /* Width of the whole menu */
WORD cyMenu; /* Height of the whole menu */
ULONG cxTextAlign;
PWND spwndNotify; /* window receiving the messages for ownerdraw */
INT iTop;
INT iMaxTop;
DWORD dwArrowsOn:2;
HMENU Self; /* Handle of this menu */
HWND Wnd; /* Window containing the menu */
BOOL TimeToHide; /* Request hiding when receiving a second click in the top-level menu item */
} ROSMENUINFO, *PROSMENUINFO;
typedef struct tagROSMENUITEMINFO
{
/* ----------- MENUITEMINFOW ----------- */
UINT cbSize;
UINT fMask;
UINT fType;
UINT fState;
UINT wID;
HMENU hSubMenu;
HBITMAP hbmpChecked;
HBITMAP hbmpUnchecked;
DWORD dwItemData;
LPWSTR dwTypeData;
UINT cch;
HBITMAP hbmpItem;
/* ----------- Extra ----------- */
RECT Rect; /* Item area (relative to menu window) */
UINT dxTab; /* X position of text after Tab */
LPWSTR lpstr; /* Copy of the text pointer in MenuItem->Text */
SIZE maxBmpSize; /* Maximum size of the bitmap items in MIIM_BITMAP state */
} ROSMENUITEMINFO, *PROSMENUITEMINFO;
HMONITOR
NTAPI
NtUserMonitorFromPoint(

View file

@ -393,6 +393,8 @@ co_IntCallWindowProc(WNDPROC Proc,
case WM_WINDOWPOSCHANGING:
case WM_SIZING:
case WM_MOVING:
case WM_MEASUREITEM:
case WM_NEXTMENU:
TRACE("Copy lParam, Message %u Size %d lParam %d!\n", Message, lParamBufferSize, lParam);
if (InSendMessage)
// Copy into kernel space.

View file

@ -2556,6 +2556,15 @@ InvalidParameter:
Offset,
dwNewLong,
Ansi);
switch(Offset)
{
case GCLP_HICONSM:
case GCLP_HICON:
{
if (Ret && Ret != dwNewLong)
UserPaintCaption(Window, DC_ICON);
}
}
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{

View file

@ -11,6 +11,23 @@
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)
@ -171,6 +188,19 @@ DefWndHandleSysCommand(PWND pWnd, WPARAM wParam, LPARAM lParam)
}
}
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:
@ -362,6 +392,138 @@ VOID FASTCALL DefWndPrint( PWND pwnd, HDC hdc, ULONG uFlags)
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 sovled 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
*/
co_IntSendMessage(UserHMGetHandle(pWnd), WM_NCUAHDRAWCAPTION, Flags, 0);
}
else
{
HDC hDC = UserGetDCEx(pWnd, NULL, DCX_WINDOW|DCX_USESTYLE);
UserDrawCaptionBar(pWnd, hDC, Flags);
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);
hIcon = UserGetProp(pWnd, gpsi->atomIconProp);
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;
}
IntSetProp(pWnd, gpsi->atomIconProp, hIcon);
IntSetProp(pWnd, gpsi->atomIconSmProp, hIconSmall);
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);
break;
case ICON_SMALL:
case ICON_SMALL2:
hIconRet = UserGetProp(pWnd, gpsi->atomIconSmProp);
break;
default:
break;
}
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
@ -374,6 +536,7 @@ IntDefWindowProc(
LPARAM lParam,
BOOL Ansi)
{
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
LRESULT lResult = 0;
USER_REFERENCE_ENTRY Ref;
@ -381,12 +544,74 @@ IntDefWindowProc(
switch (Msg)
{
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:
{
ERR("hwnd %p WM_SYSCOMMAND %lx %lx\n", Wnd->head.h, wParam, lParam );
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;
@ -411,7 +636,6 @@ IntDefWindowProc(
return IntClientShutdown(Wnd, wParam, lParam);
case WM_APPCOMMAND:
ERR("WM_APPCOMMAND\n");
if ( (Wnd->style & (WS_POPUP|WS_CHILD)) != WS_CHILD &&
Wnd != co_GetDesktopWindow(Wnd) )
{
@ -424,6 +648,241 @@ IntDefWindowProc(
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_LBUTTONDBLCLK:
return (NC_HandleNCLButtonDblClk( Wnd, HTCLIENT, lParam));
case WM_NCLBUTTONDBLCLK:
return (NC_HandleNCLButtonDblClk( Wnd, wParam, lParam));
case WM_NCRBUTTONDOWN:
return NC_HandleNCRButtonDown( 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_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));
}
}
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;
@ -457,6 +916,18 @@ IntDefWindowProc(
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 */
@ -523,6 +994,18 @@ IntDefWindowProc(
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:
{
@ -548,7 +1031,9 @@ IntDefWindowProc(
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);
@ -578,7 +1063,6 @@ IntDefWindowProc(
}
case WM_SETREDRAW:
ERR("WM_SETREDRAW\n");
if (wParam)
{
if (!(Wnd->style & WS_VISIBLE))
@ -607,6 +1091,53 @@ IntDefWindowProc(
return (DefWndHandleWindowPosChanged(Wnd, (WINDOWPOS*)lParam));
}
case WM_NCCALCSIZE:
{
return NC_HandleNCCalcSize( Wnd, wParam, (RECTL *)lParam );
}
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 glich.
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:
{

View file

@ -664,6 +664,7 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lRe
case WM_SYSCOLORCHANGE:
co_UserRedrawWindow(Wnd, NULL, NULL, RDW_INVALIDATE|RDW_ERASE|RDW_ALLCHILDREN);
return TRUE;
case WM_SETCURSOR:
{
PCURICON_OBJECT pcurOld, pcurNew;
@ -691,8 +692,11 @@ DesktopWindowProc(PWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT *lRe
HDESK hdesk = IntGetDesktopObjectHandle(gpdeskInputDesktop);
IntSetThreadDesktop(hdesk, FALSE);
}
break;
}
default:
TRACE("DWP calling IDWP Msg %d\n",Msg);
*lResult = IntDefWindowProc(Wnd, Msg, wParam, lParam, FALSE);
}
return TRUE; /* We are done. Do not do any callbacks to user mode */
}
@ -711,6 +715,9 @@ UserMessageWindowProc(PWND pwnd, UINT Msg, WPARAM wParam, LPARAM lParam, LRESULT
case WM_DESTROY:
pwnd->fnid |= FNID_DESTROY;
break;
default:
ERR("UMWP calling IDWP\n");
*lResult = IntDefWindowProc(pwnd, Msg, wParam, lParam, FALSE);
}
return TRUE; /* We are done. Do not do any callbacks to user mode */

View file

@ -948,6 +948,14 @@ BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
WCHAR Symbol;
switch(uFlags & 0xff)
{
case DFCS_MENUARROWUP:
Symbol = '5';
break;
case DFCS_MENUARROWDOWN:
Symbol = '6';
break;
case DFCS_MENUARROW:
Symbol = '8';
break;
@ -980,8 +988,6 @@ BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
hFont = GreCreateFontIndirectW(&lf);
/* save font */
hOldFont = NtGdiSelectFont(dc, hFont);
// FIXME selecting color doesn't work
#if 0
if(uFlags & DFCS_INACTIVE)
{
/* draw shadow */
@ -989,7 +995,6 @@ BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
GreTextOutW(dc, r->left + 1, r->top + 1, &Symbol, 1);
}
IntGdiSetTextColor(dc, IntGetSysColor((uFlags & DFCS_INACTIVE) ? COLOR_BTNSHADOW : COLOR_BTNTEXT));
#endif
/* draw selected symbol */
GreTextOutW(dc, r->left, r->top, &Symbol, 1);
/* restore previous settings */
@ -1005,6 +1010,25 @@ BOOL FASTCALL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
//
INT WINAPI
FrameRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
{
HBRUSH oldbrush;
RECT r = *lprc;
if ((r.right <= r.left) || (r.bottom <= r.top)) return 0;
if (!(oldbrush = NtGdiSelectBrush(hDC, hbr))) return 0;
NtGdiPatBlt(hDC, r.left, r.top, 1, r.bottom - r.top, PATCOPY);
NtGdiPatBlt(hDC, r.right - 1, r.top, 1, r.bottom - r.top, PATCOPY);
NtGdiPatBlt(hDC, r.left, r.top, r.right - r.left, 1, PATCOPY);
NtGdiPatBlt(hDC, r.left, r.bottom - 1, r.right - r.left, 1, PATCOPY);
NtGdiSelectBrush(hDC, oldbrush);
return TRUE;
}
INT WINAPI
FillRect(HDC hDC, CONST RECT *lprc, HBRUSH hbr)
{

View file

@ -66,7 +66,7 @@ co_IntSendDeactivateMessages(HWND hWndPrev, HWND hWnd)
(LPARAM)hWnd);
if (WndPrev)
WndPrev->state &= ~WNDS_ACTIVEFRAME;
WndPrev->state &= ~(WNDS_ACTIVEFRAME|WNDS_HASCAPTION);
}
else
{
@ -700,7 +700,7 @@ co_IntSetActiveWindow(PWND Wnd OPTIONAL, BOOL bMouse, BOOL bFocus, BOOL Async)
}
// FIXME: Used in the menu loop!!!
//ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE;
ThreadQueue->QF_flags |= QF_ACTIVATIONCHANGE;
//ERR("co_IntSetActiveWindow Exit\n");
if (Wnd) Wnd->state &= ~WNDS_BEINGACTIVATED;
@ -946,7 +946,11 @@ co_UserSetCapture(HWND hWnd)
if (Window)
IntNotifyWinEvent(EVENT_SYSTEM_CAPTURESTART, Window, OBJID_WINDOW, CHILDID_SELF, WEF_SETBYWNDPTI);
if (hWndPrev && hWndPrev != hWnd)
//
// Only send the message if we have a previous Window!
// Fix msg_menu tracking popup menu and win test_capture_4!!!!
//
if (hWndPrev)
{
if (ThreadQueue->MenuOwner && Window) ThreadQueue->QF_flags |= QF_CAPTURELOCKED;

View file

@ -936,7 +936,7 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d
/* FIXME: Set KF_DLGMODE and KF_MENUMODE when needed */
if (pFocusQueue->QF_flags & QF_DIALOGACTIVE)
Msg.lParam |= KF_DLGMODE << 16;
if (pFocusQueue->MenuOwner) // pFocusQueue->MenuState) // MenuState needs a start flag...
if (pFocusQueue->MenuOwner) // pti->pMenuState->fMenuStarted
Msg.lParam |= KF_MENUMODE << 16;
}
@ -951,7 +951,6 @@ ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD d
if (!Wnd) {ERR("Window is NULL\n");}
MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
}
return TRUE;
}

File diff suppressed because it is too large Load diff

View file

@ -66,6 +66,62 @@ typedef struct _SETMENUITEMRECT
RECTL rcRect;
} SETMENUITEMRECT, *PSETMENUITEMRECT;
//
// Legacy ReactOS Menu transfer structures.
//
typedef struct tagROSMENUINFO
{
/* ----------- MENUINFO ----------- */
DWORD cbSize;
DWORD fMask;
DWORD dwStyle;
UINT cyMax;
HBRUSH hbrBack;
DWORD dwContextHelpID;
ULONG_PTR dwMenuData;
/* ----------- Extra ----------- */
ULONG fFlags; /* Menu flags (MF_POPUP, MF_SYSMENU) */
UINT iItem; /* Currently focused item */
UINT cItems; /* Number of items in the menu */
WORD cxMenu; /* Width of the whole menu */
WORD cyMenu; /* Height of the whole menu */
ULONG cxTextAlign;
PWND spwndNotify; /* window receiving the messages for ownerdraw */
INT iTop;
INT iMaxTop;
DWORD dwArrowsOn:2;
HMENU Self; /* Handle of this menu */
HWND Wnd; /* Window containing the menu */
BOOL TimeToHide; /* Request hiding when receiving a second click in the top-level menu item */
} ROSMENUINFO, *PROSMENUINFO;
typedef struct tagROSMENUITEMINFO
{
/* ----------- MENUITEMINFOW ----------- */
UINT cbSize;
UINT fMask;
UINT fType;
UINT fState;
UINT wID;
HMENU hSubMenu;
HBITMAP hbmpChecked;
HBITMAP hbmpUnchecked;
DWORD dwItemData;
LPWSTR dwTypeData;
UINT cch;
HBITMAP hbmpItem;
/* ----------- Extra ----------- */
RECT Rect; /* Item area (relative to menu window) */
UINT dxTab; /* X position of text after Tab */
LPWSTR lpstr; /* Copy of the text pointer in MenuItem->Text */
SIZE maxBmpSize; /* Maximum size of the bitmap items in MIIM_BITMAP state */
} ROSMENUITEMINFO, *PROSMENUITEMINFO;
//
//
//
PMENU FASTCALL
IntGetMenuObject(HMENU hMenu);
@ -101,3 +157,14 @@ BOOL FASTCALL IntRemoveMenuItem(PMENU Menu, UINT uPosition, UINT uFlags, BOOL bR
PITEM FASTCALL MENU_FindItem( PMENU *pmenu, UINT *nPos, UINT wFlags );
BOOL FASTCALL IntMenuItemInfo(PMENU Menu, UINT Item, BOOL ByPosition, PROSMENUITEMINFO UnsafeItemInfo, BOOL SetOrGet, PUNICODE_STRING lpstr);
BOOL FASTCALL IntSetMenu(PWND Wnd,HMENU Menu,BOOL *Changed);
UINT MENU_DrawMenuBar( HDC hDC, LPRECT lprect, PWND pWnd, BOOL suppress_draw );
BOOL MenuInit(VOID);
VOID MENU_TrackKbdMenuBar(PWND pwnd, UINT wParam, WCHAR wChar);
VOID MENU_TrackMouseMenuBar( PWND pWnd, ULONG ht, POINT pt);
BOOL WINAPI PopupMenuWndProc(PWND Wnd,UINT Message,WPARAM wParam,LPARAM lParam,LRESULT *lResult);
BOOL FASTCALL IntSetMenuItemInfo(PMENU, PITEM, PROSMENUITEMINFO, PUNICODE_STRING);
PWND MENU_IsMenuActive(VOID);
void MENU_EndMenu( PWND pwnd );
void FASTCALL MENU_InitSysMenuPopup(PMENU menu, DWORD style, DWORD clsStyle, LONG HitTest );
INT FASTCALL IntMenuItemFromPoint(PWND pWnd, HMENU hMenu, POINT ptScreen);
BOOL WINAPI IntTrackPopupMenuEx( PMENU menu, UINT wFlags, int x, int y, PWND pWnd, LPTPMPARAMS lpTpm);

View file

@ -136,6 +136,10 @@ static MSGMEMORY g_MsgMemory[] =
{ WM_WINDOWPOSCHANGING, sizeof(WINDOWPOS), MMS_FLAG_READWRITE },
{ WM_SIZING, sizeof(RECT), MMS_FLAG_READWRITE },
{ WM_MOVING, sizeof(RECT), MMS_FLAG_READWRITE },
{ WM_MEASUREITEM, sizeof(MEASUREITEMSTRUCT), MMS_FLAG_READWRITE },
{ WM_DRAWITEM, sizeof(DRAWITEMSTRUCT), MMS_FLAG_READWRITE },
{ WM_HELP, sizeof(HELPINFO), MMS_FLAG_READWRITE },
{ WM_NEXTMENU, sizeof(MDINEXTMENU), MMS_FLAG_READWRITE },
};
static PMSGMEMORY FASTCALL
@ -745,7 +749,13 @@ IntDispatchMessage(PMSG pMsg)
pMsg->message,
pMsg->wParam,
pMsg->lParam,
&retval);
&retval);
case FNID_MENU:
DoCallBack = !PopupMenuWndProc( Window,
pMsg->message,
pMsg->wParam,
pMsg->lParam,
&retval);
break;
}
}
@ -949,7 +959,7 @@ co_IntPeekMessage( PMSG Msg,
return TRUE;
}
static BOOL FASTCALL
BOOL FASTCALL
co_IntWaitMessage( PWND Window,
UINT MsgFilterMin,
UINT MsgFilterMax )
@ -1353,6 +1363,9 @@ co_IntSendMessageTimeoutSingle( HWND hWnd,
case FNID_MESSAGEWND:
DoCallBack = !UserMessageWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result);
break;
case FNID_MENU:
DoCallBack = !PopupMenuWndProc( Window, Msg, wParam, lParam,(LRESULT*)&Result);
break;
}
if (!DoCallBack)
{
@ -1644,6 +1657,9 @@ co_IntSendMessageWithCallBack( HWND hWnd,
case FNID_MESSAGEWND:
DoCallBack = !UserMessageWindowProc(Window, Msg, wParam, lParam,(LRESULT*)&Result);
break;
case FNID_MENU:
DoCallBack = !PopupMenuWndProc( Window, Msg, wParam, lParam,(LRESULT*)&Result);
break;
}
}
@ -2333,13 +2349,21 @@ NtUserMessageCall( HWND hWnd,
}
break;
}
case FNID_MENU:
{
Window = UserGetWindowObject(hWnd);
if (Window)
{
Ret = PopupMenuWndProc( Window, Msg, wParam, lParam, &lResult);
}
break;
}
case FNID_MESSAGEWND:
{
Window = UserGetWindowObject(hWnd);
if (Window)
{
Ret = !UserMessageWindowProc(Window, Msg, wParam, lParam,&lResult);
Ret = !UserMessageWindowProc(Window, Msg, wParam, lParam, &lResult);
}
break;
}
@ -2832,6 +2856,7 @@ NtUserMessageCall( HWND hWnd,
case FNID_CALLWNDPROCRET:
case FNID_SCROLLBAR:
case FNID_DESKTOP:
case FNID_MENU:
if (ResultInfo)
{
_SEH2_TRY

View file

@ -397,6 +397,28 @@ NtUserGetGUIThreadInfo(
CaretInfo = MsgQueue->CaretInfo;
SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0);
/*
if (W32Thread->pMenuState->pGlobalPopupMenu)
{
SafeGui.flags |= GUI_INMENUMODE;
if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify)
SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify);
if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar)
{
if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu)
{
SafeGui.flags |= GUI_SYSTEMMENUMODE;
}
}
else
{
SafeGui.flags |= GUI_POPUPMENUMODE;
}
}
*/
SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
if (MsgQueue->MenuOwner)
SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState;
@ -409,7 +431,6 @@ NtUserGetGUIThreadInfo(
SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0;
SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0;
SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0;
SafeGui.hwndMenuOwner = MsgQueue->MenuOwner;
SafeGui.hwndMoveSize = MsgQueue->MoveSize;
SafeGui.hwndCaret = CaretInfo->hWnd;

View file

@ -2005,8 +2005,28 @@ NTSTATUS FASTCALL
co_MsqWaitForNewMessages(PTHREADINFO pti, PWND WndFilter,
UINT MsgFilterMin, UINT MsgFilterMax)
{
NTSTATUS ret;
NTSTATUS ret = STATUS_SUCCESS;
// Post mouse moves before waiting for messages.
if (pti->MessageQueue->QF_flags & QF_MOUSEMOVED)
{
IntCoalesceMouseMove(pti);
}
if ( pti->nCntsQBits[QSRosMouseButton] != 0 ||
pti->nCntsQBits[QSRosMouseMove] != 0 ||
pti->nCntsQBits[QSRosKey] != 0 ||
pti->nCntsQBits[QSRosSendMessage] != 0 ||
pti->nCntsQBits[QSRosPostMessage] != 0 )
{
TRACE("No time to wait!\n");
return ret;
}
UserLeaveCo();
ZwYieldExecution(); // Let someone else run!
ret = KeWaitForSingleObject( pti->pEventQueueServer,
UserRequest,
UserMode,

View file

@ -274,5 +274,9 @@ UserPostThreadMessage( PTHREADINFO pti,
UINT Msg,
WPARAM wParam,
LPARAM lParam );
BOOL FASTCALL
co_IntWaitMessage( PWND Window,
UINT MsgFilterMin,
UINT MsgFilterMax );
/* EOF */

File diff suppressed because it is too large Load diff

View file

@ -921,23 +921,6 @@ NtUserCtxDisplayIOCtl(
return 0;
}
/*
* @unimplemented
*/
DWORD
APIENTRY
NtUserDrawMenuBarTemp(
HWND hWnd,
HDC hDC,
PRECT hRect,
HMENU hMenu,
HFONT hFont)
{
/* We'll use this function just for caching the menu bar */
STUB
return 0;
}
/*
* FillWindow: Called from User; Dialog, Edit and ListBox procs during a WM_ERASEBKGND.
*/
@ -1013,35 +996,6 @@ NtUserUpdateLayeredWindow(
return 0;
}
/*
* @unimplemented
*/
BOOL APIENTRY
NtUserEndMenu(VOID)
{
STUB
return 0;
}
/*
* @implemented
*/
/* NOTE: unused function */
BOOL APIENTRY
NtUserTrackPopupMenuEx(
HMENU hMenu,
UINT fuFlags,
int x,
int y,
HWND hWnd,
LPTPMPARAMS lptpm)
{
STUB
return FALSE;
}
DWORD APIENTRY
NtUserQuerySendMessage(DWORD Unknown0)
{

View file

@ -1865,8 +1865,6 @@ CLEANUP:
END_CLEANUP;
}
static const WCHAR ELLIPSISW[] = {'.','.','.', 0};
BOOL
UserDrawCaptionText(
PWND pWnd,
@ -1884,7 +1882,6 @@ UserDrawCaptionText(
SIZE Size;
BOOL Ret = TRUE;
ULONG fit = 0, Length;
WCHAR szText[128];
RECTL r = *lpRc;
TRACE("UserDrawCaptionText: %wZ\n", Text);
@ -1936,26 +1933,33 @@ UserDrawCaptionText(
GreGetTextExtentExW(hDc, Text->Buffer, Text->Length/sizeof(WCHAR), r.right - r.left, &fit, 0, &Size, 0);
Length = (Text->Length/sizeof(WCHAR) == fit ? fit : fit+1);
RtlZeroMemory(&szText, sizeof(szText));
RtlCopyMemory(&szText, Text->Buffer, Text->Length);
if (Text->Length/sizeof(WCHAR) > Length && Length > 3)
if (Text->Length/sizeof(WCHAR) > Length)
{
RtlCopyMemory(&szText[Length-3], ELLIPSISW, sizeof(ELLIPSISW));
Ret = FALSE;
}
GreExtTextOutW( hDc,
lpRc->left,
lpRc->top + (lpRc->bottom - lpRc->top) / 2 - Size.cy / 2, // DT_SINGLELINE && DT_VCENTER
ETO_CLIPPED,
(RECTL *)lpRc,
(LPWSTR)&szText,
Length,
NULL,
0 );
if (Ret)
{ // Faster while in setup.
GreExtTextOutW( hDc,
lpRc->left,
lpRc->top + (lpRc->bottom - lpRc->top) / 2 - Size.cy / 2, // DT_SINGLELINE && DT_VCENTER
ETO_CLIPPED,
(RECTL *)lpRc,
Text->Buffer,
Length,
NULL,
0 );
}
else
{
DrawTextW( hDc,
Text->Buffer,
Text->Length/sizeof(WCHAR),
(RECTL *)&r,
DT_END_ELLIPSIS|DT_SINGLELINE|DT_VCENTER|DT_NOPREFIX|DT_LEFT);
}
IntGdiSetTextColor(hDc, OldTextColor);
if (hOldFont)
@ -2209,8 +2213,26 @@ NtUserDrawCaptionTemp(
if (str != NULL)
Ret = UserDrawCaption(pWnd, hDC, &SafeRect, hFont, hIcon, &SafeStr, uFlags);
else
{
if ( RECTL_bIsEmptyRect(&SafeRect) && hFont == 0 && hIcon == 0 )
{
Ret = TRUE;
if (uFlags & DC_DRAWCAPTIONMD)
{
ERR("NC Caption Mode\n");
UserDrawCaptionBar(pWnd, hDC, uFlags);
goto Exit;
}
else if (uFlags & DC_DRAWFRAMEMD)
{
ERR("NC Paint Mode\n");
NC_DoNCPaint(pWnd, hDC, uFlags); // Update Menus too!
goto Exit;
}
}
Ret = UserDrawCaption(pWnd, hDC, &SafeRect, hFont, hIcon, NULL, uFlags);
}
Exit:
UserLeave();
return Ret;
}
@ -2222,7 +2244,7 @@ NtUserDrawCaption(HWND hWnd,
LPCRECT lpRc,
UINT uFlags)
{
return NtUserDrawCaptionTemp(hWnd, hDC, lpRc, 0, 0, NULL, uFlags);
return NtUserDrawCaptionTemp(hWnd, hDC, lpRc, 0, 0, NULL, uFlags);
}
BOOL

View file

@ -33,4 +33,6 @@ HDC FASTCALL IntBeginPaint(PWND,PPAINTSTRUCT);
PCURICON_OBJECT FASTCALL NC_IconForWindow( PWND );
BOOL FASTCALL IntFlashWindowEx(PWND,PFLASHWINFO);
BOOL FASTCALL IntIntersectWithParents(PWND, RECTL *);
BOOL FASTCALL IntIsWindowDrawable(PWND);
BOOL FASTCALL IntIsWindowDrawable(PWND);
BOOL UserDrawCaption(PWND,HDC,RECTL*,HFONT,HICON,const PUNICODE_STRING,UINT);

View file

@ -39,5 +39,11 @@ typedef struct _SBINFOEX
#define SBOBJ_TO_SBID(Obj) ((Obj) - OBJID_HSCROLL)
#define SBID_IS_VALID(id) (id == SB_HORZ || id == SB_VERT || id == SB_CTL)
BOOL FASTCALL co_IntCreateScrollBars(PWND Window);
BOOL FASTCALL IntDestroyScrollBars(PWND Window);
BOOL FASTCALL co_IntCreateScrollBars(PWND);
BOOL FASTCALL IntDestroyScrollBars(PWND);
DWORD FASTCALL co_UserShowScrollBar(PWND,int,BOOL,BOOL);
BOOL FASTCALL co_IntGetScrollBarInfo(PWND,LONG,PSCROLLBARINFO);
BOOL FASTCALL co_IntSetScrollBarInfo(PWND,LONG,PSETSCROLLBARINFO);
void IntDrawScrollBar(PWND,HDC,INT);
BOOL FASTCALL IntScrollWindow(PWND,int,int,CONST RECT*,CONST RECT*);
DWORD FASTCALL IntScrollWindowEx(PWND,INT,INT,const RECT*,const RECT*,HRGN,LPRECT,UINT);

View file

@ -10,6 +10,32 @@
#include <win32k.h>
DBG_DEFAULT_CHANNEL(UserScrollbar);
/* Definitions for scrollbar hit testing [See SCROLLBARINFO in MSDN] */
#define SCROLL_NOWHERE 0x00 /* Outside the scroll bar */
#define SCROLL_TOP_ARROW 0x01 /* Top or left arrow */
#define SCROLL_TOP_RECT 0x02 /* Rectangle between the top arrow and the thumb */
#define SCROLL_THUMB 0x03 /* Thumb rectangle */
#define SCROLL_BOTTOM_RECT 0x04 /* Rectangle between the thumb and the bottom arrow */
#define SCROLL_BOTTOM_ARROW 0x05 /* Bottom or right arrow */
#define SCROLL_FIRST_DELAY 200 /* Delay (in ms) before first repetition when
holding the button down */
#define SCROLL_REPEAT_DELAY 50 /* Delay (in ms) between scroll repetitions */
#define SCROLL_TIMER 0 /* Scroll timer id */
/* Minimum size of the rectangle between the arrows */
#define SCROLL_MIN_RECT 4
/* Minimum size of the thumb in pixels */
#define SCROLL_MIN_THUMB 6
/* Overlap between arrows and thumb */
#define SCROLL_ARROW_THUMB_OVERLAP 0
//
//
//
#define MINTRACKTHUMB 8 /* Minimum size of the rectangle between the arrows */
/* What to do after SetScrollInfo() */
@ -554,6 +580,39 @@ co_IntGetScrollBarInfo(PWND Window, LONG idObject, PSCROLLBARINFO psbi)
return TRUE;
}
BOOL FASTCALL
co_IntSetScrollBarInfo(PWND Window, LONG idObject, PSETSCROLLBARINFO psbi)
{
INT Bar;
PSCROLLBARINFO sbi;
LPSCROLLINFO psi;
ASSERT_REFS_CO(Window);
Bar = SBOBJ_TO_SBID(idObject);
if(!SBID_IS_VALID(Bar))
{
EngSetLastError(ERROR_INVALID_PARAMETER);
ERR("Trying to get scrollinfo for unknown scrollbar type %d\n", Bar);
return FALSE;
}
if(!co_IntCreateScrollBars(Window))
{
ERR("Failed to create scrollbars for window.\n");
return FALSE;
}
sbi = IntGetScrollbarInfoFromWindow(Window, Bar);
psi = IntGetScrollInfoFromWindow(Window, Bar);
psi->nTrackPos = psbi->nTrackPos;
sbi->reserved = psbi->reserved;
RtlCopyMemory(&sbi->rgstate, &psbi->rgstate, sizeof(psbi->rgstate));
return TRUE;
}
BOOL FASTCALL
co_IntCreateScrollBars(PWND Window)
{
@ -709,6 +768,248 @@ co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV)
return FALSE;
}
static void
IntDrawScrollInterior(PWND pWnd, HDC hDC, INT nBar, BOOL Vertical, PSCROLLBARINFO ScrollBarInfo)
{
INT ThumbSize = ScrollBarInfo->xyThumbBottom - ScrollBarInfo->xyThumbTop;
INT ThumbTop = ScrollBarInfo->xyThumbTop;
RECT Rect;
HBRUSH hSaveBrush, hBrush;
BOOL TopSelected = FALSE, BottomSelected = FALSE;
if (ScrollBarInfo->rgstate[SCROLL_TOP_RECT] & STATE_SYSTEM_PRESSED)
TopSelected = TRUE;
if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_RECT] & STATE_SYSTEM_PRESSED)
BottomSelected = TRUE;
/*
* Only scrollbar controls send WM_CTLCOLORSCROLLBAR.
* The window-owned scrollbars need to call DefWndControlColor
* to correctly setup default scrollbar colors
*/
if (nBar == SB_CTL)
{
hBrush = GetControlBrush( pWnd, hDC, WM_CTLCOLORSCROLLBAR);
if (!hBrush)
hBrush = IntGetSysColorBrush(COLOR_SCROLLBAR);
}
else
{
hBrush = DefWndControlColor(hDC, CTLCOLOR_SCROLLBAR);
}
hSaveBrush = NtGdiSelectBrush(hDC, hBrush);
/* Calculate the scroll rectangle */
if (Vertical)
{
Rect.top = ScrollBarInfo->rcScrollBar.top + ScrollBarInfo->dxyLineButton;
Rect.bottom = ScrollBarInfo->rcScrollBar.bottom - ScrollBarInfo->dxyLineButton;
Rect.left = ScrollBarInfo->rcScrollBar.left;
Rect.right = ScrollBarInfo->rcScrollBar.right;
}
else
{
Rect.top = ScrollBarInfo->rcScrollBar.top;
Rect.bottom = ScrollBarInfo->rcScrollBar.bottom;
Rect.left = ScrollBarInfo->rcScrollBar.left + ScrollBarInfo->dxyLineButton;
Rect.right = ScrollBarInfo->rcScrollBar.right - ScrollBarInfo->dxyLineButton;
}
/* Draw the scroll rectangles and thumb */
if (!ScrollBarInfo->xyThumbBottom)
{
NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left,
Rect.bottom - Rect.top, PATCOPY);
/* Cleanup and return */
NtGdiSelectBrush(hDC, hSaveBrush);
return;
}
ThumbTop -= ScrollBarInfo->dxyLineButton;
if (ScrollBarInfo->dxyLineButton)
{
if (Vertical)
{
if (ThumbSize)
{
NtGdiPatBlt(hDC, Rect.left, Rect.top, Rect.right - Rect.left,
ThumbTop, TopSelected ? BLACKNESS : PATCOPY);
Rect.top += ThumbTop;
NtGdiPatBlt(hDC, Rect.left, Rect.top + ThumbSize, Rect.right - Rect.left,
Rect.bottom - Rect.top - ThumbSize, BottomSelected ? BLACKNESS : PATCOPY);
Rect.bottom = Rect.top + ThumbSize;
}
else
{
if (ThumbTop)
{
NtGdiPatBlt(hDC, Rect.left, ScrollBarInfo->dxyLineButton,
Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY);
}
}
}
else
{
if (ThumbSize)
{
NtGdiPatBlt(hDC, Rect.left, Rect.top, ThumbTop,
Rect.bottom - Rect.top, TopSelected ? BLACKNESS : PATCOPY);
Rect.left += ThumbTop;
NtGdiPatBlt(hDC, Rect.left + ThumbSize, Rect.top,
Rect.right - Rect.left - ThumbSize, Rect.bottom - Rect.top,
BottomSelected ? BLACKNESS : PATCOPY);
Rect.right = Rect.left + ThumbSize;
}
else
{
if (ThumbTop)
{
NtGdiPatBlt(hDC, ScrollBarInfo->dxyLineButton, Rect.top,
Rect.right - Rect.left, Rect.bottom - Rect.top, PATCOPY);
}
}
}
}
/* Draw the thumb */
if (ThumbSize)
DrawEdge(hDC, &Rect, EDGE_RAISED, BF_RECT | BF_MIDDLE);
/* Cleanup */
NtGdiSelectBrush(hDC, hSaveBrush);
}
static VOID FASTCALL
IntDrawScrollArrows(HDC hDC, PSCROLLBARINFO ScrollBarInfo, BOOL Vertical)
{
RECT RectLT, RectRB;
INT ScrollDirFlagLT, ScrollDirFlagRB;
RectLT = RectRB = ScrollBarInfo->rcScrollBar;
if (Vertical)
{
ScrollDirFlagLT = DFCS_SCROLLUP;
ScrollDirFlagRB = DFCS_SCROLLDOWN;
RectLT.bottom = RectLT.top + ScrollBarInfo->dxyLineButton;
RectRB.top = RectRB.bottom - ScrollBarInfo->dxyLineButton;
}
else
{
ScrollDirFlagLT = DFCS_SCROLLLEFT;
ScrollDirFlagRB = DFCS_SCROLLRIGHT;
RectLT.right = RectLT.left + ScrollBarInfo->dxyLineButton;
RectRB.left = RectRB.right - ScrollBarInfo->dxyLineButton;
}
if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_PRESSED)
{
ScrollDirFlagLT |= DFCS_PUSHED | DFCS_FLAT;
}
if (ScrollBarInfo->rgstate[SCROLL_TOP_ARROW] & STATE_SYSTEM_UNAVAILABLE)
{
ScrollDirFlagLT |= DFCS_INACTIVE;
}
if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_PRESSED)
{
ScrollDirFlagRB |= DFCS_PUSHED | DFCS_FLAT;
}
if (ScrollBarInfo->rgstate[SCROLL_BOTTOM_ARROW] & STATE_SYSTEM_UNAVAILABLE)
{
ScrollDirFlagRB |= DFCS_INACTIVE;
}
DrawFrameControl(hDC, &RectLT, DFC_SCROLL, ScrollDirFlagLT);
DrawFrameControl(hDC, &RectRB, DFC_SCROLL, ScrollDirFlagRB);
}
static LONG FASTCALL
IntScrollGetObjectId(INT SBType)
{
if (SBType == SB_VERT)
return OBJID_VSCROLL;
if (SBType == SB_HORZ)
return OBJID_HSCROLL;
return OBJID_CLIENT;
}
void
IntDrawScrollBar(PWND Wnd, HDC DC, INT Bar)
{
//PSBWND pSBWnd;
//INT ThumbSize;
PTHREADINFO pti;
SCROLLBARINFO Info;
BOOL Vertical;
pti = PsGetCurrentThreadWin32Thread();
/*
* Get scroll bar info.
*/
switch (Bar)
{
case SB_HORZ:
Vertical = FALSE;
break;
case SB_VERT:
Vertical = TRUE;
break;
case SB_CTL:
Vertical = (Wnd->style & SBS_VERT) != 0;
break;
default:
return;
}
if (!co_IntGetScrollBarInfo(Wnd, IntScrollGetObjectId(Bar), &Info))
{
return;
}
if (RECTL_bIsEmptyRect(&Info.rcScrollBar))
{
return;
}
//ThumbSize = pSBWnd->pSBCalc->pxThumbBottom - pSBWnd->pSBCalc->pxThumbTop;
/*
* Draw the arrows.
*/
if (Info.dxyLineButton)
{
IntDrawScrollArrows(DC, &Info, Vertical);
}
/*
* Draw the interior.
*/
IntDrawScrollInterior(Wnd, DC, Bar, Vertical, &Info);
/*
* If scroll bar has focus, reposition the caret.
*/
if ( Wnd == pti->MessageQueue->spwndFocus && Bar == SB_CTL )
{
if (Vertical)
{
co_IntSetCaretPos(Info.rcScrollBar.top + 1, Info.dxyLineButton + 1);
}
else
{
co_IntSetCaretPos(Info.dxyLineButton + 1, Info.rcScrollBar.top + 1);
}
}
}
LRESULT APIENTRY
ScrollBarWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{

View file

@ -226,6 +226,241 @@ UserScrollDC(
return Result;
}
DWORD
FASTCALL
IntScrollWindowEx(
PWND Window,
INT dx,
INT dy,
const RECT *prcScroll,
const RECT *prcClip,
HRGN hrgnUpdate,
LPRECT prcUpdate,
UINT flags)
{
RECTL rcScroll, rcClip, rcCaret;
INT Result;
PWND CaretWnd;
HDC hDC;
PREGION RgnUpdate = NULL, RgnTemp, RgnWinupd = NULL;
HWND hwndCaret;
DWORD dcxflags = 0;
int rdw_flags;
USER_REFERENCE_ENTRY CaretRef;
IntGetClientRect(Window, &rcClip);
if (prcScroll)
{
RECTL_bIntersectRect(&rcScroll, &rcClip, prcScroll);
}
else
rcScroll = rcClip;
if (prcClip)
{
RECTL_bIntersectRect(&rcClip, &rcClip, prcClip);
}
if (rcClip.right <= rcClip.left || rcClip.bottom <= rcClip.top ||
(dx == 0 && dy == 0))
{
return NULLREGION;
}
/* We must use a copy of the region, as we can't hold an exclusive lock
* on it while doing callouts to user-mode */
RgnUpdate = IntSysCreateRectpRgn(0, 0, 0, 0);
if(!RgnUpdate)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return ERROR;
}
if (hrgnUpdate)
{
RgnTemp = REGION_LockRgn(hrgnUpdate);
if (!RgnTemp)
{
EngSetLastError(ERROR_INVALID_HANDLE);
return ERROR;
}
IntGdiCombineRgn(RgnUpdate, RgnTemp, NULL, RGN_COPY);
REGION_UnlockRgn(RgnTemp);
}
/* ScrollWindow uses the window DC, ScrollWindowEx doesn't */
if (flags & SW_SCROLLWNDDCE)
{
dcxflags = DCX_USESTYLE;
if (!(Window->pcls->style & (CS_OWNDC|CS_CLASSDC)))
dcxflags |= DCX_CACHE; // AH??? wine~ If not Powned or with Class go Cheap!
if (flags & SW_SCROLLCHILDREN && Window->style & WS_CLIPCHILDREN)
dcxflags |= DCX_CACHE|DCX_NOCLIPCHILDREN;
}
else
{
/* So in this case ScrollWindowEx uses Cache DC. */
dcxflags = DCX_CACHE|DCX_USESTYLE;
if (flags & SW_SCROLLCHILDREN) dcxflags |= DCX_NOCLIPCHILDREN;
}
hDC = UserGetDCEx(Window, 0, dcxflags);
if (!hDC)
{
/* FIXME: SetLastError? */
return ERROR;
}
rdw_flags = (flags & SW_ERASE) && (flags & SW_INVALIDATE) ? RDW_INVALIDATE | RDW_ERASE : RDW_INVALIDATE ;
rcCaret = rcScroll;
hwndCaret = co_IntFixCaret(Window, &rcCaret, flags);
Result = UserScrollDC( hDC,
dx,
dy,
&rcScroll,
&rcClip,
NULL,
RgnUpdate,
prcUpdate);
UserReleaseDC(Window, hDC, FALSE);
/*
* Take into account the fact that some damage may have occurred during
* the scroll. Keep a copy in hrgnWinupd to be added to hrngUpdate at the end.
*/
RgnTemp = IntSysCreateRectpRgn(0, 0, 0, 0);
if (!RgnTemp)
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return ERROR;
}
if (co_IntGetUpdateRgn(Window, RgnTemp, FALSE) != NULLREGION)
{
PREGION RgnClip = IntSysCreateRectpRgnIndirect(&rcClip);
if (RgnClip)
{
if (hrgnUpdate)
{
RgnWinupd = IntSysCreateRectpRgn( 0, 0, 0, 0);
IntGdiCombineRgn( RgnWinupd, RgnTemp, 0, RGN_COPY);
}
REGION_bOffsetRgn(RgnTemp, dx, dy);
IntGdiCombineRgn(RgnTemp, RgnTemp, RgnClip, RGN_AND);
if (hrgnUpdate)
IntGdiCombineRgn( RgnWinupd, RgnWinupd, RgnTemp, RGN_OR );
co_UserRedrawWindow(Window, NULL, RgnTemp, rdw_flags );
REGION_Delete(RgnClip);
}
}
REGION_Delete(RgnTemp);
if (flags & SW_SCROLLCHILDREN)
{
PWND Child;
RECTL rcChild;
POINT ClientOrigin;
USER_REFERENCE_ENTRY WndRef;
RECTL rcDummy;
LPARAM lParam;
IntGetClientOrigin(Window, &ClientOrigin);
for (Child = Window->spwndChild; Child; Child = Child->spwndNext)
{
rcChild = Child->rcWindow;
rcChild.left -= ClientOrigin.x;
rcChild.top -= ClientOrigin.y;
rcChild.right -= ClientOrigin.x;
rcChild.bottom -= ClientOrigin.y;
if (!prcScroll || RECTL_bIntersectRect(&rcDummy, &rcChild, &rcScroll))
{
UserRefObjectCo(Child, &WndRef);
if (Window->spwndParent == UserGetDesktopWindow()) // Window->spwndParent->fnid == FNID_DESKTOP )
lParam = MAKELONG(Child->rcClient.left, Child->rcClient.top);
else
lParam = MAKELONG(rcChild.left + dx, rcChild.top + dy);
/* wine sends WM_POSCHANGING, WM_POSCHANGED messages */
/* windows sometimes a WM_MOVE */
co_IntSendMessage(UserHMGetHandle(Child), WM_MOVE, 0, lParam);
UserDerefObjectCo(Child);
}
}
}
if (flags & (SW_INVALIDATE | SW_ERASE))
{
co_UserRedrawWindow( Window,
NULL,
RgnUpdate,
rdw_flags | /* HACK */
((flags & SW_SCROLLCHILDREN) ? RDW_ALLCHILDREN : RDW_NOCHILDREN) );
}
if (hwndCaret && (CaretWnd = UserGetWindowObject(hwndCaret)))
{
UserRefObjectCo(CaretWnd, &CaretRef);
co_IntSetCaretPos(rcCaret.left + dx, rcCaret.top + dy);
co_UserShowCaret(CaretWnd);
UserDerefObjectCo(CaretWnd);
}
if (hrgnUpdate && (Result != ERROR))
{
/* Give everything back to the caller */
RgnTemp = REGION_LockRgn(hrgnUpdate);
/* The handle should still be valid */
ASSERT(RgnTemp);
if (RgnWinupd)
IntGdiCombineRgn(RgnTemp, RgnUpdate, RgnWinupd, RGN_OR);
else
IntGdiCombineRgn(RgnTemp, RgnUpdate, NULL, RGN_COPY);
REGION_UnlockRgn(RgnTemp);
}
if (RgnWinupd)
{
REGION_Delete(RgnWinupd);
}
if (RgnUpdate)
{
REGION_Delete(RgnUpdate);
}
return Result;
}
BOOL FASTCALL
IntScrollWindow(PWND pWnd,
int dx,
int dy,
CONST RECT *lpRect,
CONST RECT *prcClip)
{
return IntScrollWindowEx( pWnd, dx, dy, lpRect, prcClip, 0, NULL,
(lpRect ? 0 : SW_SCROLLCHILDREN) | (SW_ERASE|SW_INVALIDATE|SW_SCROLLWNDDCE)) != ERROR;
}
/*
* NtUserScrollDC
*

View file

@ -2,7 +2,12 @@
FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
{
return UserGetObject(gHandleTable, hMenu, TYPE_MENU);
PMENU pMenu = UserGetObject(gHandleTable, hMenu, TYPE_MENU);
if (!pMenu)
{
EngSetLastError(ERROR_INVALID_MENU_HANDLE);
}
return pMenu;
}
#define ASSERT_REFS_CO(_obj_) \
@ -97,14 +102,11 @@ UserSystemParametersInfo(
VOID FASTCALL IntSetWindowState(PWND, UINT);
VOID FASTCALL IntClearWindowState(PWND, UINT);
PTHREADINFO FASTCALL IntTID2PTI(HANDLE);
HBRUSH FASTCALL GetControlBrush(PWND pwnd,HDC hdc,UINT ctlType);
/*************** MESSAGE.C ***************/
BOOL FASTCALL
UserPostMessage(HWND Wnd,
UINT Msg,
WPARAM wParam,
LPARAM lParam);
BOOL FASTCALL UserPostMessage(HWND Wnd,UINT Msg, WPARAM wParam, LPARAM lParam);
/*************** WINDOW.C ***************/
@ -114,6 +116,8 @@ HWND FASTCALL UserGetShellWindow(VOID);
HDC FASTCALL UserGetDCEx(PWND Window OPTIONAL, HANDLE ClipRegion, ULONG Flags);
BOOLEAN co_UserDestroyWindow(PVOID Object);
PWND FASTCALL UserGetAncestor(PWND Wnd, UINT Type);
BOOL APIENTRY DefSetText(PWND Wnd, PCWSTR WindowText);
DWORD FASTCALL IntGetWindowContextHelpId( PWND pWnd );
/*************** MENU.C ***************/
@ -121,12 +125,24 @@ HMENU FASTCALL UserCreateMenu(PDESKTOP Desktop, BOOL PopupMenu);
BOOL FASTCALL UserSetMenuDefaultItem(PMENU Menu, UINT uItem, UINT fByPos);
BOOL FASTCALL UserDestroyMenu(HMENU hMenu);
/*************** SCROLLBAR.C ***************/
DWORD FASTCALL co_UserShowScrollBar(PWND Wnd, int nBar, BOOL fShowH, BOOL fShowV);
/************** NONCLIENT **************/
VOID FASTCALL DefWndDoSizeMove(PWND pwnd, WORD wParam);
LRESULT NC_DoNCPaint(PWND,HDC,INT);
void FASTCALL NC_GetSysPopupPos(PWND, RECT *);
LRESULT NC_HandleNCActivate( PWND Wnd, WPARAM wParam, LPARAM lParam );
LRESULT NC_HandleNCCalcSize( PWND wnd, WPARAM wparam, RECTL *winRect );
VOID NC_DrawFrame( HDC hDC, RECT *CurrentRect, BOOL Active, DWORD Style, DWORD ExStyle);
VOID UserDrawCaptionBar( PWND pWnd, HDC hDC, INT Flags);
void UserGetInsideRectNC(PWND Wnd, RECT *rect);
LRESULT NC_HandleNCLButtonDown(PWND Wnd, WPARAM wParam, LPARAM lParam);
LRESULT NC_HandleNCLButtonDblClk(PWND Wnd, WPARAM wParam, LPARAM lParam);
LRESULT NC_HandleNCRButtonDown( PWND wnd, WPARAM wParam, LPARAM lParam );
/************** DEFWND **************/
HBRUSH FASTCALL DefWndControlColor(HDC hDC,UINT ctlType);
BOOL UserDrawSysMenuButton(PWND pWnd, HDC hDC, LPRECT Rect, BOOL Down);
BOOL UserPaintCaption(PWND pWnd, INT Flags);
/* EOF */

View file

@ -52,8 +52,6 @@ extern HANDLE hModuleWin; // This Win32k Instance.
extern struct _CLS *SystemClassList;
extern BOOL RegisteredSysClasses;
typedef struct tagMENUSTATE MENUSTATE, *PMENUSTATE;
#include <pshpack1.h>
// FIXME: Move to ntuser.h
typedef struct _TL
@ -110,7 +108,7 @@ typedef struct _THREADINFO
HDESK hdesk;
UINT cPaintsReady; /* Count of paints pending. */
UINT cTimersReady; /* Count of timers pending. */
PMENUSTATE pMenuState;
struct tagMENUSTATE* pMenuState;
DWORD dwExpWinVer;
DWORD dwCompatFlags;
DWORD dwCompatFlags2;

View file

@ -65,9 +65,12 @@ PWND FASTCALL VerifyWnd(PWND pWnd)
{
HWND hWnd;
UINT State, State2;
ULONG Error;
if (!pWnd) return NULL;
Error = EngGetLastError();
_SEH2_TRY
{
hWnd = UserHMGetHandle(pWnd);
@ -76,6 +79,7 @@ PWND FASTCALL VerifyWnd(PWND pWnd)
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
EngSetLastError(Error);
_SEH2_YIELD(return NULL);
}
_SEH2_END
@ -83,8 +87,9 @@ PWND FASTCALL VerifyWnd(PWND pWnd)
if ( UserObjectInDestroy(hWnd) ||
State & WNDS_DESTROYED ||
State2 & WNDS2_INDESTROY )
return NULL;
pWnd = NULL;
EngSetLastError(Error);
return pWnd;
}
@ -362,6 +367,20 @@ IntGetWindow(HWND hWnd,
return Ret;
}
DWORD FASTCALL IntGetWindowContextHelpId( PWND pWnd )
{
PPROPERTY HelpId;
do
{
HelpId = IntGetProp(pWnd, gpsi->atomContextHelpIdProp);
if (!HelpId) break;
pWnd = IntGetParent(pWnd);
}
while (pWnd && pWnd->fnid != FNID_DESKTOP);
return (DWORD) (HelpId ? HelpId->Data : 0 );
}
/***********************************************************************
* IntSendDestroyMsg
*/
@ -593,6 +612,7 @@ LRESULT co_UserFreeWindow(PWND Window,
Window->IDMenu &&
(Menu = UserGetMenuObject((HMENU)Window->IDMenu)))
{
TRACE("UFW: IDMenu %p\n",Window->IDMenu);
IntDestroyMenuObject(Menu, TRUE);
Window->IDMenu = 0;
}
@ -3497,7 +3517,7 @@ co_IntSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi, BOOL bAlte
Ansi);
if (!OldValue) return 0;
}
*/
*/
*((LONG *)((PCHAR)(Window + 1) + Index)) = NewValue;
}
else
@ -3913,6 +3933,78 @@ CLEANUP:
END_CLEANUP;
}
BOOL APIENTRY
DefSetText(PWND Wnd, PCWSTR WindowText)
{
UNICODE_STRING UnicodeString;
BOOL Ret = FALSE;
RtlInitUnicodeString(&UnicodeString, WindowText);
if (UnicodeString.Length != 0)
{
if (Wnd->strName.MaximumLength > 0 &&
UnicodeString.Length <= Wnd->strName.MaximumLength - sizeof(UNICODE_NULL))
{
ASSERT(Wnd->strName.Buffer != NULL);
Wnd->strName.Length = UnicodeString.Length;
Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
RtlCopyMemory(Wnd->strName.Buffer,
UnicodeString.Buffer,
UnicodeString.Length);
}
else
{
PWCHAR buf;
Wnd->strName.MaximumLength = Wnd->strName.Length = 0;
buf = Wnd->strName.Buffer;
Wnd->strName.Buffer = NULL;
if (buf != NULL)
{
DesktopHeapFree(Wnd->head.rpdesk, buf);
}
Wnd->strName.Buffer = DesktopHeapAlloc(Wnd->head.rpdesk,
UnicodeString.Length + sizeof(UNICODE_NULL));
if (Wnd->strName.Buffer != NULL)
{
Wnd->strName.Buffer[UnicodeString.Length / sizeof(WCHAR)] = L'\0';
RtlCopyMemory(Wnd->strName.Buffer,
UnicodeString.Buffer,
UnicodeString.Length);
Wnd->strName.MaximumLength = UnicodeString.Length + sizeof(UNICODE_NULL);
Wnd->strName.Length = UnicodeString.Length;
}
else
{
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto Exit;
}
}
}
else
{
Wnd->strName.Length = 0;
if (Wnd->strName.Buffer != NULL)
Wnd->strName.Buffer[0] = L'\0';
}
// FIXME: HAX! Windows does not do this in here!
// In User32, these are called after: NotifyWinEvent EVENT_OBJECT_NAMECHANGE than
// RepaintButton, StaticRepaint, NtUserCallHwndLock HWNDLOCK_ROUTINE_REDRAWFRAMEANDHOOK, etc.
/* Send shell notifications */
if (!Wnd->spwndOwner && !IntGetParent(Wnd))
{
co_IntShellHookNotify(HSHELL_REDRAW, (WPARAM) UserHMGetHandle(Wnd), FALSE); // FIXME Flashing?
}
Ret = TRUE;
Exit:
if (UnicodeString.Buffer) RtlFreeUnicodeString(&UnicodeString);
return Ret;
}
/*
* NtUserDefSetText
*

View file

@ -55,6 +55,10 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
PWND OwnerWindow,
PVOID acbiBuffer,
PDESKTOP pdeskCreated);
PWND FASTCALL co_UserCreateWindowEx(CREATESTRUCTW* Cs,
PUNICODE_STRING ClassName,
PLARGE_STRING WindowName,
PVOID acbiBuffer);
BOOL FASTCALL IntEnableWindow(HWND,BOOL);
BOOL FASTCALL IntIsWindowVisible(PWND);
DWORD FASTCALL GetNCHitEx(PWND,POINT);

View file

@ -2280,7 +2280,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
Cmd = SW_SHOWDEFAULT;
}
FirstTime = TRUE;
ERR("co_WPSW FT 1\n");
TRACE("co_WPSW FT 1\n");
}
}
}
@ -2292,7 +2292,7 @@ co_WinPosShowWindow(PWND Wnd, INT Cmd)
{
Cmd = pti->ppi->usi.wShowWindow;
FirstTime = TRUE;
ERR("co_WPSW FT 2\n");
TRACE("co_WPSW FT 2\n");
}
}

View file

@ -69,3 +69,5 @@ PWND FASTCALL IntRealChildWindowFromPoint(PWND,LONG,LONG);
BOOL FASTCALL IntScreenToClient(PWND,LPPOINT);
BOOL FASTCALL IntClientToScreen(PWND,LPPOINT);
BOOL FASTCALL IntGetWindowRect(PWND,RECTL*);
BOOL UserHasWindowEdge(DWORD,DWORD);
VOID UserGetWindowBorders(DWORD,DWORD,SIZE*,BOOL);

View file

@ -297,6 +297,9 @@ co_IntInitializeDesktopGraphics(VOID)
/* Setup the icons */
co_IntSetWndIcons();
/* Setup Menu */
MenuInit();
/* Show the desktop */
pdesk = IntGetActiveDesktop();
ASSERT(pdesk);

File diff suppressed because it is too large Load diff

View file

@ -60,6 +60,7 @@ list(APPEND SOURCE
windows/text.c
windows/window.c
windows/winpos.c
${REACTOS_SOURCE_DIR}/win32ss/user/rtl/text.c
${CMAKE_CURRENT_BINARY_DIR}/user32_stubs.c
include/user32.h)

View file

@ -34,7 +34,7 @@ LRESULT WINAPI RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags
DWORD gcLoadUserApiHook = 0;
LONG gcCallUserApiHook = 0;
DWORD gfUserApiHook;
DWORD gfUserApiHook = 0;
HINSTANCE ghmodUserApiHook = NULL;
USERAPIHOOKPROC gpfnInitUserApi;
RTL_CRITICAL_SECTION gcsUserApiHook;

View file

@ -184,7 +184,7 @@
@ stdcall DrawIcon(long long long long)
@ stdcall DrawIconEx(long long long long long long long long long)
@ stdcall DrawMenuBar(long)
@ stdcall DrawMenuBarTemp(long long long long long)
@ stdcall DrawMenuBarTemp(long long long long long) NtUserDrawMenuBarTemp
@ stdcall DrawStateA(long long ptr long long long long long long long)
@ stdcall DrawStateW(long long ptr long long long long long long long)
@ stdcall DrawTextA(long str long ptr long)
@ -198,7 +198,7 @@
@ stdcall EnableWindow(long long)
@ stdcall EndDeferWindowPos(long)
@ stdcall EndDialog(long long)
@ stdcall EndMenu()
@ stdcall EndMenu() NtUserEndMenu
@ stdcall EndPaint(long ptr) NtUserEndPaint
@ stdcall EndTask(ptr long long)
@ stdcall EnterReaderModeHelper(ptr)
@ -302,7 +302,7 @@
@ stdcall GetLayeredWindowAttributes(long ptr ptr ptr) NtUserGetLayeredWindowAttributes
@ stdcall GetListBoxInfo(long) NtUserGetListBoxInfo
@ stdcall GetMenu(long)
@ stdcall GetMenuBarInfo(long long long ptr) ; tempo haxzo NtUserGetMenuBarInfo
@ stdcall GetMenuBarInfo(long long long ptr) NtUserGetMenuBarInfo
@ stdcall GetMenuCheckMarkDimensions()
@ stdcall GetMenuContextHelpId(long)
@ stdcall GetMenuDefaultItem(long long long)
@ -349,7 +349,7 @@
@ stdcall GetSubMenu(long long)
@ stdcall GetSysColor(long)
@ stdcall GetSysColorBrush(long)
@ stdcall GetSystemMenu(long long) ; Direct call NtUserGetSystemMenu
@ stdcall GetSystemMenu(long long) ; NtUserGetSystemMenu
@ stdcall GetSystemMetrics(long)
@ stdcall GetTabbedTextExtentA(long str long long ptr)
@ stdcall GetTabbedTextExtentW(long wstr long long ptr)
@ -387,7 +387,7 @@
@ stdcall GrayStringA(long long ptr long long long long long long)
@ stdcall GrayStringW(long long ptr long long long long long long)
@ stdcall HideCaret(long) NtUserHideCaret
@ stdcall HiliteMenuItem(long long long long) ; Use both ReactOS and wine NtUserHiliteMenuItem
@ stdcall HiliteMenuItem(long long long long) NtUserHiliteMenuItem
@ stdcall IMPGetIMEA(long ptr)
@ stdcall IMPGetIMEW(long ptr)
@ stdcall IMPQueryIMEA(ptr)
@ -478,7 +478,7 @@
@ stdcall MapVirtualKeyExW(long long long)
@ stdcall MapVirtualKeyW(long long)
@ stdcall MapWindowPoints(long long ptr long)
@ stdcall MenuItemFromPoint(long long double) ; Direct call NtUserMenuItemFromPoint
@ stdcall MenuItemFromPoint(long long double) NtUserMenuItemFromPoint
@ stdcall MenuWindowProcA (long ptr long long long)
@ stdcall MenuWindowProcW (long ptr long long long)
@ stdcall MessageBeep(long)
@ -635,7 +635,7 @@
@ stdcall SetSysColors(long ptr ptr)
@ stdcall SetSysColorsTemp(ptr ptr long)
@ stdcall SetSystemCursor(long long)
@ stdcall SetSystemMenu(long long) ; Direct call NtUserSetSystemMenu
@ stdcall SetSystemMenu(long long) ; NtUserSetSystemMenu
@ stdcall SetSystemTimer(long long long ptr) NtUserSetSystemTimer
@ stdcall SetTaskmanWindow (long)
@ stdcall SetThreadDesktop(long) NtUserSetThreadDesktop
@ -684,7 +684,7 @@
@ stdcall ToUnicodeEx(long long ptr ptr long long long)
@ stdcall TrackMouseEvent(ptr) NtUserTrackMouseEvent
@ stdcall TrackPopupMenu(long long long long long long ptr)
@ stdcall TrackPopupMenuEx(long long long long long ptr) ; Direct call NtUserTrackPopupMenuEx
@ stdcall TrackPopupMenuEx(long long long long long ptr) NtUserTrackPopupMenuEx
@ stdcall TranslateAccelerator(long long ptr) TranslateAcceleratorA
@ stdcall TranslateAcceleratorA(long long ptr)
@ stdcall TranslateAcceleratorW(long long ptr)

View file

@ -16,21 +16,10 @@
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(user32);
LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
LRESULT DefWndNCCalcSize(HWND hWnd, BOOL CalcSizeStruct, RECT *Rect);
LRESULT DefWndNCActivate(HWND hWnd, WPARAM wParam, LPARAM lParam);
LRESULT DefWndNCHitTest(HWND hWnd, POINT Point);
LRESULT DefWndNCLButtonDown(HWND hWnd, WPARAM wParam, LPARAM lParam);
LRESULT DefWndNCLButtonDblClk(HWND hWnd, WPARAM wParam, LPARAM lParam);
LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam );
void FASTCALL MenuInitSysMenuPopup(HMENU Menu, DWORD Style, DWORD ClsStyle, LONG HitTest );
void MENU_EndMenu( HWND );
/* GLOBALS *******************************************************************/
static short iF10Key = 0;
static short iMenuSysKey = 0;
/* FUNCTIONS *****************************************************************/
/*
@ -219,6 +208,21 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
if (!IsWindowEnabled( hWnd )) return 0;
switch (wParam & 0xfff0)
{
case SC_MOVE:
case SC_SIZE:
// case SC_DEFAULT:
case SC_MOUSEMENU:
case SC_KEYMENU:
case SC_SCREENSAVE:
NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
return 0;
default:
break;
}
if (ISITHOOKED(WH_CBT))
{
NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
@ -227,10 +231,6 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
switch (wParam & 0xfff0)
{
case SC_MOVE:
case SC_SIZE:
NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
break;
case SC_MINIMIZE:
if (hWnd == GetActiveWindow())
@ -253,17 +253,6 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
case SC_CLOSE:
return SendMessageW(hWnd, WM_CLOSE, 0, 0);
// case SC_DEFAULT:
case SC_MOUSEMENU:
{
Pt.x = (short)LOWORD(lParam);
Pt.y = (short)HIWORD(lParam);
MenuTrackMouseMenuBar(hWnd, wParam & 0x000f, Pt);
}
break;
case SC_KEYMENU:
MenuTrackKbdMenuBar(hWnd, wParam, (WCHAR)lParam);
break;
case SC_VSCROLL:
case SC_HSCROLL:
{
@ -277,9 +266,6 @@ DefWndHandleSysCommand(HWND hWnd, WPARAM wParam, LPARAM lParam)
WinExec( "taskman.exe", SW_SHOWNORMAL );
break;
case SC_SCREENSAVE:
NtUserMessageCall( hWnd, WM_SYSCOMMAND, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, FALSE);
break;
case SC_NEXTWINDOW:
case SC_PREVWINDOW:
@ -359,38 +345,6 @@ DefWndControlColor(HDC hDC, UINT ctlType)
return GetSysColorBrush(COLOR_WINDOW);
}
static void DefWndPrint( HWND hwnd, HDC hdc, ULONG uFlags)
{
/*
* Visibility flag.
*/
if ( (uFlags & PRF_CHECKVISIBLE) &&
!IsWindowVisible(hwnd) )
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)
SendMessageW(hwnd, WM_ERASEBKGND, (WPARAM)hdc, 0);
/*
* Client area
*/
if ( uFlags & PRF_CLIENT)
SendMessageW(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, uFlags);
}
static BOOL CALLBACK
UserSendUiUpdateMsg(HWND hwnd, LPARAM lParam)
{
@ -398,21 +352,13 @@ UserSendUiUpdateMsg(HWND hwnd, LPARAM lParam)
return TRUE;
}
/*
RealUserDrawCaption: This function is passed through RegisterUserApiHook to uxtheme
to call it when the classic caption is needed to be drawn.
*/
LRESULT WINAPI
RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags)
{
return DefWndNCPaint(hWnd, HRGN_WINDOW, -1);
}
static void
UserPaintCaption(HWND hwnd)
UserPaintCaption(PWND pwnd, INT Flags)
{
/* FIXME: this is not 100% correct */
if ( pwnd->style & WS_VISIBLE && (pwnd->style & WS_CAPTION) == WS_CAPTION )
{
if (pwnd->state & WNDS_HASCAPTION && NtUserQueryWindow(UserHMGetHandle(pwnd), QUERY_WINDOW_FOREGROUND))
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.
@ -426,51 +372,16 @@ UserPaintCaption(HWND hwnd)
* RealUserDrawCaption in order to draw the classic caption when themes
* are disabled but the themes service is enabled
*/
SendMessage(hwnd, WM_NCUAHDRAWCAPTION,0,0);
SendMessageW(UserHMGetHandle(pwnd), WM_NCUAHDRAWCAPTION, Flags, 0);
}
else
{
DefWndNCPaint(hwnd, HRGN_WINDOW, -1);
RECT rc = {0,0,0,0};
HDC hDC = GetDCEx(UserHMGetHandle(pwnd), NULL, DCX_WINDOW|DCX_USESTYLE);
NtUserDrawCaption(UserHMGetHandle(pwnd), hDC, &rc, DC_DRAWCAPTIONMD|Flags);
ReleaseDC(UserHMGetHandle(pwnd), hDC);
}
}
// WM_SETICON
LRESULT FASTCALL
DefWndSetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
{
HICON hIcon, hIconSmall, hIconOld;
if ( wParam > ICON_SMALL2 )
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
hIconSmall = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp);
hIcon = UserGetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp);
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;
}
NtUserSetProp(UserHMGetHandle(pWnd), gpsi->atomIconProp, hIcon);
NtUserSetProp(UserHMGetHandle(pWnd), gpsi->atomIconSmProp, hIconSmall);
if ((pWnd->style & WS_CAPTION ) == WS_CAPTION)
UserPaintCaption(UserHMGetHandle(pWnd)); /* Repaint caption */
return (LRESULT)hIconOld;
}
}
LRESULT FASTCALL
@ -497,41 +408,6 @@ DefWndGetIcon(PWND pWnd, WPARAM wParam, LPARAM lParam)
return (LRESULT)hIconRet;
}
VOID FASTCALL
DefWndScreenshot(HWND hWnd)
{
RECT rect;
HDC hdc;
INT w;
INT h;
HBITMAP hbitmap;
HDC hdc2;
OpenClipboard(hWnd);
EmptyClipboard();
hdc = GetWindowDC(hWnd);
GetWindowRect(hWnd, &rect);
w = rect.right - rect.left;
h = rect.bottom - rect.top;
hbitmap = CreateCompatibleBitmap(hdc, w, h);
hdc2 = CreateCompatibleDC(hdc);
SelectObject(hdc2, hbitmap);
BitBlt(hdc2, 0, 0, w, h,
hdc, 0, 0,
SRCCOPY);
SetClipboardData(CF_BITMAP, hbitmap);
ReleaseDC(hWnd, hdc);
ReleaseDC(hWnd, hdc2);
CloseClipboard();
}
LRESULT WINAPI
User32DefWindowProc(HWND hWnd,
@ -549,33 +425,18 @@ User32DefWindowProc(HWND hWnd,
switch (Msg)
{
case WM_NCPAINT:
{
return DefWndNCPaint(hWnd, (HRGN)wParam, -1);
}
case WM_NCCALCSIZE:
{
return DefWndNCCalcSize(hWnd, (BOOL)wParam, (RECT*)lParam);
}
case WM_POPUPSYSTEMMENU:
{
/* This is an undocumented message used by the windows taskbar to
display the system menu of windows that belong to other processes. */
HMENU menu = GetSystemMenu(hWnd, FALSE);
ERR("WM_POPUPSYSTEMMENU\n");
if (menu)
TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON,
TrackPopupMenu(menu, TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_SYSTEM_MENU,
LOWORD(lParam), HIWORD(lParam), 0, hWnd, NULL);
return 0;
}
case WM_NCACTIVATE:
{
return DefWndNCActivate(hWnd, wParam, lParam);
}
case WM_NCHITTEST:
{
POINT Point;
@ -584,32 +445,9 @@ User32DefWindowProc(HWND hWnd,
return (DefWndNCHitTest(hWnd, Point));
}
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
iF10Key = iMenuSysKey = 0;
break;
case WM_NCLBUTTONDOWN:
{
return (DefWndNCLButtonDown(hWnd, wParam, lParam));
}
case WM_LBUTTONDBLCLK:
return (DefWndNCLButtonDblClk(hWnd, HTCLIENT, lParam));
case WM_NCLBUTTONDBLCLK:
{
return (DefWndNCLButtonDblClk(hWnd, wParam, lParam));
}
case WM_NCRBUTTONDOWN:
return NC_HandleNCRButtonDown( hWnd, wParam, lParam );
case WM_RBUTTONUP:
{
POINT Pt;
Pt.x = GET_X_LPARAM(lParam);
Pt.y = GET_Y_LPARAM(lParam);
ClientToScreen(hWnd, &Pt);
@ -632,6 +470,7 @@ User32DefWindowProc(HWND hWnd,
* "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_CONTEXTMENU:
@ -649,96 +488,11 @@ User32DefWindowProc(HWND hWnd,
}
else
{
POINT Pt;
LONG_PTR Style;
LONG HitCode;
Style = GetWindowLongPtrW(hWnd, GWL_STYLE);
Pt.x = GET_X_LPARAM(lParam);
Pt.y = GET_Y_LPARAM(lParam);
if (Style & WS_CHILD)
{
ScreenToClient(GetParent(hWnd), &Pt);
}
HitCode = DefWndNCHitTest(hWnd, Pt);
if (HitCode == HTCAPTION || HitCode == HTSYSMENU)
{
HMENU SystemMenu;
UINT Flags;
if((SystemMenu = GetSystemMenu(hWnd, FALSE)))
{
MenuInitSysMenuPopup(SystemMenu, GetWindowLongPtrW(hWnd, GWL_STYLE),
GetClassLongPtrW(hWnd, GCL_STYLE), HitCode);
if(HitCode == HTCAPTION)
Flags = TPM_LEFTBUTTON | TPM_RIGHTBUTTON;
else
Flags = TPM_LEFTBUTTON;
TrackPopupMenu(SystemMenu, Flags,
Pt.x, Pt.y, 0, hWnd, NULL);
}
}
}
goto GoSS;
}
break;
}
case WM_PRINT:
{
DefWndPrint(hWnd, (HDC)wParam, lParam);
return (0);
}
case WM_SYSCOLORCHANGE:
{
/* force to redraw non-client area */
DefWndNCPaint(hWnd, HRGN_WINDOW, -1);
/* Use InvalidateRect to redraw client area, enable
* erase to redraw all subcontrols otherwise send the
* WM_SYSCOLORCHANGE to child windows/controls is required
*/
InvalidateRect(hWnd,NULL,TRUE);
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 (pWnd->state2 & WNDS2_STARTPAINT && !IsRectEmpty(&pWnd->rcClient))
{
ERR("In Paint and Client area is not empty!\n");
return 0;
}
hDC = BeginPaint(hWnd, &Ps);
if (hDC)
{
HICON hIcon;
if (IsIconic(hWnd) && ((hIcon = (HICON)GetClassLongPtrW( hWnd, GCLP_HICON))))
{
RECT ClientRect;
INT x, y;
GetClientRect(hWnd, &ClientRect);
x = (ClientRect.right - ClientRect.left -
GetSystemMetrics(SM_CXICON)) / 2;
y = (ClientRect.bottom - ClientRect.top -
GetSystemMetrics(SM_CYICON)) / 2;
DrawIcon(hDC, x, y, hIcon);
}
EndPaint(hWnd, &Ps);
}
return (0);
}
case WM_CLOSE:
DestroyWindow(hWnd);
return (0);
@ -806,109 +560,6 @@ User32DefWindowProc(HWND hWnd,
case WM_SYSCOMMAND:
return (DefWndHandleSysCommand(hWnd, wParam, lParam));
case WM_KEYDOWN:
if(wParam == VK_F10) iF10Key = VK_F10;
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 ) && !iMenuSysKey )
iMenuSysKey = 1;
else
iMenuSysKey = 0;
}
iF10Key = 0;
if (wParam == VK_F4) /* Try to close the window */
{
HWND top = GetAncestor(hWnd, GA_ROOT);
if (!(GetClassLongPtrW(top, GCL_STYLE) & CS_NOCLOSE))
PostMessageW(top, WM_SYSCOMMAND, SC_CLOSE, 0);
}
else if (wParam == VK_SNAPSHOT) // Alt-VK_SNAPSHOT?
{
HWND hwnd = hWnd;
while (GetParent(hwnd) != NULL)
{
hwnd = GetParent(hwnd);
}
DefWndScreenshot(hwnd);
}
else if ( wParam == VK_ESCAPE || wParam == VK_TAB ) // Alt-Tab/ESC Alt-Shift-Tab/ESC
{
WPARAM wParamTmp;
HWND Active = GetActiveWindow(); // Noticed MDI problem.
if (!Active)
{
FIXME("WM_SYSKEYDOWN VK_ESCAPE no active\n");
break;
}
wParamTmp = GetKeyState(VK_SHIFT) & 0x8000 ? SC_PREVWINDOW : SC_NEXTWINDOW;
SendMessageW( Active, WM_SYSCOMMAND, wParamTmp, wParam );
}
}
else if( wParam == VK_F10 )
{
if (GetKeyState(VK_SHIFT) & 0x8000)
SendMessageW( hWnd, WM_CONTEXTMENU, (WPARAM)hWnd, MAKELPARAM(-1, -1) );
iF10Key = 1;
}
break;
}
case WM_KEYUP:
case WM_SYSKEYUP:
{
/* Press and release F10 or ALT */
if (((wParam == VK_MENU || wParam == VK_LMENU || wParam == VK_RMENU)
&& iMenuSysKey) || ((wParam == VK_F10) && iF10Key))
SendMessageW( GetAncestor( hWnd, GA_ROOT ), WM_SYSCOMMAND, SC_KEYMENU, 0L );
iMenuSysKey = iF10Key = 0;
break;
}
case WM_SYSCHAR:
{
iMenuSysKey = 0;
if (wParam == VK_RETURN && IsIconic(hWnd))
{
PostMessageW( hWnd, WM_SYSCOMMAND, SC_RESTORE, 0L );
break;
}
if ((HIWORD(lParam) & KF_ALTDOWN) && wParam)
{
if (wParam == VK_TAB || wParam == VK_ESCAPE) break;
if (wParam == VK_SPACE && (GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD))
SendMessageW( GetParent(hWnd), Msg, wParam, lParam );
else
SendMessageW( hWnd, WM_SYSCOMMAND, SC_KEYMENU, wParam );
}
else /* check for Ctrl-Esc */
if (wParam != VK_ESCAPE) MessageBeep(0);
break;
}
case WM_CANCELMODE:
{
iMenuSysKey = 0;
/* FIXME: Check for a desktop. */
//if (!(GetWindowLongPtrW( hWnd, GWL_STYLE ) & WS_CHILD)) EndMenu();
MENU_EndMenu( hWnd );
if (GetCapture() == hWnd)
{
ReleaseCapture();
}
break;
}
case WM_VKEYTOITEM:
case WM_CHARTOITEM:
return (-1);
@ -959,11 +610,6 @@ User32DefWindowProc(HWND hWnd,
break;
}
case WM_SETICON:
{
return DefWndSetIcon(pWnd, wParam, lParam);
}
case WM_GETICON:
{
return DefWndGetIcon(pWnd, wParam, lParam);
@ -1201,6 +847,30 @@ User32DefWindowProc(HWND hWnd,
/* Move to Win32k !*/
case WM_SHOWWINDOW:
if (!lParam) break; // Call when it is necessary.
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_NCLBUTTONDOWN:
case WM_LBUTTONDBLCLK:
case WM_NCLBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_KEYF1:
case WM_KEYUP:
case WM_SYSKEYUP:
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_SYSCHAR:
case WM_CANCELMODE:
case WM_PAINTICON:
case WM_PAINT:
case WM_PRINT:
case WM_SETICON:
case WM_SYSCOLORCHANGE:
case WM_NCUAHDRAWCAPTION:
case WM_NCUAHDRAWFRAME:
case WM_NCPAINT:
case WM_NCACTIVATE:
case WM_NCCALCSIZE:
case WM_SYNCPAINT:
case WM_SETREDRAW:
case WM_CLIENTSHUTDOWN:
@ -1210,6 +880,7 @@ User32DefWindowProc(HWND hWnd,
case WM_WINDOWPOSCHANGED:
case WM_APPCOMMAND:
case WM_SETCURSOR:
GoSS:
{
LRESULT lResult;
NtUserMessageCall( hWnd, Msg, wParam, lParam, (ULONG_PTR)&lResult, FNID_DEFWINDOWPROC, !bUnicode);
@ -1399,7 +1070,7 @@ RealDefWindowProcA(HWND hWnd,
if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
{
UserPaintCaption(hWnd);
UserPaintCaption(Wnd, DC_TEXT);
IntNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, hWnd, OBJID_WINDOW, CHILDID_SELF, 0);
}
Result = 1;
@ -1564,7 +1235,7 @@ RealDefWindowProcW(HWND hWnd,
DefSetText(hWnd, (PCWSTR)lParam, FALSE);
if ((GetWindowLongPtrW(hWnd, GWL_STYLE) & WS_CAPTION) == WS_CAPTION)
UserPaintCaption(hWnd);
UserPaintCaption(Wnd, DC_TEXT);
Result = 1;
break;
}

View file

@ -979,6 +979,14 @@ static BOOL UITOOLS95_DrawFrameMenu(HDC dc, LPRECT r, UINT uFlags)
TCHAR Symbol;
switch(uFlags & 0xff)
{
case DFCS_MENUARROWUP:
Symbol = '5';
break;
case DFCS_MENUARROWDOWN:
Symbol = '6';
break;
case DFCS_MENUARROW:
Symbol = '8';
break;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -43,35 +43,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32);
(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)
{
@ -112,582 +86,6 @@ UserGetWindowBorders(DWORD Style, DWORD ExStyle, SIZE *Size, BOOL WithClient)
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
*/
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
@ -902,334 +300,17 @@ DefWndNCHitTest(HWND hWnd, POINT Point)
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().
/*
RealUserDrawCaption: This function is passed through RegisterUserApiHook to uxtheme
to call it when the classic caption is needed to be drawn.
*/
LRESULT NC_HandleNCRButtonDown( HWND hwnd, WPARAM wParam, LPARAM lParam )
LRESULT WINAPI
RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags)
{
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;
ERR("Real DC flags %08x\n",uFlags);
return NtUserDrawCaption(hWnd, hDC, lpRc, uFlags);
}
/***********************************************************************
* 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)
{
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));
}
}
}
/***********************************************************************
* 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 ***********************************************************/