Commit a1ccb921 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

Make message flow for MDI creation/activation/destruction more like in

Windows. Add a bunch of MDI message tests.
parent 8657ad87
...@@ -480,23 +480,33 @@ static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax ...@@ -480,23 +480,33 @@ static void MDI_ChildGetMinMaxInfo( HWND client, HWND hwnd, MINMAXINFO* lpMinMax
* Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is * Note: SetWindowPos sends WM_CHILDACTIVATE to the child window that is
* being activated * being activated
*/ */
static void MDI_SwitchActiveChild( HWND clientHwnd, HWND childHwnd, static void MDI_SwitchActiveChild( MDICLIENTINFO *ci, HWND hwndTo )
BOOL bNextWindow )
{ {
HWND hwndTo = 0; HWND hwndPrev;
HWND hwndPrev = 0;
MDICLIENTINFO *ci = get_client_info( clientHwnd );
hwndTo = MDI_GetWindow(ci, childHwnd, bNextWindow, 0);
hwndPrev = ci->hwndActiveChild; hwndPrev = ci->hwndActiveChild;
TRACE("from %p, to %p\n",childHwnd,hwndTo); TRACE("from %p, to %p\n", hwndPrev, hwndTo);
if ( !hwndTo ) if ( hwndTo != hwndPrev )
MDI_ChildActivate( clientHwnd, 0 ); {
else if ( hwndTo != hwndPrev ) BOOL was_zoomed = IsZoomed(hwndPrev);
SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE ); if (was_zoomed)
{
/* restore old MDI child */
SendMessageW( hwndPrev, WM_SETREDRAW, FALSE, 0 );
ShowWindow( hwndPrev, SW_RESTORE );
SendMessageW( hwndPrev, WM_SETREDRAW, TRUE, 0 );
/* activate new MDI child */
SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
/* maximize new MDI child */
ShowWindow( hwndTo, SW_MAXIMIZE );
}
/* activate new MDI child */
SetWindowPos( hwndTo, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
}
} }
...@@ -512,8 +522,8 @@ static LRESULT MDIDestroyChild( HWND parent, MDICLIENTINFO *ci, ...@@ -512,8 +522,8 @@ static LRESULT MDIDestroyChild( HWND parent, MDICLIENTINFO *ci,
if( child == ci->hwndActiveChild ) if( child == ci->hwndActiveChild )
{ {
MDI_SwitchActiveChild(parent, child, TRUE); HWND next = MDI_GetWindow(ci, child, TRUE, 0);
ShowWindow(child, SW_HIDE); MDI_SwitchActiveChild(ci, next);
} }
for (i = 0; i < ci->nActiveChildren; i++) for (i = 0; i < ci->nActiveChildren; i++)
...@@ -546,7 +556,7 @@ static LRESULT MDIDestroyChild( HWND parent, MDICLIENTINFO *ci, ...@@ -546,7 +556,7 @@ static LRESULT MDIDestroyChild( HWND parent, MDICLIENTINFO *ci,
/********************************************************************** /**********************************************************************
* MDI_ChildActivate * MDI_ChildActivate
* *
* Note: hWndChild is NULL when last child is being destroyed * Called in response to WM_CHILDACTIVATE
*/ */
static LONG MDI_ChildActivate( HWND client, HWND child ) static LONG MDI_ChildActivate( HWND client, HWND child )
{ {
...@@ -554,18 +564,16 @@ static LONG MDI_ChildActivate( HWND client, HWND child ) ...@@ -554,18 +564,16 @@ static LONG MDI_ChildActivate( HWND client, HWND child )
HWND prevActiveWnd, frame; HWND prevActiveWnd, frame;
BOOL isActiveFrameWnd; BOOL isActiveFrameWnd;
if (child && (!IsWindowEnabled( child ))) return 0;
clientInfo = get_client_info( client ); clientInfo = get_client_info( client );
if (clientInfo->hwndActiveChild == child) return 0;
TRACE("%p\n", child); TRACE("%p\n", child);
frame = GetParent(client); frame = GetParent(client);
isActiveFrameWnd = (GetActiveWindow() == frame); isActiveFrameWnd = (GetActiveWindow() == frame);
prevActiveWnd = clientInfo->hwndActiveChild; prevActiveWnd = clientInfo->hwndActiveChild;
if (prevActiveWnd == child) return 0;
/* deactivate prev. active child */ /* deactivate prev. active child */
if(prevActiveWnd) if(prevActiveWnd)
{ {
...@@ -575,39 +583,13 @@ static LONG MDI_ChildActivate( HWND client, HWND child ) ...@@ -575,39 +583,13 @@ static LONG MDI_ChildActivate( HWND client, HWND child )
clientInfo->hwndActiveChild = child; clientInfo->hwndActiveChild = child;
/* set appearance */
if (IsZoomed(prevActiveWnd) && prevActiveWnd != child)
{
if( child )
{
INT cmd = SW_SHOWNORMAL;
HMENU hSysMenu = GetSystemMenu(child, FALSE);
UINT state = 0;
if (hSysMenu)
state = GetMenuState(hSysMenu, SC_MAXIMIZE, MF_BYCOMMAND);
if (state != 0xFFFFFFFF && !(state & (MF_DISABLED | MF_GRAYED)))
cmd = SW_SHOWMAXIMIZED;
ShowWindow( child, cmd );
}
else
MDI_RestoreFrameMenu(frame, child);
}
MDI_UpdateFrameText(frame, client, NULL);
/* check if we have any children left */
if( !child )
{
if( isActiveFrameWnd )
SetFocus( client );
return 0;
}
MDI_RefreshMenu(clientInfo); MDI_RefreshMenu(clientInfo);
if( isActiveFrameWnd ) if( isActiveFrameWnd )
{
SendMessageW( child, WM_NCACTIVATE, TRUE, 0L); SendMessageW( child, WM_NCACTIVATE, TRUE, 0L);
SetFocus(child);
}
SendMessageW( child, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child ); SendMessageW( child, WM_MDIACTIVATE, (WPARAM)prevActiveWnd, (LPARAM)child );
return TRUE; return TRUE;
...@@ -1060,8 +1042,7 @@ static LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, ...@@ -1060,8 +1042,7 @@ static LRESULT MDIClientWndProc_common( HWND hwnd, UINT message,
case WM_MDIACTIVATE: case WM_MDIACTIVATE:
{ {
if( ci->hwndActiveChild != (HWND)wParam ) MDI_SwitchActiveChild( ci, (HWND)wParam );
SetWindowPos((HWND)wParam, 0,0,0,0,0, SWP_NOSIZE | SWP_NOMOVE);
return 0; return 0;
} }
...@@ -1111,8 +1092,11 @@ static LRESULT MDIClientWndProc_common( HWND hwnd, UINT message, ...@@ -1111,8 +1092,11 @@ static LRESULT MDIClientWndProc_common( HWND hwnd, UINT message,
return 0; return 0;
case WM_MDINEXT: /* lParam != 0 means previous window */ case WM_MDINEXT: /* lParam != 0 means previous window */
MDI_SwitchActiveChild( hwnd, WIN_GetFullHandle( (HWND)wParam ), !lParam ); {
HWND next = MDI_GetWindow( ci, WIN_GetFullHandle( (HWND)wParam ), !lParam, 0 );
MDI_SwitchActiveChild( ci, next );
break; break;
}
case WM_MDIRESTORE: case WM_MDIRESTORE:
SendMessageW( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0); SendMessageW( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
...@@ -1399,6 +1383,7 @@ LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message, ...@@ -1399,6 +1383,7 @@ LRESULT WINAPI DefMDIChildProcA( HWND hwnd, UINT message,
case WM_SIZE: case WM_SIZE:
case WM_NEXTMENU: case WM_NEXTMENU:
case WM_SYSCHAR: case WM_SYSCHAR:
case WM_DESTROY:
return DefMDIChildProcW( hwnd, message, wParam, lParam ); return DefMDIChildProcW( hwnd, message, wParam, lParam );
} }
return DefWindowProcA(hwnd, message, wParam, lParam); return DefWindowProcA(hwnd, message, wParam, lParam);
...@@ -1472,29 +1457,20 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message, ...@@ -1472,29 +1457,20 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
break; break;
case WM_SIZE: case WM_SIZE:
if (wParam == SIZE_MAXIMIZED && !IsWindowVisible(hwnd)) if( hwnd == ci->hwndActiveChild )
wParam = SIZE_RESTORED;
if( hwnd == ci->hwndActiveChild && wParam != SIZE_MAXIMIZED )
{
MDI_RestoreFrameMenu( GetParent(client), hwnd );
MDI_UpdateFrameText( GetParent(client), client, NULL );
}
if( wParam == SIZE_MAXIMIZED )
{ {
TRACE("maximizing child %p\n", hwnd ); if( wParam == SIZE_MAXIMIZED )
{
TRACE("maximizing child %p\n", hwnd );
MDI_AugmentFrameMenu( GetParent(client), hwnd ); MDI_AugmentFrameMenu( GetParent(client), hwnd );
MDI_UpdateFrameText( GetParent(client), client, NULL ); }
else
MDI_RestoreFrameMenu( GetParent(client), hwnd );
} }
if( wParam == SIZE_MINIMIZED ) MDI_UpdateFrameText( GetParent(client), client, NULL );
{ MDI_RefreshMenu(ci);
HWND switchTo = MDI_GetWindow(ci, hwnd, TRUE, WS_MINIMIZE);
if (switchTo) SendMessageW( switchTo, WM_CHILDACTIVATE, 0, 0);
}
MDI_PostUpdate(client, ci, SB_BOTH+1); MDI_PostUpdate(client, ci, SB_BOTH+1);
break; break;
...@@ -1524,6 +1500,11 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message, ...@@ -1524,6 +1500,11 @@ LRESULT WINAPI DefMDIChildProcW( HWND hwnd, UINT message,
return 0; return 0;
} }
break; break;
case WM_DESTROY:
/* Remove itself from the Window menu */
MDI_RefreshMenu(ci);
break;
} }
return DefWindowProcW(hwnd, message, wParam, lParam); return DefWindowProcW(hwnd, message, wParam, lParam);
} }
......
...@@ -1024,6 +1024,18 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, ...@@ -1024,6 +1024,18 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
} }
top_child = GetWindow(cs->hwndParent, GW_CHILD); top_child = GetWindow(cs->hwndParent, GW_CHILD);
if (top_child)
{
/* Restore current maximized child */
if((cs->style & WS_VISIBLE) && IsZoomed(top_child))
{
TRACE("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 );
}
}
} }
/* Find the parent window */ /* Find the parent window */
...@@ -1167,24 +1179,22 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom, ...@@ -1167,24 +1179,22 @@ static HWND WIN_CreateWindowEx( CREATESTRUCTA *cs, ATOM classAtom,
send_parent_notify( hwnd, WM_CREATE ); send_parent_notify( hwnd, WM_CREATE );
if (!IsWindow( hwnd )) return 0; if (!IsWindow( hwnd )) return 0;
if (cs->dwExStyle & WS_EX_MDICHILD) if (cs->style & WS_VISIBLE)
{ {
if (top_child) if (cs->style & WS_MAXIMIZE)
sw = SW_SHOWMAXIMIZED;
else if (cs->style & WS_MINIMIZE)
sw = SW_SHOWMINIMIZED;
ShowWindow( hwnd, sw );
if (cs->dwExStyle & WS_EX_MDICHILD)
{ {
/* Restore current maximized child */ SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
if((cs->style & WS_VISIBLE) && IsZoomed(top_child)) /* ShowWindow won't activate child windows */
{ SetWindowPos( hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE );
TRACE("Restoring current maximized child %p\n", top_child);
ShowWindow(top_child, SW_SHOWNOACTIVATE);
}
} }
SendMessageW(cs->hwndParent, WM_MDIREFRESHMENU, 0, 0);
} }
if (cs->style & WS_VISIBLE)
ShowWindow( hwnd, sw );
/* Call WH_SHELL hook */ /* Call WH_SHELL hook */
if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER )) if (!(GetWindowLongW( hwnd, GWL_STYLE ) & WS_CHILD) && !GetWindow( hwnd, GW_OWNER ))
...@@ -1432,9 +1442,6 @@ BOOL WINAPI DestroyWindow( HWND hwnd ) ...@@ -1432,9 +1442,6 @@ BOOL WINAPI DestroyWindow( HWND hwnd )
TRACE("(%p)\n", hwnd); TRACE("(%p)\n", hwnd);
if (GetWindowLongW(hwnd, GWL_EXSTYLE) & WS_EX_MDICHILD)
SendMessageW(GetAncestor(hwnd, GA_PARENT), WM_MDIREFRESHMENU, 0, 0);
/* Call hooks */ /* Call hooks */
if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE; if (HOOK_CallHooks( WH_CBT, HCBT_DESTROYWND, (WPARAM)hwnd, 0, TRUE )) return FALSE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment