📄 mdi.c
字号:
for (x = i = 0, c = 1; c <= columns && *pWnd; c++)
{
if (c == columns)
{
rows = total - i;
ysize = rect.bottom / rows;
}
y = 0;
for (r = 1; r <= rows && *pWnd; r++, i++)
{
SetWindowPos(*pWnd, 0, x, y, xsize, ysize,
SWP_DRAWFRAME | SWP_NOACTIVATE | SWP_NOZORDER);
y += ysize;
pWnd++;
}
x += xsize;
}
}
HeapFree( GetProcessHeap(), 0, win_array );
if (has_icons) ArrangeIconicWindows( client );
}
/* ----------------------- Frame window ---------------------------- */
/**********************************************************************
* MDI_AugmentFrameMenu
*/
static BOOL MDI_AugmentFrameMenu( HWND frame, HWND hChild )
{
HMENU menu = GetMenu( frame );
HMENU hSysPopup = 0;
HBITMAP hSysMenuBitmap = 0;
INT nItems;
UINT iId;
HICON hIcon;
TRACE("frame %p,child %p\n",frame,hChild);
if( !menu ) return 0;
/* if the system buttons already exist do not add them again */
nItems = GetMenuItemCount(menu) - 1;
iId = GetMenuItemID(menu,nItems) ;
if (iId == SC_RESTORE || iId == SC_CLOSE)
return 0;
/* create a copy of sysmenu popup and insert it into frame menu bar */
if (!(hSysPopup = GetSystemMenu(hChild, FALSE)))
return 0;
AppendMenuW(menu, MF_HELP | MF_BITMAP,
SC_MINIMIZE, (LPCWSTR)HBMMENU_MBAR_MINIMIZE ) ;
AppendMenuW(menu, MF_HELP | MF_BITMAP,
SC_RESTORE, (LPCWSTR)HBMMENU_MBAR_RESTORE );
AppendMenuW(menu, MF_HELP | MF_BITMAP,
SC_CLOSE, is_close_enabled(hChild, hSysPopup) ?
(LPCWSTR)HBMMENU_MBAR_CLOSE : (LPCWSTR)HBMMENU_MBAR_CLOSE_D );
/* The system menu is replaced by the child icon */
hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICONSM);
if (!hIcon)
hIcon = (HICON)GetClassLongPtrW(hChild, GCLP_HICON);
if (!hIcon)
hIcon = LoadIconW(NULL, IDI_APPLICATION);
if (hIcon)
{
HDC hMemDC;
HBITMAP hBitmap, hOldBitmap;
HBRUSH hBrush;
HDC hdc = GetDC(hChild);
if (hdc)
{
int cx, cy;
cx = GetSystemMetrics(SM_CXSMICON);
cy = GetSystemMetrics(SM_CYSMICON);
hMemDC = CreateCompatibleDC(hdc);
hBitmap = CreateCompatibleBitmap(hdc, cx, cy);
hOldBitmap = SelectObject(hMemDC, hBitmap);
SetMapMode(hMemDC, MM_TEXT);
hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
DrawIconEx(hMemDC, 0, 0, hIcon, cx, cy, 0, hBrush, DI_NORMAL);
SelectObject (hMemDC, hOldBitmap);
DeleteObject(hBrush);
DeleteDC(hMemDC);
ReleaseDC(hChild, hdc);
hSysMenuBitmap = hBitmap;
}
}
if( !InsertMenuA(menu,0,MF_BYPOSITION | MF_BITMAP | MF_POPUP,
(UINT_PTR)hSysPopup, (LPSTR)hSysMenuBitmap))
{
TRACE("not inserted\n");
DestroyMenu(hSysPopup);
return 0;
}
EnableMenuItem(hSysPopup, SC_SIZE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hSysPopup, SC_MOVE, MF_BYCOMMAND | MF_GRAYED);
EnableMenuItem(hSysPopup, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED);
SetMenuDefaultItem(hSysPopup, SC_CLOSE, FALSE);
/* redraw menu */
DrawMenuBar(frame);
return 1;
}
/**********************************************************************
* MDI_RestoreFrameMenu
*/
static BOOL MDI_RestoreFrameMenu( HWND frame, HWND hChild, HBITMAP hBmpClose )
{
MENUITEMINFOW menuInfo;
HMENU menu = GetMenu( frame );
INT nItems = GetMenuItemCount(menu) - 1;
UINT iId = GetMenuItemID(menu,nItems) ;
TRACE("frame %p,child %p,nIt=%d,iId=%d\n",frame,hChild,nItems,iId);
if( !menu ) return 0;
/* if there is no system buttons then nothing to do */
if(!(iId == SC_RESTORE || iId == SC_CLOSE) )
return 0;
/*
* Remove the system menu, If that menu is the icon of the window
* as it is in win95, we have to delete the bitmap.
*/
memset(&menuInfo, 0, sizeof(menuInfo));
menuInfo.cbSize = sizeof(menuInfo);
menuInfo.fMask = MIIM_DATA | MIIM_TYPE | MIIM_BITMAP;
GetMenuItemInfoW(menu,
0,
TRUE,
&menuInfo);
RemoveMenu(menu,0,MF_BYPOSITION);
if ( (menuInfo.fType & MFT_BITMAP) &&
(menuInfo.dwTypeData != 0) &&
(menuInfo.dwTypeData != (LPWSTR)hBmpClose) )
{
DeleteObject(menuInfo.dwTypeData);
}
if ( menuInfo.hbmpItem != 0 )
DeleteObject(menuInfo.hbmpItem);
/* close */
DeleteMenu(menu, SC_CLOSE, MF_BYCOMMAND);
/* restore */
DeleteMenu(menu, SC_RESTORE, MF_BYCOMMAND);
/* minimize */
DeleteMenu(menu, SC_MINIMIZE, MF_BYCOMMAND);
DrawMenuBar(frame);
return 1;
}
/**********************************************************************
* MDI_UpdateFrameText
*
* used when child window is maximized/restored
*
* Note: lpTitle can be NULL
*/
static void MDI_UpdateFrameText( HWND frame, HWND hClient, LPCWSTR lpTitle )
{
WCHAR lpBuffer[MDI_MAXTITLELENGTH+1];
MDICLIENTINFO *ci = get_client_info( hClient );
TRACE("frameText %s\n", debugstr_w(lpTitle));
if (!ci) return;
if (!lpTitle && !ci->frameTitle) /* first time around, get title from the frame window */
{
GetWindowTextW( frame, lpBuffer, sizeof(lpBuffer)/sizeof(WCHAR) );
lpTitle = lpBuffer;
}
/* store new "default" title if lpTitle is not NULL */
if (lpTitle)
{
HeapFree( GetProcessHeap(), 0, ci->frameTitle );
if ((ci->frameTitle = HeapAlloc( GetProcessHeap(), 0, (strlenW(lpTitle)+1)*sizeof(WCHAR))))
strcpyW( ci->frameTitle, lpTitle );
}
if (ci->frameTitle)
{
if (IsZoomed(ci->hwndActiveChild) && IsWindowVisible(ci->hwndActiveChild))
{
/* combine frame title and child title if possible */
static const WCHAR lpBracket[] = {' ','-',' ','[',0};
static const WCHAR lpBracket2[] = {']',0};
int i_frame_text_length = strlenW(ci->frameTitle);
lstrcpynW( lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH);
if( i_frame_text_length + 6 < MDI_MAXTITLELENGTH )
{
strcatW( lpBuffer, lpBracket );
if (GetWindowTextW( ci->hwndActiveChild, lpBuffer + i_frame_text_length + 4,
MDI_MAXTITLELENGTH - i_frame_text_length - 5 ))
strcatW( lpBuffer, lpBracket2 );
else
lpBuffer[i_frame_text_length] = 0; /* remove bracket */
}
}
else
{
lstrcpynW(lpBuffer, ci->frameTitle, MDI_MAXTITLELENGTH+1 );
}
}
else
lpBuffer[0] = '\0';
DefWindowProcW( frame, WM_SETTEXT, 0, (LPARAM)lpBuffer );
}
/* ----------------------------- Interface ---------------------------- */
/**********************************************************************
* MDIClientWndProc_common
*/
static LRESULT MDIClientWndProc_common( HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam, BOOL unicode )
{
MDICLIENTINFO *ci = NULL;
TRACE("%p %04x (%s) %08x %08lx\n", hwnd, message, SPY_GetMsgName(message, hwnd), wParam, lParam);
if (WM_NCCREATE != message && NULL == (ci = get_client_info(hwnd)))
{
return 0;
}
#ifndef __REACTOS__
if (!(ci = get_client_info( hwnd ))) return 0;
#endif
switch (message)
{
#ifdef __REACTOS__
case WM_NCCREATE:
if (!(ci = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ci))))
return FALSE;
SetWindowLongPtrW( hwnd, 0, (LONG_PTR)ci );
ci->hBmpClose = 0;
return TRUE;
#endif
case WM_CREATE:
{
/* Since we are using only cs->lpCreateParams, we can safely
* cast to LPCREATESTRUCTA here */
LPCREATESTRUCTA cs = (LPCREATESTRUCTA)lParam;
#ifndef __REACTOS__
WND *wndPtr = WIN_GetPtr( hwnd );
wndPtr->flags |= WIN_ISMDICLIENT;
#endif
/* Translation layer doesn't know what's in the cs->lpCreateParams
* so we have to keep track of what environment we're in. */
#ifndef __REACTOS__
if( wndPtr->flags & WIN_ISWIN32 )
#endif
{
LPCLIENTCREATESTRUCT ccs = (LPCLIENTCREATESTRUCT)cs->lpCreateParams;
ci->hWindowMenu = ccs->hWindowMenu;
ci->idFirstChild = ccs->idFirstChild;
}
#ifndef __REACTOS__
else
{
LPCLIENTCREATESTRUCT16 ccs = MapSL((SEGPTR)cs->lpCreateParams);
ci->hWindowMenu = HMENU_32(ccs->hWindowMenu);
ci->idFirstChild = ccs->idFirstChild;
}
WIN_ReleasePtr( wndPtr );
#endif
ci->child = NULL;
ci->nActiveChildren = 0;
ci->nTotalCreated = 0;
ci->frameTitle = NULL;
ci->mdiFlags = 0;
ci->hFrameMenu = GetMenu(cs->hwndParent);
if (!ci->hBmpClose) ci->hBmpClose = CreateMDIMenuBitmap();
TRACE("Client created: hwnd %p, Window menu %p, idFirst = %04x\n",
hwnd, ci->hWindowMenu, ci->idFirstChild );
return 0;
}
case WM_DESTROY:
{
if( IsZoomed(ci->hwndActiveChild) )
MDI_RestoreFrameMenu(GetParent(hwnd), ci->hwndActiveChild, ci->hBmpClose);
ci->nActiveChildren = 0;
MDI_RefreshMenu(ci);
HeapFree( GetProcessHeap(), 0, ci->child );
HeapFree( GetProcessHeap(), 0, ci->frameTitle );
#ifdef __REACTOS__
HeapFree( GetProcessHeap(), 0, ci );
SetWindowLongPtrW( hwnd, 0, 0 );
#endif
return 0;
}
case WM_MDIACTIVATE:
{
MDI_SwitchActiveChild( ci, (HWND)wParam, TRUE );
return 0;
}
case WM_MDICASCADE:
return MDICascade(hwnd, ci);
case WM_MDICREATE:
if (lParam)
{
HWND child;
if (unicode)
{
MDICREATESTRUCTW *csW = (MDICREATESTRUCTW *)lParam;
child = CreateWindowExW(WS_EX_MDICHILD, csW->szClass,
csW->szTitle, csW->style,
csW->x, csW->y, csW->cx, csW->cy,
hwnd, 0, csW->hOwner,
(LPVOID)csW->lParam);
}
else
{
MDICREATESTRUCTA *csA = (MDICREATESTRUCTA *)lParam;
child = CreateWindowExA(WS_EX_MDICHILD, csA->szClass,
csA->szTitle, csA->style,
csA->x, csA->y, csA->cx, csA->cy,
hwnd, 0, csA->hOwner,
(LPVOID)csA->lParam);
}
if (IsZoomed(ci->hwndActiveChild))
{
MDI_AugmentFrameMenu(GetParent(hwnd), child);
MDI_UpdateFrameText(GetParent(hwnd), hwnd, NULL);
}
return (LRESULT)child;
}
return 0;
case WM_MDIDESTROY:
#ifndef __REACTOS__
return MDIDestroyChild( hwnd, ci, WIN_GetFullHandle( (HWND)wParam ), TRUE );
#else
return MDIDestroyChild( hwnd, ci, (HWND)wParam, TRUE );
#endif
case WM_MDIGETACTIVE:
if (lParam) *(BOOL *)lParam = IsZoomed(ci->hwndActiveChild);
return (LRESULT)ci->hwndActiveChild;
case WM_MDIICONARRANGE:
ci->mdiFlags |= MDIF_NEEDUPDATE;
ArrangeIconicWindows( hwnd );
ci->sbRecalc = SB_BOTH+1;
SendMessageW( hwnd, WM_MDICALCCHILDSCROLL, 0, 0 );
return 0;
case WM_MDIMAXIMIZE:
ShowWindow( (HWND)wParam, SW_MAXIMIZE );
return 0;
case WM_MDINEXT: /* lParam != 0 means previous window */
{
#ifndef __REACTOS__
HWND next = MDI_GetWindow( ci, WIN_GetFullHandle( (HWND)wParam ), !lParam, 0 );
#else
HWND next = MDI_GetWindow( ci, (HWND)wParam, !lParam, 0 );
#endif
MDI_SwitchActiveChild( ci, next, TRUE );
break;
}
case WM_MDIRESTORE:
SendMessageW( (HWND)wParam, WM_SYSCOMMAND, SC_RESTORE, 0);
return 0;
case WM_MDISETMENU:
return MDISetMenu( hwnd, (HMENU)wParam, (HMENU)lParam );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -