📄 window.c
字号:
Sibling = WndNewParent->FirstChild;
while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
{
InsertAfter = Sibling;
Sibling = Sibling->NextSibling;
}
}
if (NULL == InsertAfter)
{
IntLinkWindow(Wnd, WndNewParent, InsertAfter /*prev sibling*/);
}
else
{
// UserRefObject(InsertAfter);
IntLinkWindow(Wnd, WndNewParent, InsertAfter /*prev sibling*/);
// UserDerefObject(InsertAfter);
}
}
/*
* SetParent additionally needs to make hwnd the top window
* in the z-order and send the expected WM_WINDOWPOSCHANGING and
* WM_WINDOWPOSCHANGED notification messages.
*/
co_WinPosSetWindowPos(Wnd, (0 == (Wnd->ExStyle & WS_EX_TOPMOST) ? HWND_TOP : HWND_TOPMOST),
0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE
| (WasVisible ? SWP_SHOWWINDOW : 0));
/*
* FIXME: a WM_MOVE is also generated (in the DefWindowProc handler
* for WM_WINDOWPOSCHANGED) in Windows, should probably remove SWP_NOMOVE
*/
/*
* Validate that the old parent still exist, since it migth have been
* destroyed during the last callbacks to user-mode
*/
// if(WndOldParent)
// {
// if(!IntIsWindow(WndOldParent->hSelf))
// {
// UserDerefObject(WndOldParent);
// return NULL;
// }
/* don't dereference the window object here, it must be done by the caller
of IntSetParent() */
// return WndOldParent;
// }
return WndOldParent;//NULL;
}
BOOL FASTCALL
IntSetSystemMenu(PWINDOW_OBJECT Window, PMENU_OBJECT Menu)
{
PMENU_OBJECT OldMenu;
if(Window->SystemMenu)
{
OldMenu = IntGetMenuObject(Window->SystemMenu);
if(OldMenu)
{
OldMenu->MenuInfo.Flags &= ~ MF_SYSMENU;
IntReleaseMenuObject(OldMenu);
}
}
if(Menu)
{
/* FIXME check window style, propably return FALSE ? */
Window->SystemMenu = Menu->MenuInfo.Self;
Menu->MenuInfo.Flags |= MF_SYSMENU;
}
else
Window->SystemMenu = (HMENU)0;
return TRUE;
}
/* unlink the window from siblings and parent. children are kept in place. */
VOID FASTCALL
IntUnlinkWindow(PWINDOW_OBJECT Wnd)
{
PWINDOW_OBJECT WndParent = Wnd->Parent;
if (Wnd->NextSibling)
Wnd->NextSibling->PrevSibling = Wnd->PrevSibling;
else if (WndParent && WndParent->LastChild == Wnd)
WndParent->LastChild = Wnd->PrevSibling;
if (Wnd->PrevSibling)
Wnd->PrevSibling->NextSibling = Wnd->NextSibling;
else if (WndParent && WndParent->FirstChild == Wnd)
WndParent->FirstChild = Wnd->NextSibling;
Wnd->PrevSibling = Wnd->NextSibling = Wnd->Parent = NULL;
}
BOOL FASTCALL
IntAnyPopup(VOID)
{
PWINDOW_OBJECT Window, Child;
if(!(Window = UserGetWindowObject(IntGetDesktopWindow())))
{
return FALSE;
}
for(Child = Window->FirstChild; Child; Child = Child->NextSibling)
{
if(Child->hOwner && Child->Style & WS_VISIBLE)
{
/*
* The desktop has a popup window if one of them has
* an owner window and is visible
*/
return TRUE;
}
}
return FALSE;
}
BOOL FASTCALL
IntIsWindowInDestroy(PWINDOW_OBJECT Window)
{
return ((Window->Status & WINDOWSTATUS_DESTROYING) == WINDOWSTATUS_DESTROYING);
}
/* FUNCTIONS *****************************************************************/
/*
* @unimplemented
*/
DWORD STDCALL
NtUserAlterWindowStyle(DWORD Unknown0,
DWORD Unknown1,
DWORD Unknown2)
{
UNIMPLEMENTED
return(0);
}
/*
* As best as I can figure, this function is used by EnumWindows,
* EnumChildWindows, EnumDesktopWindows, & EnumThreadWindows.
*
* It's supposed to build a list of HWNDs to return to the caller.
* We can figure out what kind of list by what parameters are
* passed to us.
*/
/*
* @implemented
*/
ULONG
STDCALL
NtUserBuildHwndList(
HDESK hDesktop,
HWND hwndParent,
BOOLEAN bChildren,
ULONG dwThreadId,
ULONG lParam,
HWND* pWnd,
ULONG nBufSize)
{
NTSTATUS Status;
ULONG dwCount = 0;
if (hwndParent || !dwThreadId)
{
PDESKTOP_OBJECT Desktop;
PWINDOW_OBJECT Parent, Window;
if(!hwndParent)
{
if(hDesktop == NULL && !(Desktop = IntGetActiveDesktop()))
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
if(hDesktop)
{
Status = IntValidateDesktopHandle(hDesktop,
UserMode,
0,
&Desktop);
if(!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
}
hwndParent = Desktop->DesktopWindow;
}
else
{
hDesktop = 0;
}
if((Parent = UserGetWindowObject(hwndParent)) &&
(Window = Parent->FirstChild))
{
BOOL bGoDown = TRUE;
Status = STATUS_SUCCESS;
while(TRUE)
{
if (bGoDown)
{
if(dwCount++ < nBufSize && pWnd)
{
_SEH_TRY
{
ProbeForWrite(pWnd, sizeof(HWND), 1);
*pWnd = Window->hSelf;
pWnd++;
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
break;
}
}
if (Window->FirstChild && bChildren)
{
Window = Window->FirstChild;
continue;
}
bGoDown = FALSE;
}
if (Window->NextSibling)
{
Window = Window->NextSibling;
bGoDown = TRUE;
continue;
}
Window = Window->Parent;
if (Window == Parent)
{
break;
}
}
}
if(hDesktop)
{
ObDereferenceObject(Desktop);
}
}
else
{
PETHREAD Thread;
PW32THREAD W32Thread;
PLIST_ENTRY Current;
PWINDOW_OBJECT Window;
Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread);
if(!NT_SUCCESS(Status))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
}
if(!(W32Thread = (PW32THREAD)Thread->Tcb.Win32Thread))
{
ObDereferenceObject(Thread);
DPRINT("Thread is not a GUI Thread!\n");
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return 0;
}
Current = W32Thread->WindowListHead.Flink;
while(Current != &(W32Thread->WindowListHead))
{
Window = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry);
ASSERT(Window);
if(dwCount < nBufSize && pWnd)
{
Status = MmCopyToCaller(pWnd++, &Window->hSelf, sizeof(HWND));
if(!NT_SUCCESS(Status))
{
SetLastNtError(Status);
break;
}
}
dwCount++;
Current = Current->Flink;
}
ObDereferenceObject(Thread);
}
return dwCount;
}
/*
* @implemented
*/
HWND STDCALL
NtUserChildWindowFromPointEx(HWND hwndParent,
LONG x,
LONG y,
UINT uiFlags)
{
PWINDOW_OBJECT Parent;
POINTL Pt;
HWND Ret;
HWND *List, *phWnd;
if(!(Parent = UserGetWindowObject(hwndParent)))
{
return NULL;
}
Pt.x = x;
Pt.y = y;
if(Parent->hSelf != IntGetDesktopWindow())
{
Pt.x += Parent->ClientRect.left;
Pt.y += Parent->ClientRect.top;
}
if(!IntPtInWindow(Parent, Pt.x, Pt.y))
{
return NULL;
}
Ret = Parent->hSelf;
if((List = IntWinListChildren(Parent)))
{
for(phWnd = List; *phWnd; phWnd++)
{
PWINDOW_OBJECT Child;
if((Child = UserGetWindowObject(*phWnd)))
{
if(!(Child->Style & WS_VISIBLE) && (uiFlags & CWP_SKIPINVISIBLE))
{
continue;
}
if((Child->Style & WS_DISABLED) && (uiFlags & CWP_SKIPDISABLED))
{
continue;
}
if((Child->ExStyle & WS_EX_TRANSPARENT) && (uiFlags & CWP_SKIPTRANSPARENT))
{
continue;
}
if(IntPtInWindow(Child, Pt.x, Pt.y))
{
Ret = Child->hSelf;
break;
}
}
}
ExFreePool(List);
}
return Ret;
}
/*
* calculates the default position of a window
*/
BOOL FASTCALL
IntCalcDefPosSize(PWINDOW_OBJECT Parent, PWINDOW_OBJECT Window, RECT *rc, BOOL IncPos)
{
SIZE Sz;
POINT Pos = {0, 0};
if(Parent != NULL)
{
IntGdiIntersectRect(rc, rc, &Parent->ClientRect);
if(IncPos)
{
Pos.x = Parent->TiledCounter * (UserGetSystemMetrics(SM_CXSIZE) + UserGetSystemMetrics(SM_CXFRAME));
Pos.y = Parent->TiledCounter * (UserGetSystemMetrics(SM_CYSIZE) + UserGetSystemMetrics(SM_CYFRAME));
if(Pos.x > ((rc->right - rc->left) / 4) ||
Pos.y > ((rc->bottom - rc->top) / 4))
{
/* reset counter and position */
Pos.x = 0;
Pos.y = 0;
Parent->TiledCounter = 0;
}
Parent->TiledCounter++;
}
Pos.x += rc->left;
Pos.y += rc->top;
}
else
{
Pos.x = rc->left;
Pos.y = rc->top;
}
Sz.cx = EngMulDiv(rc->right - rc->left, 3, 4);
Sz.cy = EngMulDiv(rc->bottom - rc->top, 3, 4);
rc->left = Pos.x;
rc->top = Pos.y;
rc->right = rc->left + Sz.cx;
rc->bottom = rc->top + Sz.cy;
return TRUE;
}
/*
* @implemented
*/
HWND STDCALL
co_IntCreateWindowEx(DWORD dwExStyle,
PUNICODE_STRING ClassName,
PUNICODE_STRING WindowName,
DWORD dwStyle,
LONG x,
LONG y,
LONG nWidth,
LONG nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam,
DWORD dwShowMode,
BOOL bUnicodeWindow)
{
PWINSTATION_OBJECT WinSta;
PWINDOWCLASS *ClassLink, Class = NULL;
RTL_ATOM ClassAtom;
PWINDOW_OBJECT Window = NULL;
PWINDOW_OBJECT ParentWindow = NULL, OwnerWindow;
HWND ParentWindowHandle;
HWND OwnerWindowHandle;
PMENU_OBJECT SystemMenu;
HWND hWnd;
POINT Pos;
SIZE Size;
PW32THREADINFO ti = NULL;
#if 0
POINT MaxSize, MaxPos, MinTrack, MaxTrack;
#else
POINT MaxPos;
#endif
CREATESTRUCTW Cs;
CBT_CREATEWNDW CbtCreate;
LRESULT Result;
BOOL MenuChanged;
DECLARE_RETURN(HWND);
BOOL HasOwner;
USER_REFERENCE_ENTRY ParentRef, Ref;
ParentWindowHandle = PsGetCurrentThreadWin32Thread()->Desktop->DesktopWindow;
OwnerWindowHandle = NULL;
if (hWndParent == HWND_MESSAGE)
{
/*
* native ole32.OleInitialize uses HWND_MESSAGE to create the
* message window (style: WS_POPUP|WS_DISABLED)
*/
DPRINT1("FIXME - Parent is HWND_MESSAGE\n");
}
else if (hWndParent)
{
if ((dwStyle & (WS_CHILD | WS_POPUP)) != WS_CHILD)
{ //temp hack
PWINDOW_OBJECT Par = UserGetWindowObject(hWndParent), Root;
if (Par && (Root = UserGetAncestor(Par, GA_ROOT)))
OwnerWindowHandle = Root->hSelf;
}
else
ParentWindowHandle = hWndParent;
}
else if ((dwStyle & (WS_CHILD | WS_POPUP)) == WS_CHILD)
{
SetLastWin32Error(ERROR_TLW_WITH_WSCHILD);
RETURN( (HWND)0); /* WS_CHILD needs a parent, but WS_POPUP doesn't */
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -