📄 winmdi.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1998 Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Foundation Classes Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft Foundation Classes product.
#include "stdafx.h"
#ifdef AFX_CORE4_SEG
#pragma code_seg(AFX_CORE4_SEG)
#endif
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CMDIFrameWnd
BEGIN_MESSAGE_MAP(CMDIFrameWnd, CFrameWnd)
//{{AFX_MSG_MAP(CMDIFrameWnd)
ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
ON_UPDATE_COMMAND_UI(ID_WINDOW_ARRANGE, OnUpdateMDIWindowCmd)
ON_UPDATE_COMMAND_UI(ID_WINDOW_CASCADE, OnUpdateMDIWindowCmd)
ON_UPDATE_COMMAND_UI(ID_WINDOW_TILE_HORZ, OnUpdateMDIWindowCmd)
ON_UPDATE_COMMAND_UI(ID_WINDOW_TILE_VERT, OnUpdateMDIWindowCmd)
ON_WM_SIZE()
ON_COMMAND_EX(ID_WINDOW_ARRANGE, OnMDIWindowCmd)
ON_COMMAND_EX(ID_WINDOW_CASCADE, OnMDIWindowCmd)
ON_COMMAND_EX(ID_WINDOW_TILE_HORZ, OnMDIWindowCmd)
ON_COMMAND_EX(ID_WINDOW_TILE_VERT, OnMDIWindowCmd)
ON_UPDATE_COMMAND_UI(ID_WINDOW_NEW, OnUpdateMDIWindowCmd)
ON_COMMAND(ID_WINDOW_NEW, OnWindowNew)
ON_WM_DESTROY()
ON_MESSAGE(WM_COMMANDHELP, OnCommandHelp)
ON_WM_MENUCHAR()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
CMDIFrameWnd::CMDIFrameWnd()
{
m_hWndMDIClient = NULL;
}
BOOL CMDIFrameWnd::OnCommand(WPARAM wParam, LPARAM lParam)
{
// send to MDI child first - will be re-sent through OnCmdMsg later
CMDIChildWnd* pActiveChild = MDIGetActive();
if (pActiveChild != NULL && AfxCallWndProc(pActiveChild,
pActiveChild->m_hWnd, WM_COMMAND, wParam, lParam) != 0)
return TRUE; // handled by child
if (CFrameWnd::OnCommand(wParam, lParam))
return TRUE; // handled through normal mechanism (MDI child or frame)
HWND hWndCtrl = (HWND)lParam;
ASSERT(AFX_IDM_FIRST_MDICHILD == 0xFF00);
if (hWndCtrl == NULL && (LOWORD(wParam) & 0xf000) == 0xf000)
{
// menu or accelerator within range of MDI children
// default frame proc will handle it
DefWindowProc(WM_COMMAND, wParam, lParam);
return TRUE;
}
return FALSE; // not handled
}
BOOL CMDIFrameWnd::OnCmdMsg(UINT nID, int nCode, void* pExtra,
AFX_CMDHANDLERINFO* pHandlerInfo)
{
CMDIChildWnd* pActiveChild = MDIGetActive();
// pump through active child FIRST
if (pActiveChild != NULL)
{
CPushRoutingFrame push(this);
if (pActiveChild->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
return TRUE;
}
// then pump through normal frame
return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}
LRESULT CMDIFrameWnd::OnCommandHelp(WPARAM wParam, LPARAM lParam)
{
if (lParam == 0 && IsTracking())
lParam = HID_BASE_COMMAND+m_nIDTracking;
CMDIChildWnd* pActiveChild = MDIGetActive();
if (pActiveChild != NULL && AfxCallWndProc(pActiveChild,
pActiveChild->m_hWnd, WM_COMMANDHELP, wParam, lParam) != 0)
{
// handled by child
return TRUE;
}
if (CFrameWnd::OnCommandHelp(wParam, lParam))
{
// handled by our base
return TRUE;
}
if (lParam != 0)
{
CWinApp* pApp = AfxGetApp();
if (pApp != NULL)
{
AfxGetApp()->WinHelp(lParam);
return TRUE;
}
}
return FALSE;
}
BOOL CMDIFrameWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext*)
{
CMenu* pMenu = NULL;
if (m_hMenuDefault == NULL)
{
// default implementation for MFC V1 backward compatibility
pMenu = GetMenu();
ASSERT(pMenu != NULL);
// This is attempting to guess which sub-menu is the Window menu.
// The Windows user interface guidelines say that the right-most
// menu on the menu bar should be Help and Window should be one
// to the left of that.
int iMenu = pMenu->GetMenuItemCount() - 2;
// If this assertion fails, your menu bar does not follow the guidelines
// so you will have to override this function and call CreateClient
// appropriately or use the MFC V2 MDI functionality.
ASSERT(iMenu >= 0);
pMenu = pMenu->GetSubMenu(iMenu);
ASSERT(pMenu != NULL);
}
return CreateClient(lpcs, pMenu);
}
BOOL CMDIFrameWnd::CreateClient(LPCREATESTRUCT lpCreateStruct,
CMenu* pWindowMenu)
{
ASSERT(m_hWnd != NULL);
ASSERT(m_hWndMDIClient == NULL);
DWORD dwStyle = WS_VISIBLE | WS_CHILD | WS_BORDER |
WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
MDIS_ALLCHILDSTYLES; // allow children to be created invisible
DWORD dwExStyle = 0;
// will be inset by the frame
if (afxData.bWin4)
{
// special styles for 3d effect on Win4
dwStyle &= ~WS_BORDER;
dwExStyle = WS_EX_CLIENTEDGE;
}
CLIENTCREATESTRUCT ccs;
ccs.hWindowMenu = pWindowMenu->GetSafeHmenu();
// set hWindowMenu for MFC V1 backward compatibility
// for MFC V2, window menu will be set in OnMDIActivate
ccs.idFirstChild = AFX_IDM_FIRST_MDICHILD;
if (lpCreateStruct->style & (WS_HSCROLL|WS_VSCROLL))
{
// parent MDIFrame's scroll styles move to the MDICLIENT
dwStyle |= (lpCreateStruct->style & (WS_HSCROLL|WS_VSCROLL));
// fast way to turn off the scrollbar bits (without a resize)
ModifyStyle(WS_HSCROLL|WS_VSCROLL, 0, SWP_NOREDRAW|SWP_FRAMECHANGED);
}
// Create MDICLIENT control with special IDC
if ((m_hWndMDIClient = ::CreateWindowEx(dwExStyle, _T("mdiclient"), NULL,
dwStyle, 0, 0, 0, 0, m_hWnd, (HMENU)AFX_IDW_PANE_FIRST,
AfxGetInstanceHandle(), (LPVOID)&ccs)) == NULL)
{
TRACE(_T("Warning: CMDIFrameWnd::OnCreateClient: failed to create MDICLIENT.")
_T(" GetLastError returns 0x%8.8X\n"), ::GetLastError());
return FALSE;
}
// Move it to the top of z-order
::BringWindowToTop(m_hWndMDIClient);
return TRUE;
}
LRESULT CMDIFrameWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
return ::DefFrameProc(m_hWnd, m_hWndMDIClient, nMsg, wParam, lParam);
}
BOOL CMDIFrameWnd::PreTranslateMessage(MSG* pMsg)
{
// check for special cancel modes for ComboBoxes
if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_NCLBUTTONDOWN)
AfxCancelModes(pMsg->hwnd); // filter clicks
// allow tooltip messages to be filtered
if (CWnd::PreTranslateMessage(pMsg))
return TRUE;
#ifndef _AFX_NO_OLE_SUPPORT
// allow hook to consume message
if (m_pNotifyHook != NULL && m_pNotifyHook->OnPreTranslateMessage(pMsg))
return TRUE;
#endif
CMDIChildWnd* pActiveChild = MDIGetActive();
// current active child gets first crack at it
if (pActiveChild != NULL && pActiveChild->PreTranslateMessage(pMsg))
return TRUE;
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
{
// translate accelerators for frame and any children
if (m_hAccelTable != NULL &&
::TranslateAccelerator(m_hWnd, m_hAccelTable, pMsg))
{
return TRUE;
}
// special processing for MDI accelerators last
// and only if it is not in SDI mode (print preview)
if (GetActiveView() == NULL)
{
if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
{
// the MDICLIENT window may translate it
if (::TranslateMDISysAccel(m_hWndMDIClient, pMsg))
return TRUE;
}
}
}
return FALSE;
}
void CMDIFrameWnd::DelayUpdateFrameMenu(HMENU hMenuAlt)
{
OnUpdateFrameMenu(hMenuAlt);
m_nIdleFlags |= idleMenu;
}
void CMDIFrameWnd::OnIdleUpdateCmdUI()
{
if (m_nIdleFlags & idleMenu)
{
DrawMenuBar();
m_nIdleFlags &= ~idleMenu;
}
CFrameWnd::OnIdleUpdateCmdUI();
}
CFrameWnd* CMDIFrameWnd::GetActiveFrame()
{
CMDIChildWnd* pActiveChild = MDIGetActive();
if (pActiveChild == NULL)
return this;
return pActiveChild;
}
BOOL CMDIFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDMDIFRAME_REG));
cs.lpszClass = _afxWndMDIFrame;
}
return TRUE;
}
BOOL CMDIFrameWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
CWnd* pParentWnd, CCreateContext* pContext)
{
if (!CFrameWnd::LoadFrame(nIDResource, dwDefaultStyle,
pParentWnd, pContext))
return FALSE;
// save menu to use when no active MDI child window is present
ASSERT(m_hWnd != NULL);
m_hMenuDefault = ::GetMenu(m_hWnd);
if (m_hMenuDefault == NULL)
TRACE0("Warning: CMDIFrameWnd without a default menu.\n");
return TRUE;
}
void CMDIFrameWnd::OnDestroy()
{
CFrameWnd::OnDestroy(); // exit and misc cleanup
// owned menu stored in shared slot for MDIFRAME
if (m_hMenuDefault != NULL && ::GetMenu(m_hWnd) != m_hMenuDefault)
{
// must go through MDI client to get rid of MDI menu additions
::SendMessage(m_hWndMDIClient, WM_MDISETMENU,
(WPARAM)m_hMenuDefault, NULL);
ASSERT(::GetMenu(m_hWnd) == m_hMenuDefault);
}
}
void CMDIFrameWnd::OnSize(UINT nType, int, int)
{
// do not call default - it will reposition the MDICLIENT
if (nType != SIZE_MINIMIZED)
RecalcLayout();
}
LRESULT CMDIFrameWnd::OnMenuChar(UINT nChar, UINT, CMenu*)
{
// do not call Default() for Alt+(-) when in print preview mode
if (m_lpfnCloseProc != NULL && nChar == (UINT)'-')
return 0;
else
return Default();
}
CMDIChildWnd* CMDIFrameWnd::MDIGetActive(BOOL* pbMaximized) const
{
// check first for MDI client window not created
if (m_hWndMDIClient == NULL)
{
if (pbMaximized != NULL)
*pbMaximized = FALSE;
return NULL;
}
// MDI client has been created, get active MDI child
HWND hWnd = (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0,
(LPARAM)pbMaximized);
CMDIChildWnd* pWnd = (CMDIChildWnd*)CWnd::FromHandlePermanent(hWnd);
ASSERT(pWnd == NULL || pWnd->IsKindOf(RUNTIME_CLASS(CMDIChildWnd)));
// check for special pseudo-inactive state
if (pWnd != NULL && pWnd->m_bPseudoInactive &&
(pWnd->GetStyle() & WS_VISIBLE) == 0)
{
// Window is hidden, active, but m_bPseudoInactive -- return NULL
pWnd = NULL;
// Ignore maximized flag if pseudo-inactive and maximized
if (pbMaximized != NULL)
*pbMaximized = FALSE;
}
return pWnd;
}
CMDIChildWnd* CMDIFrameWnd::CreateNewChild(CRuntimeClass* pClass,
UINT nResources, HMENU hMenu /* = NULL */, HACCEL hAccel /* = NULL */)
{
ASSERT(pClass != NULL);
CMDIChildWnd* pFrame = (CMDIChildWnd*) pClass->CreateObject();
ASSERT_KINDOF(CMDIChildWnd, pFrame);
// load the frame
CCreateContext context;
context.m_pCurrentFrame = this;
if (!pFrame->LoadFrame(nResources,
WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, &context))
{
TRACE0("Couldn't load frame window.\n");
delete pFrame;
return NULL;
}
CString strFullString, strTitle;
if (strFullString.LoadString(nResources))
AfxExtractSubString(strTitle, strFullString, CDocTemplate::docName);
// set the handles and redraw the frame and parent
pFrame->SetHandles(hMenu, hAccel);
pFrame->SetTitle(strTitle);
pFrame->InitialUpdateFrame(NULL, TRUE);
return pFrame;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -