📄 window.c
字号:
/* $Id: window.c 23228 2006-07-22 17:03:00Z turner $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS user32.dll
* FILE: lib/user32/windows/window.c
* PURPOSE: Window management
* PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
* UPDATE HISTORY:
* 06-06-2001 CSH Created
*/
/* INCLUDES ******************************************************************/
#define DEBUG
#include <user32.h>
#include <wine/debug.h>
BOOL ControlsInitialized = FALSE;
LRESULT DefWndNCPaint(HWND hWnd, HRGN hRgn, BOOL Active);
void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id );
#define CW_USEDEFAULT16 0x00008000
/* FUNCTIONS *****************************************************************/
NTSTATUS STDCALL
User32CallSendAsyncProcForKernel(PVOID Arguments, ULONG ArgumentLength)
{
PSENDASYNCPROC_CALLBACK_ARGUMENTS CallbackArgs;
DPRINT("User32CallSendAsyncProcKernel()\n");
CallbackArgs = (PSENDASYNCPROC_CALLBACK_ARGUMENTS)Arguments;
if (ArgumentLength != sizeof(WINDOWPROC_CALLBACK_ARGUMENTS))
{
return(STATUS_INFO_LENGTH_MISMATCH);
}
CallbackArgs->Callback(CallbackArgs->Wnd, CallbackArgs->Msg,
CallbackArgs->Context, CallbackArgs->Result);
return(STATUS_SUCCESS);
}
/*
* @unimplemented
*/
BOOL STDCALL
AllowSetForegroundWindow(DWORD dwProcessId)
{
UNIMPLEMENTED;
return(FALSE);
}
/*
* @unimplemented
*/
HDWP STDCALL
BeginDeferWindowPos(int nNumWindows)
{
#if 0
UNIMPLEMENTED;
return (HDWP)0;
#else
return (HDWP)1;
#endif
}
/*
* @implemented
*/
BOOL STDCALL
BringWindowToTop(HWND hWnd)
{
return NtUserSetWindowPos( hWnd,
HWND_TOP,
0,
0,
0,
0,
SWP_NOSIZE | SWP_NOMOVE );
}
/*
* @unimplemented
*/
/*
WORD STDCALL
CascadeWindows(HWND hwndParent,
UINT wHow,
CONST RECT *lpRect,
UINT cKids,
const HWND *lpKids)
{
UNIMPLEMENTED;
return 0;
}
*/
VOID
STDCALL
SwitchToThisWindow ( HWND hwnd, BOOL fUnknown )
{
ShowWindow ( hwnd, SW_SHOW );
}
/*
* @implemented
*/
HWND STDCALL
ChildWindowFromPoint(HWND hWndParent,
POINT Point)
{
return (HWND) NtUserChildWindowFromPointEx(hWndParent, Point.x, Point.y, 0);
}
/*
* @implemented
*/
HWND STDCALL
ChildWindowFromPointEx(HWND hwndParent,
POINT pt,
UINT uFlags)
{
return (HWND) NtUserChildWindowFromPointEx(hwndParent, pt.x, pt.y, uFlags);
}
/*
* @implemented
*/
BOOL STDCALL
CloseWindow(HWND hWnd)
{
SendMessageA(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
return (BOOL)(hWnd);
}
HWND STDCALL
User32CreateWindowEx(DWORD dwExStyle,
LPCSTR lpClassName,
LPCSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam,
BOOL Unicode)
{
UNICODE_STRING WindowName;
UNICODE_STRING ClassName;
WNDCLASSEXA wceA;
WNDCLASSEXW wceW;
HWND Handle;
MDICREATESTRUCTA mdi;
#if 0
DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent);
#endif
if (IS_ATOM(lpClassName))
{
RtlInitUnicodeString(&ClassName, NULL);
ClassName.Buffer = (LPWSTR)lpClassName;
}
else
{
if(Unicode)
RtlInitUnicodeString(&ClassName, (PCWSTR)lpClassName);
else
{
if (!RtlCreateUnicodeStringFromAsciiz(&(ClassName), (PCSZ)lpClassName))
{
SetLastError(ERROR_OUTOFMEMORY);
return (HWND)0;
}
}
}
/* Register built-in controls if not already done */
if (! ControlsInitialized)
{
ControlsInitialized = ControlsInit(ClassName.Buffer);
}
if (dwExStyle & WS_EX_MDICHILD)
{
POINT mPos[2];
UINT id = 0;
/* lpParams of WM_[NC]CREATE is different for MDI children.
* MDICREATESTRUCT members have the originally passed values.
*
* Note: we rely on the fact that MDICREATESTRUCTA and MDICREATESTRUCTW
* have the same layout.
*/
mdi.szClass = (LPCSTR)lpClassName;
mdi.szTitle = (LPCSTR)lpWindowName;
mdi.hOwner = hInstance;
mdi.x = x;
mdi.y = y;
mdi.cx = nWidth;
mdi.cy = nHeight;
mdi.style = dwStyle;
mdi.lParam = (LPARAM)lpParam;
lpParam = (LPVOID)&mdi;
if (GetWindowLongW(hWndParent, GWL_STYLE) & MDIS_ALLCHILDSTYLES)
{
if (dwStyle & WS_POPUP)
{
DPRINT1("WS_POPUP with MDIS_ALLCHILDSTYLES is not allowed\n");
return(0);
}
dwStyle |= (WS_CHILD | WS_CLIPSIBLINGS);
}
else
{
dwStyle &= ~WS_POPUP;
dwStyle |= (WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CAPTION |
WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
}
HWND top_child = GetWindow(hWndParent, GW_CHILD);
if (top_child)
{
/* Restore current maximized child */
if((dwStyle & WS_VISIBLE) && IsZoomed(top_child))
{
DPRINT("Restoring current maximized child %p\n", top_child);
SendMessageW( top_child, WM_SETREDRAW, FALSE, 0 );
ShowWindow(top_child, SW_RESTORE);
SendMessageW( top_child, WM_SETREDRAW, TRUE, 0 );
}
}
MDI_CalcDefaultChildPos(hWndParent, -1, mPos, 0, &id);
if (!(dwStyle & WS_POPUP)) hMenu = (HMENU)id;
if (dwStyle & (WS_CHILD | WS_POPUP))
{
if (x == CW_USEDEFAULT || x == CW_USEDEFAULT16)
{
x = mPos[0].x;
y = mPos[0].y;
}
if (nWidth == CW_USEDEFAULT || nWidth == CW_USEDEFAULT16 || !nWidth)
nWidth = mPos[1].x;
if (nHeight == CW_USEDEFAULT || nHeight == CW_USEDEFAULT16 || !nHeight)
nHeight = mPos[1].y;
}
}
if (Unicode)
RtlInitUnicodeString(&WindowName, (PCWSTR)lpWindowName);
else
{
if (!RtlCreateUnicodeStringFromAsciiz(&WindowName, (PCSZ)lpWindowName))
{
if (!IS_ATOM(lpClassName))
{
RtlFreeUnicodeString(&ClassName);
}
SetLastError(ERROR_OUTOFMEMORY);
return (HWND)0;
}
}
if(!hMenu && (dwStyle & (WS_OVERLAPPEDWINDOW | WS_POPUP)))
{
if(Unicode)
{
wceW.cbSize = sizeof(WNDCLASSEXW);
if(GetClassInfoExW(hInstance, (LPCWSTR)lpClassName, &wceW) && wceW.lpszMenuName)
{DbgPrint("LoadingMenu 0x%p %d\n", wceW.lpszMenuName, IS_INTRESOURCE(wceW.lpszMenuName));
hMenu = LoadMenuW(hInstance, wceW.lpszMenuName);DbgPrint("Loaded menu: 0x%p\n", hMenu);
}
}
else
{
wceA.cbSize = sizeof(WNDCLASSEXA);
if(GetClassInfoExA(hInstance, lpClassName, &wceA) && wceA.lpszMenuName)
{
hMenu = LoadMenuA(hInstance, wceA.lpszMenuName);
}
}
}
Handle = NtUserCreateWindowEx(dwExStyle,
&ClassName,
&WindowName,
dwStyle,
x,
y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam,
SW_SHOW,
FALSE);
#if 0
DbgPrint("[window] NtUserCreateWindowEx() == %d\n", Handle);
#endif
if ((dwStyle & WS_VISIBLE) && (dwExStyle & WS_EX_MDICHILD))
{
SendMessageW(hWndParent, WM_MDIREFRESHMENU, 0, 0);
SetWindowPos(Handle, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW |
SWP_NOMOVE | SWP_NOSIZE);
}
if(!Unicode)
{
RtlFreeUnicodeString(&WindowName);
if (!IS_ATOM(lpClassName))
{
RtlFreeUnicodeString(&ClassName);
}
}
return Handle;
}
/*
* @implemented
*/
HWND STDCALL
CreateWindowExA(DWORD dwExStyle,
LPCSTR lpClassName,
LPCSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam)
{
return User32CreateWindowEx(dwExStyle,
lpClassName,
lpWindowName,
dwStyle,
x,
y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam,
FALSE);
}
/*
* @implemented
*/
HWND STDCALL
CreateWindowExW(DWORD dwExStyle,
LPCWSTR lpClassName,
LPCWSTR lpWindowName,
DWORD dwStyle,
int x,
int y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam)
{
return User32CreateWindowEx(dwExStyle,
(LPCSTR) lpClassName,
(LPCSTR) lpWindowName,
dwStyle,
x,
y,
nWidth,
nHeight,
hWndParent,
hMenu,
hInstance,
lpParam,
TRUE);
}
/*
* @unimplemented
*/
HDWP STDCALL
DeferWindowPos(HDWP hWinPosInfo,
HWND hWnd,
HWND hWndInsertAfter,
int x,
int y,
int cx,
int cy,
UINT uFlags)
{
#if 0
return NtUserDeferWindowPos(hWinPosInfo, hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
#else
SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags);
return hWinPosInfo;
#endif
}
/*
* @implemented
*/
BOOL STDCALL
DestroyWindow(HWND hWnd)
{
return NtUserDestroyWindow(hWnd);
}
/*
* @unimplemented
*/
BOOL STDCALL
EndDeferWindowPos(HDWP hWinPosInfo)
{
#if 0
UNIMPLEMENTED;
return FALSE;
#else
return TRUE;
#endif
}
/*
* @implemented
*/
HWND STDCALL
GetDesktopWindow(VOID)
{
return NtUserGetDesktopWindow();
}
/*
* @unimplemented
*/
HWND STDCALL
GetForegroundWindow(VOID)
{
return NtUserGetForegroundWindow();
}
static
BOOL
User32EnumWindows (
HDESK hDesktop,
HWND hWndparent,
WNDENUMPROC lpfn,
LPARAM lParam,
DWORD dwThreadId,
BOOL bChildren )
{
DWORD i, dwCount = 0;
HWND* pHwnd = NULL;
HANDLE hHeap;
if ( !lpfn )
{
SetLastError ( ERROR_INVALID_PARAMETER );
return FALSE;
}
/* FIXME instead of always making two calls, should we use some
sort of persistent buffer and only grow it ( requiring a 2nd
call ) when the buffer wasn't already big enough? */
/* first get how many window entries there are */
SetLastError(0);
dwCount = NtUserBuildHwndList (
hDesktop, hWndparent, bChildren, dwThreadId, lParam, NULL, 0 );
if ( !dwCount || GetLastError() )
return FALSE;
/* allocate buffer to receive HWND handles */
hHeap = GetProcessHeap();
pHwnd = HeapAlloc ( hHeap, 0, sizeof(HWND)*(dwCount+1) );
if ( !pHwnd )
{
SetLastError ( ERROR_NOT_ENOUGH_MEMORY );
return FALSE;
}
/* now call kernel again to fill the buffer this time */
dwCount = NtUserBuildHwndList (
hDesktop, hWndparent, bChildren, dwThreadId, lParam, pHwnd, dwCount );
if ( !dwCount || GetLastError() )
{
if ( pHwnd )
HeapFree ( hHeap, 0, pHwnd );
return FALSE;
}
/* call the user's callback function until we're done or
they tell us to quit */
for ( i = 0; i < dwCount; i++ )
{
/* FIXME I'm only getting NULLs from Thread Enumeration, and it's
* probably because I'm not doing it right in NtUserBuildHwndList.
* Once that's fixed, we shouldn't have to check for a NULL HWND
* here
*/
if ( !(ULONG)pHwnd[i] ) /* don't enumerate a NULL HWND */
continue;
if ( !(*lpfn)( pHwnd[i], lParam ) )
{
HeapFree ( hHeap, 0, pHwnd );
return FALSE;
}
}
if ( pHwnd )
HeapFree ( hHeap, 0, pHwnd );
return TRUE;
}
/*
* @implemented
*/
BOOL
STDCALL
EnumChildWindows(
HWND hWndParent,
WNDENUMPROC lpEnumFunc,
LPARAM lParam)
{
if ( !hWndParent )
hWndParent = GetDesktopWindow();
return User32EnumWindows ( NULL, hWndParent, lpEnumFunc, lParam, 0, FALSE );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -