📄 winmdi.cpp
字号:
// update the Window menu to reflect new child window
CMDIFrameWnd* pFrame = GetMDIFrame();
::SendMessage(pFrame->m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
// Note: Update the m_bPseudoInactive flag. This is used to handle the
// last MDI child getting hidden. Windows provides no way to deactivate
// an MDI child window.
BOOL bVisibleNow = (GetStyle() & WS_VISIBLE) != 0;
if (bVisibleNow == bVisibleThen)
return;
if (!bVisibleNow)
{
// get current active window according to Windows MDI
HWND hWnd = (HWND)::SendMessage(pFrameWnd->m_hWndMDIClient,
WM_MDIGETACTIVE, 0, 0);
if (hWnd != m_hWnd)
{
// not active any more -- window must have been deactivated
ASSERT(!m_bPseudoInactive);
return;
}
// check next window
ASSERT(hWnd != NULL);
pFrameWnd->MDINext();
// see if it has been deactivated now...
hWnd = (HWND)::SendMessage(pFrameWnd->m_hWndMDIClient,
WM_MDIGETACTIVE, 0, 0);
if (hWnd == m_hWnd)
{
// still active -- fake deactivate it
ASSERT(hWnd != NULL);
OnMDIActivate(FALSE, NULL, this);
m_bPseudoInactive = TRUE; // so MDIGetActive returns NULL
}
}
else if (m_bPseudoInactive)
{
// if state transitioned from not visible to visible, but
// was pseudo deactivated -- send activate notify now
OnMDIActivate(TRUE, this, NULL);
ASSERT(!m_bPseudoInactive); // should get set in OnMDIActivate!
}
}
void CMDIChildWnd::SetHandles(HMENU hMenu, HACCEL hAccel)
{
m_hMenuShared = hMenu;
m_hAccelTable = hAccel;
}
/////////////////////////////////////////////////////////////////////////////
// CMDIChildWnd Diagnostics
#ifdef _DEBUG
void CMDIChildWnd::AssertValid() const
{
CFrameWnd::AssertValid();
ASSERT(m_hMenuShared == NULL || ::IsMenu(m_hMenuShared));
}
void CMDIChildWnd::Dump(CDumpContext& dc) const
{
CFrameWnd::Dump(dc);
dc << "m_hMenuShared = " << (UINT)m_hMenuShared;
dc << "\n";
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// Smarts for the "Window" menu
HMENU CMDIFrameWnd::GetWindowMenuPopup(HMENU hMenuBar)
// find which popup is the "Window" menu
{
if (hMenuBar == NULL)
return NULL;
ASSERT(::IsMenu(hMenuBar));
int iItem = ::GetMenuItemCount(hMenuBar);
while (iItem--)
{
HMENU hMenuPop = ::GetSubMenu(hMenuBar, iItem);
if (hMenuPop != NULL)
{
int iItemMax = ::GetMenuItemCount(hMenuPop);
for (int iItemPop = 0; iItemPop < iItemMax; iItemPop++)
{
UINT nID = GetMenuItemID(hMenuPop, iItemPop);
if (nID >= AFX_IDM_WINDOW_FIRST && nID <= AFX_IDM_WINDOW_LAST)
return hMenuPop;
}
}
}
// no default menu found
TRACE0("Warning: GetWindowMenuPopup failed!\n");
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// Smarts for updating the window menu based on the current child
void CMDIFrameWnd::OnUpdateFrameMenu(HMENU hMenuAlt)
{
CMDIChildWnd* pActiveWnd = MDIGetActive();
if (pActiveWnd != NULL)
{
// let child update the menu bar
pActiveWnd->OnUpdateFrameMenu(TRUE, pActiveWnd, hMenuAlt);
}
else
{
// no child active, so have to update it ourselves
// (we can't send it to a child window, since pActiveWnd is NULL)
if (hMenuAlt == NULL)
hMenuAlt = m_hMenuDefault; // use default
::SendMessage(m_hWndMDIClient, WM_MDISETMENU, (WPARAM)hMenuAlt, NULL);
}
}
/////////////////////////////////////////////////////////////////////////////
// MDI Child Extensions
// walk up two parents for MDIFrame that owns MDIChild (skip MDIClient)
CMDIFrameWnd* CMDIChildWnd::GetMDIFrame()
{
ASSERT_KINDOF(CMDIChildWnd, this);
ASSERT(m_hWnd != NULL);
HWND hWndMDIClient = ::GetParent(m_hWnd);
ASSERT(hWndMDIClient != NULL);
CMDIFrameWnd* pMDIFrame;
pMDIFrame = (CMDIFrameWnd*)CWnd::FromHandle(::GetParent(hWndMDIClient));
ASSERT(pMDIFrame != NULL);
ASSERT_KINDOF(CMDIFrameWnd, pMDIFrame);
ASSERT(pMDIFrame->m_hWndMDIClient == hWndMDIClient);
ASSERT_VALID(pMDIFrame);
return pMDIFrame;
}
CWnd* CMDIChildWnd::GetMessageBar()
{
// status bar/message bar owned by parent MDI frame
return GetMDIFrame()->GetMessageBar();
}
void CMDIChildWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
{
// update our parent window first
GetMDIFrame()->OnUpdateFrameTitle(bAddToTitle);
if ((GetStyle() & FWS_ADDTOTITLE) == 0)
return; // leave child window alone!
CDocument* pDocument = GetActiveDocument();
if (bAddToTitle)
{
TCHAR szText[256+_MAX_PATH];
if (pDocument == NULL)
lstrcpy(szText, m_strTitle);
else
lstrcpy(szText, pDocument->GetTitle());
if (m_nWindow > 0)
wsprintf(szText + lstrlen(szText), _T(":%d"), m_nWindow);
// set title if changed, but don't remove completely
AfxSetWindowText(m_hWnd, szText);
}
}
void CMDIChildWnd::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd*)
{
m_bPseudoInactive = FALSE; // must be happening for real
// make sure MDI client window has correct client edge
UpdateClientEdge();
// send deactivate notification to active view
CView* pActiveView = GetActiveView();
if (!bActivate && pActiveView != NULL)
pActiveView->OnActivateView(FALSE, pActiveView, pActiveView);
// allow hook to short circuit normal activation
BOOL bHooked = FALSE;
#ifndef _AFX_NO_OLE_SUPPORT
if (m_pNotifyHook != NULL && m_pNotifyHook->OnDocActivate(bActivate))
bHooked = TRUE;
#endif
// update titles (don't AddToTitle if deactivate last)
if (!bHooked)
OnUpdateFrameTitle(bActivate || (pActivateWnd != NULL));
// re-activate the appropriate view
if (bActivate)
{
if (pActiveView != NULL && GetMDIFrame() == GetActiveWindow())
pActiveView->OnActivateView(TRUE, pActiveView, pActiveView);
}
// update menus
if (!bHooked)
{
OnUpdateFrameMenu(bActivate, pActivateWnd, NULL);
GetMDIFrame()->DrawMenuBar();
}
}
void CMDIChildWnd::OnUpdateFrameMenu(BOOL bActivate, CWnd* pActivateWnd,
HMENU hMenuAlt)
{
CMDIFrameWnd* pFrame = GetMDIFrame();
if (hMenuAlt == NULL && bActivate)
{
// attempt to get default menu from document
CDocument* pDoc = GetActiveDocument();
if (pDoc != NULL)
hMenuAlt = pDoc->GetDefaultMenu();
}
// use default menu stored in frame if none from document
if (hMenuAlt == NULL)
hMenuAlt = m_hMenuShared;
if (hMenuAlt != NULL && bActivate)
{
ASSERT(pActivateWnd == this);
// activating child, set parent menu
::SendMessage(pFrame->m_hWndMDIClient, WM_MDISETMENU,
(WPARAM)hMenuAlt, (LPARAM)pFrame->GetWindowMenuPopup(hMenuAlt));
}
else if (hMenuAlt != NULL && !bActivate && pActivateWnd == NULL)
{
// destroying last child
HMENU hMenuLast = NULL;
::SendMessage(pFrame->m_hWndMDIClient, WM_MDISETMENU,
(WPARAM)pFrame->m_hMenuDefault, (LPARAM)hMenuLast);
}
else
{
// refresh MDI Window menu (even if non-shared menu)
::SendMessage(pFrame->m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
}
}
BOOL CMDIChildWnd::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
if (!CFrameWnd::OnNcCreate(lpCreateStruct))
return FALSE;
// handle extended styles under Win4
// call PreCreateWindow again just to get dwExStyle
VERIFY(PreCreateWindow(*lpCreateStruct));
SetWindowLong(m_hWnd, GWL_EXSTYLE, lpCreateStruct->dwExStyle);
return TRUE;
}
int CMDIChildWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// call base class with lParam context (not MDI one)
MDICREATESTRUCT* lpmcs;
lpmcs = (MDICREATESTRUCT*)lpCreateStruct->lpCreateParams;
CCreateContext* pContext = (CCreateContext*)lpmcs->lParam;
return OnCreateHelper(lpCreateStruct, pContext);
}
/////////////////////////////////////////////////////////////////////////////
// Special UI processing depending on current active child
void CMDIFrameWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
{
if ((GetStyle() & FWS_ADDTOTITLE) == 0)
return; // leave it alone!
#ifndef _AFX_NO_OLE_SUPPORT
// allow hook to set the title (used for OLE support)
if (m_pNotifyHook != NULL && m_pNotifyHook->OnUpdateFrameTitle())
return;
#endif
CMDIChildWnd* pActiveChild = NULL;
CDocument* pDocument = GetActiveDocument();
if (bAddToTitle &&
(pActiveChild = MDIGetActive()) != NULL &&
(pActiveChild->GetStyle() & WS_MAXIMIZE) == 0 &&
(pDocument != NULL ||
(pDocument = pActiveChild->GetActiveDocument()) != NULL))
UpdateFrameTitleForDocument(pDocument->GetTitle());
else
{
LPCTSTR lpstrTitle = NULL;
CString strTitle;
if (pActiveChild != NULL)
{
strTitle = pActiveChild->GetTitle();
if (!strTitle.IsEmpty())
lpstrTitle = strTitle;
}
UpdateFrameTitleForDocument(lpstrTitle);
}
}
/////////////////////////////////////////////////////////////////////////////
// Standard MDI Commands
// Two function for all standard MDI "Window" commands
void CMDIFrameWnd::OnUpdateMDIWindowCmd(CCmdUI* pCmdUI)
{
ASSERT(m_hWndMDIClient != NULL);
pCmdUI->Enable(MDIGetActive() != NULL);
}
BOOL CMDIFrameWnd::OnMDIWindowCmd(UINT nID)
{
ASSERT(m_hWndMDIClient != NULL);
UINT msg;
UINT wParam = 0;
switch (nID)
{
default:
return FALSE; // not for us
case ID_WINDOW_ARRANGE:
msg = WM_MDIICONARRANGE;
break;
case ID_WINDOW_CASCADE:
msg = WM_MDICASCADE;
break;
case ID_WINDOW_TILE_HORZ:
wParam = MDITILE_HORIZONTAL;
// fall through
case ID_WINDOW_TILE_VERT:
ASSERT(MDITILE_VERTICAL == 0);
msg = WM_MDITILE;
break;
}
::SendMessage(m_hWndMDIClient, msg, wParam, 0);
return TRUE;
}
void CMDIFrameWnd::OnWindowNew()
{
CMDIChildWnd* pActiveChild = MDIGetActive();
CDocument* pDocument;
if (pActiveChild == NULL ||
(pDocument = pActiveChild->GetActiveDocument()) == NULL)
{
TRACE0("Warning: No active document for WindowNew command.\n");
AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
return; // command failed
}
// otherwise we have a new frame !
CDocTemplate* pTemplate = pDocument->GetDocTemplate();
ASSERT_VALID(pTemplate);
CFrameWnd* pFrame = pTemplate->CreateNewFrame(pDocument, pActiveChild);
if (pFrame == NULL)
{
TRACE0("Warning: failed to create new frame.\n");
return; // command failed
}
pTemplate->InitialUpdateFrame(pFrame, pDocument);
}
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
IMPLEMENT_DYNCREATE(CMDIFrameWnd, CFrameWnd)
IMPLEMENT_DYNCREATE(CMDIChildWnd, CFrameWnd)
////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -