📄 winpos.c
字号:
}
}
}
}
return TRUE;
}
/* x and y are always screen relative */
BOOLEAN FASTCALL
co_WinPosSetWindowPos(
PWINDOW_OBJECT Window,
HWND WndInsertAfter,
INT x,
INT y,
INT cx,
INT cy,
UINT flags
)
{
WINDOWPOS WinPos;
RECT NewWindowRect;
RECT NewClientRect;
PROSRGNDATA VisRgn;
HRGN VisBefore = NULL;
HRGN VisAfter = NULL;
HRGN DirtyRgn = NULL;
HRGN ExposedRgn = NULL;
HRGN CopyRgn = NULL;
ULONG WvrFlags = 0;
RECT OldWindowRect, OldClientRect;
int RgnType;
HDC Dc;
RECT CopyRect;
RECT TempRect;
ASSERT_REFS_CO(Window);
/* FIXME: Get current active window from active queue. */
/*
* Only allow CSRSS to mess with the desktop window
*/
if (Window->hSelf == IntGetDesktopWindow() &&
Window->OwnerThread->ThreadsProcess != PsGetCurrentProcess())
{
return FALSE;
}
WinPos.hwnd = Window->hSelf;
WinPos.hwndInsertAfter = WndInsertAfter;
WinPos.x = x;
WinPos.y = y;
WinPos.cx = cx;
WinPos.cy = cy;
WinPos.flags = flags;
co_WinPosDoWinPosChanging(Window, &WinPos, &NewWindowRect, &NewClientRect);
/* Fix up the flags. */
if (!WinPosFixupFlags(&WinPos, Window))
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
/* Does the window still exist? */
if (!IntIsWindow(WinPos.hwnd))
{
SetLastWin32Error(ERROR_INVALID_WINDOW_HANDLE);
return FALSE;
}
if ((WinPos.flags & (SWP_NOZORDER | SWP_HIDEWINDOW | SWP_SHOWWINDOW)) !=
SWP_NOZORDER &&
// UserGetAncestor(WinPos.hwnd, GA_PARENT) == IntGetDesktopWindow())
//faxme: is WinPos.hwnd constant?? (WinPos.hwnd = Window->hSelf above)
UserGetAncestor(Window, GA_PARENT)->hSelf == IntGetDesktopWindow())
{
WinPos.hwndInsertAfter = WinPosDoOwnedPopups(WinPos.hwnd, WinPos.hwndInsertAfter);
}
if (!(WinPos.flags & SWP_NOREDRAW))
{
/* Compute the visible region before the window position is changed */
if (!(WinPos.flags & (SWP_NOREDRAW | SWP_SHOWWINDOW)) &&
(WinPos.flags & (SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_HIDEWINDOW | SWP_FRAMECHANGED)) !=
(SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER))
{
VisBefore = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
VisRgn = NULL;
if (VisBefore != NULL && (VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(VisBefore)) &&
UnsafeIntGetRgnBox(VisRgn, &TempRect) == NULLREGION)
{
RGNDATA_UnlockRgn(VisRgn);
NtGdiDeleteObject(VisBefore);
VisBefore = NULL;
}
else if(VisRgn)
{
RGNDATA_UnlockRgn(VisRgn);
NtGdiOffsetRgn(VisBefore, -Window->WindowRect.left, -Window->WindowRect.top);
}
}
}
WvrFlags = co_WinPosDoNCCALCSize(Window, &WinPos, &NewWindowRect, &NewClientRect);
//DPRINT1("co_WinPosDoNCCALCSize");
/* Relink windows. (also take into account shell window in hwndShellWindow) */
if (!(WinPos.flags & SWP_NOZORDER) && WinPos.hwnd != UserGetShellWindow())
{
PWINDOW_OBJECT ParentWindow;
PWINDOW_OBJECT Sibling;
PWINDOW_OBJECT InsertAfterWindow;
if ((ParentWindow = Window->Parent))
{
if (HWND_TOPMOST == WinPos.hwndInsertAfter)
{
InsertAfterWindow = NULL;
}
else if (HWND_TOP == WinPos.hwndInsertAfter
|| HWND_NOTOPMOST == WinPos.hwndInsertAfter)
{
InsertAfterWindow = NULL;
Sibling = ParentWindow->FirstChild;
while (NULL != Sibling && 0 != (Sibling->ExStyle & WS_EX_TOPMOST))
{
InsertAfterWindow = Sibling;
Sibling = Sibling->NextSibling;
}
if (NULL != InsertAfterWindow)
{
UserRefObject(InsertAfterWindow);
}
}
else if (WinPos.hwndInsertAfter == HWND_BOTTOM)
{
if(ParentWindow->LastChild)
{
UserRefObject(ParentWindow->LastChild);
InsertAfterWindow = ParentWindow->LastChild;
}
else
InsertAfterWindow = NULL;
}
else
InsertAfterWindow = IntGetWindowObject(WinPos.hwndInsertAfter);
/* Do nothing if hwndInsertAfter is HWND_BOTTOM and Window is already
the last window */
if (InsertAfterWindow != Window)
{
IntUnlinkWindow(Window);
IntLinkWindow(Window, ParentWindow, InsertAfterWindow);
}
if (InsertAfterWindow != NULL)
UserDerefObject(InsertAfterWindow);
if ((HWND_TOPMOST == WinPos.hwndInsertAfter)
|| (0 != (Window->ExStyle & WS_EX_TOPMOST)
&& NULL != Window->PrevSibling
&& 0 != (Window->PrevSibling->ExStyle & WS_EX_TOPMOST))
|| (NULL != Window->NextSibling
&& 0 != (Window->NextSibling->ExStyle & WS_EX_TOPMOST)))
{
Window->ExStyle |= WS_EX_TOPMOST;
}
else
{
Window->ExStyle &= ~ WS_EX_TOPMOST;
}
}
}
OldWindowRect = Window->WindowRect;
OldClientRect = Window->ClientRect;
if (OldClientRect.bottom - OldClientRect.top ==
NewClientRect.bottom - NewClientRect.top)
{
WvrFlags &= ~WVR_VREDRAW;
}
if (OldClientRect.right - OldClientRect.left ==
NewClientRect.right - NewClientRect.left)
{
WvrFlags &= ~WVR_HREDRAW;
}
/* FIXME: Actually do something with WVR_VALIDRECTS */
if (NewClientRect.left != OldClientRect.left ||
NewClientRect.top != OldClientRect.top)
{
WinPosInternalMoveWindow(Window,
NewClientRect.left - OldClientRect.left,
NewClientRect.top - OldClientRect.top);
}
Window->WindowRect = NewWindowRect;
Window->ClientRect = NewClientRect;
if (!(WinPos.flags & SWP_SHOWWINDOW) && (WinPos.flags & SWP_HIDEWINDOW))
{
/* Clear the update region */
co_UserRedrawWindow(Window, NULL, 0, RDW_VALIDATE | RDW_NOFRAME |
RDW_NOERASE | RDW_NOINTERNALPAINT | RDW_ALLCHILDREN);
if ((Window->Style & WS_VISIBLE) &&
Window->Parent == UserGetDesktopWindow())
{
co_IntShellHookNotify(HSHELL_WINDOWDESTROYED, (LPARAM)Window->hSelf);
}
Window->Style &= ~WS_VISIBLE;
}
else if (WinPos.flags & SWP_SHOWWINDOW)
{
if (!(Window->Style & WS_VISIBLE) &&
Window->Parent == UserGetDesktopWindow())
{
co_IntShellHookNotify(HSHELL_WINDOWCREATED, (LPARAM)Window->hSelf);
}
Window->Style |= WS_VISIBLE;
}
if (Window->UpdateRegion != NULL && Window->UpdateRegion != (HRGN)1)
{
NtGdiOffsetRgn(Window->UpdateRegion,
NewWindowRect.left - OldWindowRect.left,
NewWindowRect.top - OldWindowRect.top);
}
DceResetActiveDCEs(Window);
if (!(WinPos.flags & SWP_NOREDRAW))
{
/* Determine the new visible region */
VisAfter = VIS_ComputeVisibleRegion(Window, FALSE, FALSE, TRUE);
VisRgn = NULL;
if (VisAfter != NULL && (VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(VisAfter)) &&
UnsafeIntGetRgnBox(VisRgn, &TempRect) == NULLREGION)
{
RGNDATA_UnlockRgn(VisRgn);
NtGdiDeleteObject(VisAfter);
VisAfter = NULL;
}
else if(VisRgn)
{
RGNDATA_UnlockRgn(VisRgn);
NtGdiOffsetRgn(VisAfter, -Window->WindowRect.left, -Window->WindowRect.top);
}
/*
* Determine which pixels can be copied from the old window position
* to the new. Those pixels must be visible in both the old and new
* position. Also, check the class style to see if the windows of this
* class need to be completely repainted on (horizontal/vertical) size
* change.
*/
if (VisBefore != NULL && VisAfter != NULL && !(WinPos.flags & SWP_NOCOPYBITS) &&
((WinPos.flags & SWP_NOSIZE) || !(WvrFlags & WVR_REDRAW)) &&
!(Window->ExStyle & WS_EX_TRANSPARENT))
{
CopyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
RgnType = NtGdiCombineRgn(CopyRgn, VisAfter, VisBefore, RGN_AND);
/*
* If this is (also) a window resize, the whole nonclient area
* needs to be repainted. So we limit the copy to the client area,
* 'cause there is no use in copying it (would possibly cause
* "flashing" too). However, if the copy region is already empty,
* we don't have to crop (can't take anything away from an empty
* region...)
*/
if (!(WinPos.flags & SWP_NOSIZE) && RgnType != ERROR &&
RgnType != NULLREGION)
{
RECT ORect = OldClientRect;
RECT NRect = NewClientRect;
IntGdiOffsetRect(&ORect, - OldWindowRect.left, - OldWindowRect.top);
IntGdiOffsetRect(&NRect, - NewWindowRect.left, - NewWindowRect.top);
IntGdiIntersectRect(&CopyRect, &ORect, &NRect);
REGION_CropRgn(CopyRgn, CopyRgn, &CopyRect, NULL);
}
/* No use in copying bits which are in the update region. */
if (Window->UpdateRegion != NULL)
{
NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
NtGdiCombineRgn(CopyRgn, CopyRgn, Window->UpdateRegion, RGN_DIFF);
NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
}
/*
* Now, get the bounding box of the copy region. If it's empty
* there's nothing to copy. Also, it's no use copying bits onto
* themselves.
*/
if ((VisRgn = (PROSRGNDATA)RGNDATA_LockRgn(CopyRgn)) &&
UnsafeIntGetRgnBox(VisRgn, &CopyRect) == NULLREGION)
{
/* Nothing to copy, clean up */
RGNDATA_UnlockRgn(VisRgn);
NtGdiDeleteObject(CopyRgn);
CopyRgn = NULL;
}
else if (OldWindowRect.left != NewWindowRect.left ||
OldWindowRect.top != NewWindowRect.top)
{
if(VisRgn)
{
RGNDATA_UnlockRgn(VisRgn);
}
/*
* Small trick here: there is no function to bitblt a region. So
* we set the region as the clipping region, take the bounding box
* of the region and bitblt that. Since nothing outside the clipping
* region is copied, this has the effect of bitblt'ing the region.
*
* Since NtUserGetDCEx takes ownership of the clip region, we need
* to create a copy of CopyRgn and pass that. We need CopyRgn later
*/
NtGdiOffsetRgn(CopyRgn, NewWindowRect.left, NewWindowRect.top);
Dc = UserGetDCEx(Window, CopyRgn, DCX_WINDOW | DCX_CACHE |
DCX_INTERSECTRGN | DCX_CLIPSIBLINGS |
DCX_KEEPCLIPRGN);
NtGdiBitBlt(Dc,
CopyRect.left, CopyRect.top, CopyRect.right - CopyRect.left,
CopyRect.bottom - CopyRect.top, Dc,
CopyRect.left + (OldWindowRect.left - NewWindowRect.left),
CopyRect.top + (OldWindowRect.top - NewWindowRect.top), SRCCOPY, 0, 0);
UserReleaseDC(Window, Dc, FALSE);
IntValidateParent(Window, CopyRgn, FALSE);
NtGdiOffsetRgn(CopyRgn, -NewWindowRect.left, -NewWindowRect.top);
}
else if(VisRgn)
{
RGNDATA_UnlockRgn(VisRgn);
}
}
else
{
CopyRgn = NULL;
}
/* We need to redraw what wasn't visible before */
if (VisAfter != NULL)
{
DirtyRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
if (CopyRgn != NULL)
{
RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, CopyRgn, RGN_DIFF);
}
else
{
RgnType = NtGdiCombineRgn(DirtyRgn, VisAfter, 0, RGN_COPY);
}
if (RgnType != ERROR && RgnType != NULLREGION)
{
/* old code
NtGdiOffsetRgn(DirtyRgn, Window->WindowRect.left, Window->WindowRect.top);
IntInvalidateWindows(Window, DirtyRgn,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
NtGdiDeleteObject(DirtyRgn);
*/
PWINDOW_OBJECT Parent = Window->Parent;
NtGdiOffsetRgn(DirtyRgn,
Window->WindowRect.left,
Window->WindowRect.top);
if ((Window->Style & WS_CHILD) &&
(Parent) &&
!(Parent->Style & WS_CLIPCHILDREN))
{
IntInvalidateWindows(Parent, DirtyRgn,
RDW_ERASE | RDW_INVALIDATE);
co_IntPaintWindows(Parent, RDW_ERASENOW, FALSE);
}
else
{
IntInvalidateWindows(Window, DirtyRgn,
RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
NtGdiDeleteObject(DirtyRgn);
}
if (CopyRgn != NULL)
{
NtGdiDeleteObject(CopyRgn);
}
/* Expose what was covered before but not covered anymore */
if (VisBefore != NULL)
{
ExposedRgn = NtGdiCreateRectRgn(0, 0, 0, 0);
NtGdiCombineRgn(ExposedRgn, VisBefore, NULL, RGN_COPY);
NtGdiOffsetRgn(ExposedRgn, OldWindowRect.left - NewWindowRect.left,
OldWindowRect.top - NewWindowRect.top);
if (VisAfter != NULL)
RgnType = NtGdiCombineRgn(ExposedRgn, ExposedRgn, VisAfter, RGN_DIFF);
else
RgnType = SIMPLEREGION;
if (RgnType != ERROR && RgnType != NULLREGION)
{
co_VIS_WindowLayoutChanged(Window, ExposedRgn);
}
NtGdiDeleteObject(ExposedRgn);
NtGdiDeleteObject(VisBefore);
}
if (VisAfter != NULL)
{
NtGdiDeleteObject(VisAfter);
}
if (!(WinPos.flags & SWP_NOACTIVATE))
{
if ((Window->Style & (WS_CHILD | WS_POPUP)) == WS_CHILD)
{
co_IntSendMessage(WinPos.hwnd, WM_CHILDACTIVATE, 0, 0);
}
else
{
co_IntSetForegroundWindow(Window);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -