home *** CD-ROM | disk | FTP | other *** search
- // 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::FromHandle(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;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CMDIFrameWnd Diagnostics
-
- #ifdef _DEBUG
- void CMDIFrameWnd::AssertValid() const
- {
- CFrameWnd::AssertValid();
- ASSERT(m_hWndMDIClient == NULL || ::IsWindow(m_hWndMDIClient));
- ASSERT(m_hMenuDefault == NULL || ::IsMenu(m_hMenuDefault));
- }
-
- void CMDIFrameWnd::Dump(CDumpContext& dc) const
- {
- CFrameWnd::Dump(dc);
-
- dc << "m_hWndMDIClient = " << (UINT)m_hWndMDIClient;
- dc << "\nm_hMenuDefault = " << (UINT)m_hMenuDefault;
-
- dc << "\n";
- }
- #endif //_DEBUG
-
- /////////////////////////////////////////////////////////////////////////////
- // CMDIChildWnd
-
- BEGIN_MESSAGE_MAP(CMDIChildWnd, CFrameWnd)
- //{{AFX_MSG_MAP(CMDIChildWnd)
- ON_WM_MOUSEACTIVATE()
- ON_WM_NCACTIVATE()
- ON_WM_MDIACTIVATE()
- ON_WM_SIZE()
- ON_WM_WINDOWPOSCHANGING()
- ON_WM_NCCREATE()
- ON_WM_CREATE()
- ON_WM_DESTROY()
- ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
- ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
- //}}AFX_MSG_MAP
- END_MESSAGE_MAP()
-
- CMDIChildWnd::CMDIChildWnd()
- {
- m_hMenuShared = NULL;
- m_bPseudoInactive = FALSE;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // CMDIChildWnd special processing
-
- LRESULT CMDIChildWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- return ::DefMDIChildProc(m_hWnd, nMsg, wParam, lParam);
- }
-
- BOOL CMDIChildWnd::DestroyWindow()
- {
- if (m_hWnd == NULL)
- return FALSE;
-
- // avoid changing the caption during the destroy message(s)
- CMDIFrameWnd* pFrameWnd = GetMDIFrame();
- HWND hWndFrame = pFrameWnd->m_hWnd;
- ASSERT(::IsWindow(hWndFrame));
- DWORD dwStyle = SetWindowLong(hWndFrame, GWL_STYLE,
- GetWindowLong(hWndFrame, GWL_STYLE) & ~FWS_ADDTOTITLE);
-
- MDIDestroy();
-
- if (::IsWindow(hWndFrame))
- {
- ASSERT(hWndFrame == pFrameWnd->m_hWnd);
- SetWindowLong(hWndFrame, GWL_STYLE, dwStyle);
- pFrameWnd->OnUpdateFrameTitle(TRUE);
- }
-
- return TRUE;
- }
-
- BOOL CMDIChildWnd::PreTranslateMessage(MSG* pMsg)
- {
- // check for special cancel modes for combo boxes
- 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;
-
- // we can't call 'CFrameWnd::PreTranslate' since it will translate
- // accelerators in the context of the MDI Child - but since MDI Child
- // windows don't have menus this doesn't work properly. MDI Child
- // accelerators must be translated in context of their MDI Frame.
-
- if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
- {
- // use document specific accelerator table over m_hAccelTable
- HACCEL hAccel = GetDefaultAccelerator();
- return hAccel != NULL &&
- ::TranslateAccelerator(GetMDIFrame()->m_hWnd, hAccel, pMsg);
- }
- return FALSE;
- }
-
- BOOL CMDIChildWnd::PreCreateWindow(CREATESTRUCT& cs)
- {
- ASSERT(cs.style & WS_CHILD);
- // MFC V2 requires that MDI Children are created with proper styles,
- // usually: WS_CHILD | WS_VISIBLE | WS_OVERLAPPEDWINDOW.
- // See Technical note TN019 for more details on MFC V1->V2 migration.
-
- return CFrameWnd::PreCreateWindow(cs);
- }
-
- BOOL CMDIChildWnd::Create(LPCTSTR lpszClassName,
- LPCTSTR lpszWindowName, DWORD dwStyle,
- const RECT& rect, CMDIFrameWnd* pParentWnd,
- CCreateContext* pContext)
- {
- if (pParentWnd == NULL)
- {
- CWnd* pMainWnd = AfxGetThread()->m_pMainWnd;
- ASSERT(pMainWnd != NULL);
- ASSERT_KINDOF(CMDIFrameWnd, pMainWnd);
- pParentWnd = (CMDIFrameWnd*)pMainWnd;
- }
- ASSERT(::IsWindow(pParentWnd->m_hWndMDIClient));
-
- // insure correct window positioning
- pParentWnd->RecalcLayout();
-
- // first copy into a CREATESTRUCT for PreCreate
- CREATESTRUCT cs;
- cs.dwExStyle = 0L;
- cs.lpszClass = lpszClassName;
- cs.lpszName = lpszWindowName;
- cs.style = dwStyle;
- cs.x = rect.left;
- cs.y = rect.top;
- cs.cx = rect.right - rect.left;
- cs.cy = rect.bottom - rect.top;
- cs.hwndParent = pParentWnd->m_hWnd;
- cs.hMenu = NULL;
- cs.hInstance = AfxGetInstanceHandle();
- cs.lpCreateParams = (LPVOID)pContext;
-
- if (!PreCreateWindow(cs))
- {
- PostNcDestroy();
- return FALSE;
- }
- // extended style must be zero for MDI Children (except under Win4)
- ASSERT(afxData.bWin4 || cs.dwExStyle == 0);
- ASSERT(cs.hwndParent == pParentWnd->m_hWnd); // must not change
-
- // now copy into a MDICREATESTRUCT for real create
- MDICREATESTRUCT mcs;
- mcs.szClass = cs.lpszClass;
- mcs.szTitle = cs.lpszName;
- mcs.hOwner = cs.hInstance;
- mcs.x = cs.x;
- mcs.y = cs.y;
- mcs.cx = cs.cx;
- mcs.cy = cs.cy;
- mcs.style = cs.style & ~(WS_MAXIMIZE | WS_VISIBLE);
- mcs.lParam = (LONG)cs.lpCreateParams;
-
- // create the window through the MDICLIENT window
- AfxHookWindowCreate(this);
- HWND hWnd = (HWND)::SendMessage(pParentWnd->m_hWndMDIClient,
- WM_MDICREATE, 0, (LPARAM)&mcs);
- if (!AfxUnhookWindowCreate())
- PostNcDestroy(); // cleanup if MDICREATE fails too soon
-
- if (hWnd == NULL)
- return FALSE;
-
- // special handling of visibility (always created invisible)
- if (cs.style & WS_VISIBLE)
- {
- // place the window on top in z-order before showing it
- ::BringWindowToTop(hWnd);
-
- // show it as specified
- if (cs.style & WS_MINIMIZE)
- ShowWindow(SW_SHOWMINIMIZED);
- else if (cs.style & WS_MAXIMIZE)
- ShowWindow(SW_SHOWMAXIMIZED);
- else
- ShowWindow(SW_SHOWNORMAL);
-
- // make sure it is active (visibility == activation)
- pParentWnd->MDIActivate(this);
-
- // refresh MDI Window menu
- ::SendMessage(pParentWnd->m_hWndMDIClient, WM_MDIREFRESHMENU, 0, 0);
- }
-
- ASSERT(hWnd == m_hWnd);
- return TRUE;
- }
-
- BOOL CMDIChildWnd::LoadFrame(UINT nIDResource, DWORD dwDefaultStyle,
- CWnd* pParentWnd, CCreateContext* pContext)
- {
- // only do this once
- ASSERT_VALID_IDR(nIDResource);
- ASSERT(m_nIDHelp == 0 || m_nIDHelp == nIDResource);
- ASSERT(m_hMenuShared == NULL); // only do once
-
- m_nIDHelp = nIDResource; // ID for help context (+HID_BASE_RESOURCE)
-
- // parent must be MDI Frame (or NULL for default)
- ASSERT(pParentWnd == NULL || pParentWnd->IsKindOf(RUNTIME_CLASS(CMDIFrameWnd)));
- // will be a child of MDIClient
- ASSERT(!(dwDefaultStyle & WS_POPUP));
- dwDefaultStyle |= WS_CHILD;
-
- // if available - get MDI child menus from doc template
- ASSERT(m_hMenuShared == NULL); // only do once
- CMultiDocTemplate* pTemplate;
- if (pContext != NULL &&
- (pTemplate = (CMultiDocTemplate*)pContext->m_pNewDocTemplate) != NULL)
- {
- ASSERT_KINDOF(CMultiDocTemplate, pTemplate);
- // get shared menu from doc template
- m_hMenuShared = pTemplate->m_hMenuShared;
- m_hAccelTable = pTemplate->m_hAccelTable;
- }
- else
- {
- TRACE0("Warning: no shared menu/acceltable for MDI Child window.\n");
- // if this happens, programmer must load these manually
- }
-
- CString strFullString, strTitle;
- if (strFullString.LoadString(nIDResource))
- AfxExtractSubString(strTitle, strFullString, 0); // first sub-string
-
- ASSERT(m_hWnd == NULL);
- if (!Create(GetIconWndClass(dwDefaultStyle, nIDResource),
- strTitle, dwDefaultStyle, rectDefault,
- (CMDIFrameWnd*)pParentWnd, pContext))
- {
- return FALSE; // will self destruct on failure normally
- }
-
- // it worked !
- return TRUE;
- }
-
- void CMDIChildWnd::OnSize(UINT nType, int cx, int cy)
- {
- CFrameWnd::OnSize(nType, cx, cy);
-
- // update our parent frame - in case we are now maximized or not
- GetMDIFrame()->OnUpdateFrameTitle(TRUE);
- }
-
- BOOL CMDIChildWnd::UpdateClientEdge(LPRECT lpRect)
- {
- if (!afxData.bWin4)
- return FALSE;
-
- // only adjust for active MDI child window
- CMDIFrameWnd* pFrameWnd = GetMDIFrame();
- CMDIChildWnd* pChild = pFrameWnd->MDIGetActive();
- if (pChild == NULL || pChild == this)
- {
- // need to adjust the client edge style as max/restore happens
- DWORD dwStyle = ::GetWindowLong(pFrameWnd->m_hWndMDIClient, GWL_EXSTYLE);
- DWORD dwNewStyle = dwStyle;
- if (pChild != NULL && !(GetExStyle() & WS_EX_CLIENTEDGE) &&
- (GetStyle() & WS_MAXIMIZE))
- dwNewStyle &= ~(WS_EX_CLIENTEDGE);
- else
- dwNewStyle |= WS_EX_CLIENTEDGE;
-
- if (dwStyle != dwNewStyle)
- {
- // SetWindowPos will not move invalid bits
- ::RedrawWindow(pFrameWnd->m_hWndMDIClient, NULL, NULL,
- RDW_INVALIDATE | RDW_ALLCHILDREN);
-
- // remove/add WS_EX_CLIENTEDGE to MDI client area
- ::SetWindowLong(pFrameWnd->m_hWndMDIClient, GWL_EXSTYLE, dwNewStyle);
- ::SetWindowPos(pFrameWnd->m_hWndMDIClient, NULL, 0, 0, 0, 0,
- SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE |
- SWP_NOZORDER | SWP_NOCOPYBITS);
-
- // return new client area
- if (lpRect != NULL)
- ::GetClientRect(pFrameWnd->m_hWndMDIClient, lpRect);
- return TRUE;
- }
- }
- return FALSE;
- }
-
- void CMDIChildWnd::OnWindowPosChanging(LPWINDOWPOS lpWndPos)
- {
- if (afxData.bWin4 && !(lpWndPos->flags & SWP_NOSIZE))
- {
- CRect rectClient;
- if (UpdateClientEdge(rectClient) && (GetStyle() & WS_MAXIMIZE))
- {
- // adjust maximized window size and position based on new
- // size/position of the MDI client area.
- ::AdjustWindowRectEx(rectClient, GetStyle(), FALSE, GetExStyle());
- lpWndPos->x = rectClient.left;
- lpWndPos->y = rectClient.top;
- lpWndPos->cx = rectClient.Width();
- lpWndPos->cy = rectClient.Height();
- }
- }
-
- CFrameWnd::OnWindowPosChanging(lpWndPos);
- }
-
- void CMDIChildWnd::OnDestroy()
- {
- UpdateClientEdge();
-
- CFrameWnd::OnDestroy();
- }
-
- BOOL CMDIChildWnd::OnNcActivate(BOOL bActive)
- {
- // bypass CFrameWnd::OnNcActivate()
- return CWnd::OnNcActivate(bActive);
- }
-
- int CMDIChildWnd::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
- {
- int nResult = CFrameWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
- if (nResult == MA_NOACTIVATE || nResult == MA_NOACTIVATEANDEAT)
- return nResult; // frame does not want to activate
-
- // activate this window if necessary
- CMDIFrameWnd* pFrameWnd = GetMDIFrame();
- ASSERT_VALID(pFrameWnd);
- CMDIChildWnd* pActive = pFrameWnd->MDIGetActive();
- if (pActive != this)
- MDIActivate();
-
- return nResult;
- }
-
- BOOL CMDIChildWnd::OnToolTipText(UINT msg, NMHDR* pNMHDR, LRESULT* pResult)
- {
- ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW);
- UNUSED(pNMHDR);
-
- // check to see if the message is going directly to this window or not
- const MSG* pMsg = GetCurrentMessage();
- if (pMsg->hwnd != m_hWnd)
- {
- // let top level frame handle this for us
- return FALSE;
- }
-
- // otherwise, handle it ourselves
- return CFrameWnd::OnToolTipText(msg, pNMHDR, pResult);
- }
-
- void CMDIChildWnd::ActivateFrame(int nCmdShow)
- {
- BOOL bVisibleThen = (GetStyle() & WS_VISIBLE) != 0;
- CMDIFrameWnd* pFrameWnd = GetMDIFrame();
- ASSERT_VALID(pFrameWnd);
-
- // determine default show command
- if (nCmdShow == -1)
- {
- // get maximized state of frame window (previously active child)
- BOOL bMaximized;
- pFrameWnd->MDIGetActive(&bMaximized);
-
- // convert show command based on current style
- DWORD dwStyle = GetStyle();
- if (bMaximized || (dwStyle & WS_MAXIMIZE))
- nCmdShow = SW_SHOWMAXIMIZED;
- else if (dwStyle & WS_MINIMIZE)
- nCmdShow = SW_SHOWMINIMIZED;
- }
-
- // finally, show the window
- CFrameWnd::ActivateFrame(nCmdShow);
-
- // 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)
-
- ////////////////////////////////////////////////////////////////////////////
-