📄 window.c
字号:
}
}
static WNDPROC
IntGetWindowProc(IN PWINDOW_OBJECT Window,
IN BOOL Ansi)
{
if (Window->IsSystem)
{
return (Ansi ? Window->WndProcExtra : Window->WndProc);
}
else
{
if (!Ansi == Window->Unicode)
{
return Window->WndProc;
}
else
{
if (Window->CallProc != NULL)
{
return GetCallProcHandle(Window->CallProc);
}
else
{
PCALLPROC NewCallProc, CallProc;
/* NOTE: use the interlocked functions, as this operation may be done even
when only the shared lock is held! */
NewCallProc = CreateCallProc(Window->ti->Desktop,
Window->WndProc,
Window->Unicode,
Window->ti->kpi);
if (NewCallProc == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
CallProc = InterlockedCompareExchangePointer(&Window->CallProc,
NewCallProc,
NULL);
if (CallProc != NULL)
{
DestroyCallProc(Window->ti->Desktop,
NewCallProc);
}
return GetCallProcHandle((CallProc == NULL ? NewCallProc : CallProc));
}
}
}
}
BOOL FASTCALL
IntGetWindowInfo(PWINDOW_OBJECT Window, PWINDOWINFO pwi)
{
pwi->cbSize = sizeof(WINDOWINFO);
pwi->rcWindow = Window->WindowRect;
pwi->rcClient = Window->ClientRect;
pwi->dwStyle = Window->Style;
pwi->dwExStyle = Window->ExStyle;
pwi->dwWindowStatus = (UserGetForegroundWindow() == Window->hSelf); /* WS_ACTIVECAPTION */
IntGetWindowBorderMeasures(Window, &pwi->cxWindowBorders, &pwi->cyWindowBorders);
pwi->atomWindowType = (Window->Class ? Window->Class->Atom : 0);
pwi->wCreatorVersion = 0x400; /* FIXME - return a real version number */
return TRUE;
}
static BOOL FASTCALL
IntSetMenu(
PWINDOW_OBJECT Window,
HMENU Menu,
BOOL *Changed)
{
PMENU_OBJECT OldMenu, NewMenu = NULL;
if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
{
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
*Changed = (Window->IDMenu != (UINT) Menu);
if (! *Changed)
{
return TRUE;
}
if (Window->IDMenu)
{
OldMenu = IntGetMenuObject((HMENU) Window->IDMenu);
ASSERT(NULL == OldMenu || OldMenu->MenuInfo.Wnd == Window->hSelf);
}
else
{
OldMenu = NULL;
}
if (NULL != Menu)
{
NewMenu = IntGetMenuObject(Menu);
if (NULL == NewMenu)
{
if (NULL != OldMenu)
{
IntReleaseMenuObject(OldMenu);
}
SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
return FALSE;
}
if (NULL != NewMenu->MenuInfo.Wnd)
{
/* Can't use the same menu for two windows */
if (NULL != OldMenu)
{
IntReleaseMenuObject(OldMenu);
}
SetLastWin32Error(ERROR_INVALID_MENU_HANDLE);
return FALSE;
}
}
Window->IDMenu = (UINT) Menu;
if (NULL != NewMenu)
{
NewMenu->MenuInfo.Wnd = Window->hSelf;
IntReleaseMenuObject(NewMenu);
}
if (NULL != OldMenu)
{
OldMenu->MenuInfo.Wnd = NULL;
IntReleaseMenuObject(OldMenu);
}
return TRUE;
}
/* INTERNAL ******************************************************************/
VOID FASTCALL
co_DestroyThreadWindows(struct _ETHREAD *Thread)
{
PW32THREAD WThread;
PLIST_ENTRY Current;
PWINDOW_OBJECT Wnd;
USER_REFERENCE_ENTRY Ref;
WThread = (PW32THREAD)Thread->Tcb.Win32Thread;
while (!IsListEmpty(&WThread->WindowListHead))
{
Current = WThread->WindowListHead.Flink;
Wnd = CONTAINING_RECORD(Current, WINDOW_OBJECT, ThreadListEntry);
DPRINT("thread cleanup: while destroy wnds, wnd=0x%x\n",Wnd);
/* window removes itself from the list */
/*
fixme: it is critical that the window removes itself! if now, we will loop
here forever...
*/
//ASSERT(co_UserDestroyWindow(Wnd));
UserRefObjectCo(Wnd, &Ref);//faxme: temp hack??
if (!co_UserDestroyWindow(Wnd))
{
DPRINT1("Unable to destroy window 0x%x at thread cleanup... This is _VERY_ bad!\n", Wnd);
}
UserDerefObjectCo(Wnd);//faxme: temp hack??
}
}
/*!
* Internal function.
* Returns client window rectangle relative to the upper-left corner of client area.
*
* \note Does not check the validity of the parameters
*/
VOID FASTCALL
IntGetClientRect(PWINDOW_OBJECT Window, PRECT Rect)
{
ASSERT( Window );
ASSERT( Rect );
Rect->left = Rect->top = 0;
Rect->right = Window->ClientRect.right - Window->ClientRect.left;
Rect->bottom = Window->ClientRect.bottom - Window->ClientRect.top;
}
#if 0
HWND FASTCALL
IntGetFocusWindow(VOID)
{
PUSER_MESSAGE_QUEUE Queue;
PDESKTOP_OBJECT pdo = IntGetActiveDesktop();
if( !pdo )
return NULL;
Queue = (PUSER_MESSAGE_QUEUE)pdo->ActiveMessageQueue;
if (Queue == NULL)
return(NULL);
else
return(Queue->FocusWindow);
}
#endif
PMENU_OBJECT FASTCALL
IntGetSystemMenu(PWINDOW_OBJECT Window, BOOL bRevert, BOOL RetMenu)
{
PMENU_OBJECT Menu, NewMenu = NULL, SysMenu = NULL, ret = NULL;
PW32THREAD W32Thread;
HMENU hNewMenu, hSysMenu;
ROSMENUITEMINFO ItemInfo;
if(bRevert)
{
W32Thread = PsGetCurrentThreadWin32Thread();
if(!W32Thread->Desktop)
return NULL;
if(Window->SystemMenu)
{
Menu = UserGetMenuObject(Window->SystemMenu);
if(Menu)
{
IntDestroyMenuObject(Menu, FALSE, TRUE);
Window->SystemMenu = (HMENU)0;
}
}
if(W32Thread->Desktop->WindowStation->SystemMenuTemplate)
{
/* clone system menu */
Menu = UserGetMenuObject(W32Thread->Desktop->WindowStation->SystemMenuTemplate);
if(!Menu)
return NULL;
NewMenu = IntCloneMenu(Menu);
if(NewMenu)
{
Window->SystemMenu = NewMenu->MenuInfo.Self;
NewMenu->MenuInfo.Flags |= MF_SYSMENU;
NewMenu->MenuInfo.Wnd = Window->hSelf;
ret = NewMenu;
//IntReleaseMenuObject(NewMenu);
}
}
else
{
hSysMenu = UserCreateMenu(FALSE);
if (NULL == hSysMenu)
{
return NULL;
}
SysMenu = IntGetMenuObject(hSysMenu);
if (NULL == SysMenu)
{
UserDestroyMenu(hSysMenu);
return NULL;
}
SysMenu->MenuInfo.Flags |= MF_SYSMENU;
SysMenu->MenuInfo.Wnd = Window->hSelf;
hNewMenu = co_IntLoadSysMenuTemplate();
if(!hNewMenu)
{
IntReleaseMenuObject(SysMenu);
UserDestroyMenu(hSysMenu);
return NULL;
}
Menu = IntGetMenuObject(hNewMenu);
if(!Menu)
{
IntReleaseMenuObject(SysMenu);
UserDestroyMenu(hSysMenu);
return NULL;
}
NewMenu = IntCloneMenu(Menu);
if(NewMenu)
{
NewMenu->MenuInfo.Flags |= MF_SYSMENU | MF_POPUP;
IntReleaseMenuObject(NewMenu);
UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE);
ItemInfo.cbSize = sizeof(MENUITEMINFOW);
ItemInfo.fMask = MIIM_FTYPE | MIIM_STRING | MIIM_STATE | MIIM_SUBMENU;
ItemInfo.fType = MF_POPUP;
ItemInfo.fState = MFS_ENABLED;
ItemInfo.dwTypeData = NULL;
ItemInfo.cch = 0;
ItemInfo.hSubMenu = NewMenu->MenuInfo.Self;
IntInsertMenuItem(SysMenu, (UINT) -1, TRUE, &ItemInfo);
Window->SystemMenu = SysMenu->MenuInfo.Self;
ret = SysMenu;
}
IntDestroyMenuObject(Menu, FALSE, TRUE);
}
if(RetMenu)
return ret;
else
return NULL;
}
else
{
if(Window->SystemMenu)
return IntGetMenuObject((HMENU)Window->SystemMenu);
else
return NULL;
}
}
BOOL FASTCALL
IntIsChildWindow(PWINDOW_OBJECT Parent, PWINDOW_OBJECT BaseWindow)
{
PWINDOW_OBJECT Window;
Window = BaseWindow;
while (Window)
{
if (Window == Parent)
{
return(TRUE);
}
if(!(Window->Style & WS_CHILD))
{
break;
}
Window = Window->Parent;
}
return(FALSE);
}
BOOL FASTCALL
IntIsWindowVisible(PWINDOW_OBJECT BaseWindow)
{
PWINDOW_OBJECT Window;
Window = BaseWindow;
while(Window)
{
if(!(Window->Style & WS_CHILD))
{
break;
}
if(!(Window->Style & WS_VISIBLE))
{
return FALSE;
}
Window = Window->Parent;
}
if(Window && Window->Style & WS_VISIBLE)
{
return TRUE;
}
return FALSE;
}
/* link the window into siblings and parent. children are kept in place. */
VOID FASTCALL
IntLinkWindow(
PWINDOW_OBJECT Wnd,
PWINDOW_OBJECT WndParent,
PWINDOW_OBJECT WndPrevSibling /* set to NULL if top sibling */
)
{
PWINDOW_OBJECT Parent;
Wnd->Parent = WndParent;
if ((Wnd->PrevSibling = WndPrevSibling))
{
/* link after WndPrevSibling */
if ((Wnd->NextSibling = WndPrevSibling->NextSibling))
Wnd->NextSibling->PrevSibling = Wnd;
else if ((Parent = Wnd->Parent))
{
if(Parent->LastChild == WndPrevSibling)
Parent->LastChild = Wnd;
}
Wnd->PrevSibling->NextSibling = Wnd;
}
else
{
/* link at top */
Parent = Wnd->Parent;
if ((Wnd->NextSibling = WndParent->FirstChild))
Wnd->NextSibling->PrevSibling = Wnd;
else if (Parent)
{
Parent->LastChild = Wnd;
Parent->FirstChild = Wnd;
return;
}
if(Parent)
{
Parent->FirstChild = Wnd;
}
}
}
HWND FASTCALL
IntSetOwner(HWND hWnd, HWND hWndNewOwner)
{
PWINDOW_OBJECT Wnd, WndOldOwner, WndNewOwner;
HWND ret;
Wnd = IntGetWindowObject(hWnd);
if(!Wnd)
return NULL;
WndOldOwner = IntGetWindowObject(Wnd->hOwner);
if (WndOldOwner)
{
ret = WndOldOwner->hSelf;
UserDerefObject(WndOldOwner);
}
else
{
ret = 0;
}
if((WndNewOwner = UserGetWindowObject(hWndNewOwner)))
{
Wnd->hOwner = hWndNewOwner;
}
else
Wnd->hOwner = NULL;
UserDerefObject(Wnd);
return ret;
}
PWINDOW_OBJECT FASTCALL
co_IntSetParent(PWINDOW_OBJECT Wnd, PWINDOW_OBJECT WndNewParent)
{
PWINDOW_OBJECT WndOldParent, Sibling, InsertAfter;
// HWND hWnd, hWndNewParent;
BOOL WasVisible;
ASSERT(Wnd);
ASSERT(WndNewParent);
ASSERT_REFS_CO(Wnd);
ASSERT_REFS_CO(WndNewParent);
// hWnd = Wnd->hSelf;
// hWndNewParent = WndNewParent->hSelf;
/*
* Windows hides the window first, then shows it again
* including the WM_SHOWWINDOW messages and all
*/
WasVisible = co_WinPosShowWindow(Wnd, SW_HIDE);
// /* Validate that window and parent still exist */
// if (!IntIsWindow(hWnd) || !IntIsWindow(hWndNewParent))
// return NULL;
/* Window must belong to current process */
if (Wnd->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
return NULL;
WndOldParent = Wnd->Parent;
if (WndOldParent) UserRefObject(WndOldParent); /* caller must deref */
if (WndNewParent != WndOldParent)
{
IntUnlinkWindow(Wnd);
InsertAfter = NULL;
if (0 == (Wnd->ExStyle & WS_EX_TOPMOST))
{
/* Not a TOPMOST window, put after TOPMOSTs of new parent */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -