--- /dev/null
+// Win32++ Version 7.3\r
+// Released: 30th November 2011\r
+//\r
+// David Nash\r
+// url: https://sourceforge.net/projects/win32-framework\r
+//\r
+//\r
+// Copyright (c) 2005-2011 David Nash\r
+//\r
+// Permission is hereby granted, free of charge, to\r
+// any person obtaining a copy of this software and\r
+// associated documentation files (the "Software"),\r
+// to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify,\r
+// merge, publish, distribute, sublicense, and/or sell\r
+// copies of the Software, and to permit persons to whom\r
+// the Software is furnished to do so, subject to the\r
+// following conditions:\r
+//\r
+// The above copyright notice and this permission notice\r
+// shall be included in all copies or substantial portions\r
+// of the Software.\r
+//\r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF\r
+// ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED\r
+// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A\r
+// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT\r
+// SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+// ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\r
+// OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+////////////////////////////////////////////////////////\r
+\r
+\r
+////////////////////////////////////////////////////////\r
+// mdi.h\r
+// Declaration of the CMDIChild and CMDIFrame classes\r
+\r
+// The classes defined here add MDI frames support to Win32++. MDI\r
+// (Multiple Document Interface) frames host one or more child windows. The\r
+// child windows hosted by a MDI frame can be different types. For example,\r
+// some MDI child windows could be used to edit text, while others could be\r
+// used to display a bitmap. Four classes are defined here to support MDI\r
+// frames:\r
+\r
+\r
+// 1) CMDIFrame. This class inherits from CFrame, and adds the functionality\r
+// required by MDI frames. It keeps track of the MDI children created and\r
+// destroyed, and adjusts the menu when a MDI child is activated. Use the\r
+// AddMDIChild function to add MDI child windows to the MDI frame. Inherit\r
+// from CMDIFrame to create your own MDI frame.\r
+//\r
+// 2) CMDIChild: All MDI child windows (ie. CWnd classes) should inherit from\r
+// this class. Each MDI child type can have a different frame menu.\r
+\r
+// Use the MDIFrame generic application as the starting point for your own MDI\r
+// frame applications.\r
+// Refer to the MDIDemo sample for an example on how to use these classes to\r
+// create a MDI frame application with different types of MDI child windows.\r
+\r
+\r
+#ifndef _WIN32XX_MDI_H_\r
+#define _WIN32XX_MDI_H_\r
+\r
+#include "frame.h"\r
+#include <vector>\r
+\r
+\r
+\r
+namespace Win32xx\r
+{\r
+ class CMDIChild;\r
+ class CMDIFrame;\r
+ typedef Shared_Ptr<CMDIChild> MDIChildPtr;\r
+\r
+ /////////////////////////////////////\r
+ // Declaration of the CMDIChild class\r
+ //\r
+ class CMDIChild : public CWnd\r
+ {\r
+ friend class CMDIFrame;\r
+ public:\r
+ CMDIChild();\r
+ virtual ~CMDIChild();\r
+\r
+ // These are the functions you might wish to override\r
+ virtual HWND Create(CWnd* pParent = NULL);\r
+ virtual void RecalcLayout();\r
+\r
+ // These functions aren't virtual, and shouldn't be overridden\r
+ void SetHandles(HMENU MenuName, HACCEL AccelName);\r
+ CMDIFrame* GetMDIFrame() const;\r
+ CWnd* GetView() const {return m_pView;}\r
+ void SetView(CWnd& pwndView);\r
+ void MDIActivate() const;\r
+ void MDIDestroy() const;\r
+ void MDIMaximize() const;\r
+ void MDIRestore() const;\r
+\r
+ protected:\r
+ // Its unlikely you would need to override these functions\r
+ virtual LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
+ virtual void OnCreate();\r
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
+\r
+ private:\r
+ CMDIChild(const CMDIChild&); // Disable copy construction\r
+ CMDIChild& operator = (const CMDIChild&); // Disable assignment operator\r
+\r
+ CWnd* m_pView; // pointer to the View CWnd object\r
+ HMENU m_hChildMenu;\r
+ HACCEL m_hChildAccel;\r
+ };\r
+\r
+\r
+ /////////////////////////////////////\r
+ // Declaration of the CMDIFrame class\r
+ //\r
+ class CMDIFrame : public CFrame\r
+ {\r
+ friend class CMDIChild; // CMDIChild uses m_hOrigMenu\r
+ typedef Shared_Ptr<CMDIChild> MDIChildPtr;\r
+\r
+ public:\r
+ class CMDIClient : public CWnd // a nested class within CMDIFrame\r
+ {\r
+ public:\r
+ CMDIClient() {}\r
+ virtual ~CMDIClient() {}\r
+ virtual HWND Create(CWnd* pParent = NULL);\r
+ virtual LRESULT WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
+ CMDIFrame* GetMDIFrame() const { return (CMDIFrame*)GetParent(); }\r
+\r
+ private:\r
+ CMDIClient(const CMDIClient&); // Disable copy construction\r
+ CMDIClient& operator = (const CMDIClient&); // Disable assignment operator\r
+ };\r
+\r
+\r
+ CMDIFrame();\r
+ virtual ~CMDIFrame() {}\r
+\r
+ virtual CMDIChild* AddMDIChild(MDIChildPtr pMDIChild);\r
+ virtual CMDIClient& GetMDIClient() const { return (CMDIClient&)m_MDIClient; }\r
+ virtual BOOL IsMDIFrame() const { return TRUE; }\r
+ virtual void RemoveMDIChild(HWND hWnd);\r
+ virtual BOOL RemoveAllMDIChildren();\r
+ virtual void UpdateCheckMarks();\r
+\r
+ // These functions aren't virtual, so don't override them\r
+ std::vector <MDIChildPtr>& GetAllMDIChildren() {return m_vMDIChild;}\r
+ CMDIChild* GetActiveMDIChild() const;\r
+ BOOL IsMDIChildMaxed() const;\r
+ void MDICascade(int nType = 0) const;\r
+ void MDIIconArrange() const;\r
+ void MDIMaximize() const;\r
+ void MDINext() const;\r
+ void MDIPrev() const;\r
+ void MDIRestore() const;\r
+ void MDITile(int nType = 0) const;\r
+ void SetActiveMDIChild(CMDIChild* pChild);\r
+\r
+ protected:\r
+ // These are the functions you might wish to override\r
+ virtual void OnClose();\r
+ virtual void OnViewStatusBar();\r
+ virtual void OnViewToolBar();\r
+ virtual void OnWindowPosChanged();\r
+ virtual void RecalcLayout();\r
+ virtual BOOL PreTranslateMessage(MSG* pMsg);\r
+ virtual LRESULT WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
+\r
+ private:\r
+ CMDIFrame(const CMDIFrame&); // Disable copy construction\r
+ CMDIFrame& operator = (const CMDIFrame&); // Disable assignment operator\r
+ void AppendMDIMenu(HMENU hMenuWindow);\r
+ LRESULT FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam);\r
+ void UpdateFrameMenu(HMENU hMenu);\r
+\r
+ CMDIClient m_MDIClient;\r
+ std::vector <MDIChildPtr> m_vMDIChild;\r
+ HWND m_hActiveMDIChild;\r
+ };\r
+\r
+}\r
+\r
+\r
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r
+\r
+\r
+namespace Win32xx\r
+{\r
+\r
+ /////////////////////////////////////\r
+ // Definitions for the CMDIFrame class\r
+ //\r
+ inline CMDIFrame::CMDIFrame() : m_hActiveMDIChild(NULL)\r
+ {\r
+ SetView(GetMDIClient());\r
+ }\r
+\r
+ inline CMDIChild* CMDIFrame::AddMDIChild(MDIChildPtr pMDIChild)\r
+ {\r
+ assert(NULL != pMDIChild.get()); // Cannot add Null MDI Child\r
+\r
+ m_vMDIChild.push_back(pMDIChild);\r
+ pMDIChild->Create(GetView());\r
+\r
+ return pMDIChild.get();\r
+ }\r
+\r
+ inline void CMDIFrame::AppendMDIMenu(HMENU hMenuWindow)\r
+ {\r
+ // Adds the additional menu items the the "Window" submenu when\r
+ // MDI child windows are created\r
+\r
+ if (!IsMenu(hMenuWindow))\r
+ return;\r
+\r
+ // Delete previously appended items\r
+ int nItems = ::GetMenuItemCount(hMenuWindow);\r
+ UINT uLastID = ::GetMenuItemID(hMenuWindow, --nItems);\r
+ if ((uLastID >= IDW_FIRSTCHILD) && (uLastID < IDW_FIRSTCHILD + 10))\r
+ {\r
+ while ((uLastID >= IDW_FIRSTCHILD) && (uLastID < IDW_FIRSTCHILD + 10))\r
+ {\r
+ ::DeleteMenu(hMenuWindow, nItems, MF_BYPOSITION);\r
+ uLastID = ::GetMenuItemID(hMenuWindow, --nItems);\r
+ }\r
+ //delete the separator too\r
+ ::DeleteMenu(hMenuWindow, nItems, MF_BYPOSITION);\r
+ }\r
+\r
+ int nWindow = 0;\r
+\r
+ // Allocate an iterator for our MDIChild vector\r
+ std::vector <MDIChildPtr>::iterator v;\r
+\r
+ for (v = GetAllMDIChildren().begin(); v < GetAllMDIChildren().end(); ++v)\r
+ {\r
+ if ((*v)->GetWindowLongPtr(GWL_STYLE) & WS_VISIBLE) // IsWindowVisible is unreliable here\r
+ {\r
+ // Add Separator\r
+ if (0 == nWindow)\r
+ ::AppendMenu(hMenuWindow, MF_SEPARATOR, 0, NULL);\r
+\r
+ // Add a menu entry for each MDI child (up to 9)\r
+ if (nWindow < 9)\r
+ {\r
+ CString strMenuItem ( (*v)->GetWindowText() );\r
+\r
+ if (strMenuItem.GetLength() > MAX_MENU_STRING -10)\r
+ {\r
+ // Truncate the string if its too long\r
+ strMenuItem.Delete(strMenuItem.GetLength() - MAX_MENU_STRING +10);\r
+ strMenuItem += _T(" ...");\r
+ }\r
+\r
+ TCHAR szMenuString[MAX_MENU_STRING+1];\r
+ wsprintf(szMenuString, _T("&%d %s"), nWindow+1, strMenuItem.c_str());\r
+\r
+ ::AppendMenu(hMenuWindow, MF_STRING, IDW_FIRSTCHILD + nWindow, szMenuString);\r
+\r
+ if (GetActiveMDIChild() == (*v).get())\r
+ ::CheckMenuItem(hMenuWindow, IDW_FIRSTCHILD+nWindow, MF_CHECKED);\r
+\r
+ ++nWindow;\r
+ }\r
+ else if (9 == nWindow)\r
+ // For the 10th MDI child, add this menu item and return\r
+ {\r
+ ::AppendMenu(hMenuWindow, MF_STRING, IDW_FIRSTCHILD + nWindow, _T("&Windows..."));\r
+ return;\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ inline LRESULT CMDIFrame::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
+ {\r
+ return ::DefFrameProc(m_hWnd, GetMDIClient(), uMsg, wParam, lParam);\r
+ }\r
+\r
+ inline CMDIChild* CMDIFrame::GetActiveMDIChild() const\r
+ {\r
+ return (CMDIChild*)FromHandle(m_hActiveMDIChild);\r
+ }\r
+\r
+ inline BOOL CMDIFrame::IsMDIChildMaxed() const\r
+ {\r
+ BOOL bMaxed = FALSE;\r
+ GetMDIClient().SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMaxed);\r
+ return bMaxed;\r
+ }\r
+\r
+ inline void CMDIFrame::MDICascade(int nType /* = 0*/) const\r
+ {\r
+ // Possible values for nType are:\r
+ // MDITILE_SKIPDISABLED Prevents disabled MDI child windows from being cascaded.\r
+\r
+ assert(::IsWindow(m_hWnd));\r
+ GetView()->SendMessage(WM_MDICASCADE, (WPARAM)nType, 0L);\r
+ }\r
+\r
+ inline void CMDIFrame::MDIIconArrange() const\r
+ {\r
+ assert(::IsWindow(m_hWnd));\r
+ GetView()->SendMessage(WM_MDIICONARRANGE, 0L, 0L);\r
+ }\r
+\r
+ inline void CMDIFrame::MDIMaximize() const\r
+ {\r
+ assert(::IsWindow(m_hWnd));\r
+ GetView()->SendMessage(WM_MDIMAXIMIZE, 0L, 0L);\r
+ }\r
+\r
+ inline void CMDIFrame::MDINext() const\r
+ {\r
+ assert(::IsWindow(m_hWnd));\r
+ HWND hMDIChild = GetActiveMDIChild()->GetHwnd();\r
+ GetView()->SendMessage(WM_MDINEXT, (WPARAM)hMDIChild, FALSE);\r
+ }\r
+\r
+ inline void CMDIFrame::MDIPrev() const\r
+ {\r
+ assert(::IsWindow(m_hWnd));\r
+ HWND hMDIChild = GetActiveMDIChild()->GetHwnd();\r
+ GetView()->SendMessage(WM_MDINEXT, (WPARAM)hMDIChild, TRUE);\r
+ }\r
+\r
+ inline void CMDIFrame::MDIRestore() const\r
+ {\r
+ assert(::IsWindow(m_hWnd));\r
+ GetView()->SendMessage(WM_MDIRESTORE, 0L, 0L);\r
+ }\r
+\r
+ inline void CMDIFrame::MDITile(int nType /* = 0*/) const\r
+ {\r
+ // Possible values for nType are:\r
+ // MDITILE_HORIZONTAL Tiles MDI child windows so that one window appears above another.\r
+ // MDITILE_SKIPDISABLED Prevents disabled MDI child windows from being tiled.\r
+ // MDITILE_VERTICAL Tiles MDI child windows so that one window appears beside another.\r
+\r
+ assert(::IsWindow(m_hWnd));\r
+ GetView()->SendMessage(WM_MDITILE, (WPARAM)nType, 0L);\r
+ }\r
+\r
+ inline void CMDIFrame::OnClose()\r
+ {\r
+ if (RemoveAllMDIChildren())\r
+ {\r
+ CFrame::OnClose();\r
+ Destroy();\r
+ }\r
+ }\r
+\r
+ inline void CMDIFrame::OnViewStatusBar()\r
+ {\r
+ CFrame::OnViewStatusBar();\r
+ UpdateCheckMarks();\r
+ GetView()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);\r
+ }\r
+\r
+ inline void CMDIFrame::OnViewToolBar()\r
+ {\r
+ CFrame::OnViewToolBar();\r
+ UpdateCheckMarks();\r
+ GetView()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN);\r
+ }\r
+\r
+ inline void CMDIFrame::OnWindowPosChanged()\r
+ {\r
+ if (IsMenuBarUsed())\r
+ {\r
+ // Refresh MenuBar Window\r
+ HMENU hMenu= GetMenuBar().GetMenu();\r
+ GetMenuBar().SetMenu(hMenu);\r
+ UpdateCheckMarks();\r
+ }\r
+ }\r
+\r
+ inline BOOL CMDIFrame::PreTranslateMessage(MSG* pMsg)\r
+ {\r
+ if (WM_KEYFIRST <= pMsg->message && pMsg->message <= WM_KEYLAST)\r
+ {\r
+ if (TranslateMDISysAccel(GetView()->GetHwnd(), pMsg))\r
+ return TRUE;\r
+ }\r
+\r
+ return CFrame::PreTranslateMessage(pMsg);\r
+ }\r
+\r
+ inline void CMDIFrame::RecalcLayout()\r
+ {\r
+ CFrame::RecalcLayout();\r
+\r
+ if (GetView()->IsWindow())\r
+ MDIIconArrange();\r
+ }\r
+\r
+ inline BOOL CMDIFrame::RemoveAllMDIChildren()\r
+ {\r
+ BOOL bResult = TRUE;\r
+ int Children = (int)m_vMDIChild.size();\r
+\r
+ // Remove the children in reverse order\r
+ for (int i = Children-1; i >= 0; --i)\r
+ {\r
+ if (IDNO == m_vMDIChild[i]->SendMessage(WM_CLOSE, 0L, 0L)) // Also removes the MDI child\r
+ bResult = FALSE;\r
+ }\r
+\r
+ return bResult;\r
+ }\r
+\r
+ inline void CMDIFrame::RemoveMDIChild(HWND hWnd)\r
+ {\r
+ // Allocate an iterator for our HWND map\r
+ std::vector <MDIChildPtr>::iterator v;\r
+\r
+ for (v = m_vMDIChild.begin(); v!= m_vMDIChild.end(); ++v)\r
+ {\r
+ if ((*v)->GetHwnd() == hWnd)\r
+ {\r
+ m_vMDIChild.erase(v);\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (GetActiveMDIChild())\r
+ {\r
+ if (GetActiveMDIChild()->m_hChildMenu)\r
+ UpdateFrameMenu(GetActiveMDIChild()->m_hChildMenu);\r
+ if (GetActiveMDIChild()->m_hChildAccel)\r
+ GetApp()->SetAccelerators(GetActiveMDIChild()->m_hChildAccel, this);\r
+ }\r
+ else\r
+ {\r
+ if (IsMenuBarUsed())\r
+ GetMenuBar().SetMenu(GetFrameMenu());\r
+ else\r
+ SetMenu(FromHandle(GetFrameMenu()));\r
+\r
+ GetApp()->SetAccelerators(GetFrameAccel(), this);\r
+ }\r
+ }\r
+\r
+ inline void CMDIFrame::SetActiveMDIChild(CMDIChild* pChild)\r
+ {\r
+ assert ( pChild->IsWindow() );\r
+\r
+ GetMDIClient().SendMessage(WM_MDIACTIVATE, (WPARAM)pChild->GetHwnd(), 0L);\r
+\r
+ // Verify\r
+ assert ( m_hActiveMDIChild == pChild->GetHwnd() );\r
+ }\r
+\r
+ inline void CMDIFrame::UpdateCheckMarks()\r
+ {\r
+ if ((GetActiveMDIChild()) && GetActiveMDIChild()->m_hChildMenu)\r
+ {\r
+ HMENU hMenu = GetActiveMDIChild()->m_hChildMenu;\r
+\r
+ UINT uCheck = GetToolBar().IsWindowVisible()? MF_CHECKED : MF_UNCHECKED;\r
+ ::CheckMenuItem(hMenu, IDW_VIEW_TOOLBAR, uCheck);\r
+\r
+ uCheck = GetStatusBar().IsWindowVisible()? MF_CHECKED : MF_UNCHECKED;\r
+ ::CheckMenuItem (hMenu, IDW_VIEW_STATUSBAR, uCheck);\r
+ }\r
+ }\r
+\r
+ inline void CMDIFrame::UpdateFrameMenu(HMENU hMenu)\r
+ {\r
+ int nMenuItems = GetMenuItemCount(hMenu);\r
+ if (nMenuItems > 0)\r
+ {\r
+ // The Window menu is typically second from the right\r
+ int nWindowItem = MAX (nMenuItems -2, 0);\r
+ HMENU hMenuWindow = ::GetSubMenu (hMenu, nWindowItem);\r
+\r
+ if (hMenuWindow)\r
+ {\r
+ if (IsMenuBarUsed())\r
+ {\r
+ AppendMDIMenu(hMenuWindow);\r
+ GetMenuBar().SetMenu(hMenu);\r
+ }\r
+ else\r
+ {\r
+ GetView()->SendMessage (WM_MDISETMENU, (WPARAM) hMenu, (LPARAM)hMenuWindow);\r
+ DrawMenuBar();\r
+ }\r
+ }\r
+ }\r
+ UpdateCheckMarks();\r
+ }\r
+\r
+ inline LRESULT CMDIFrame::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
+ {\r
+ switch (uMsg)\r
+ {\r
+ case WM_CLOSE:\r
+ OnClose();\r
+ return 0;\r
+\r
+ case WM_WINDOWPOSCHANGED:\r
+ // MDI Child or MDI frame has been resized\r
+ OnWindowPosChanged();\r
+ break; // Continue with default processing\r
+\r
+ } // switch uMsg\r
+ return CFrame::WndProcDefault(uMsg, wParam, lParam);\r
+ }\r
+\r
+ inline HWND CMDIFrame::CMDIClient::Create(CWnd* pParent)\r
+ {\r
+ assert(pParent != 0);\r
+\r
+ CLIENTCREATESTRUCT clientcreate ;\r
+ clientcreate.hWindowMenu = m_hWnd;\r
+ clientcreate.idFirstChild = IDW_FIRSTCHILD ;\r
+ DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | MDIS_ALLCHILDSTYLES;\r
+\r
+ // Create the view window\r
+ CreateEx(WS_EX_CLIENTEDGE, _T("MDICLient"), TEXT(""), dwStyle, 0, 0, 0, 0, pParent, NULL, (PSTR) &clientcreate);\r
+\r
+ return m_hWnd;\r
+ }\r
+\r
+ inline LRESULT CMDIFrame::CMDIClient::WndProc(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
+ {\r
+ switch (uMsg)\r
+ {\r
+ case WM_MDIDESTROY:\r
+ {\r
+ // Do default processing first\r
+ CallWindowProc(GetPrevWindowProc(), uMsg, wParam, lParam);\r
+\r
+ // Now remove MDI child\r
+ GetMDIFrame()->RemoveMDIChild((HWND) wParam);\r
+ }\r
+ return 0; // Discard message\r
+\r
+ case WM_MDISETMENU:\r
+ {\r
+ if (GetMDIFrame()->IsMenuBarUsed())\r
+ {\r
+ return 0L;\r
+ }\r
+ }\r
+ break;\r
+\r
+ case WM_MDIACTIVATE:\r
+ {\r
+ // Suppress redraw to avoid flicker when activating maximised MDI children\r
+ SendMessage(WM_SETREDRAW, FALSE, 0L);\r
+ LRESULT lr = CallWindowProc(GetPrevWindowProc(), WM_MDIACTIVATE, wParam, lParam);\r
+ SendMessage(WM_SETREDRAW, TRUE, 0L);\r
+ RedrawWindow(0, 0, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);\r
+\r
+ return lr;\r
+ }\r
+ }\r
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
+ }\r
+\r
+\r
+ /////////////////////////////////////\r
+ //Definitions for the CMDIChild class\r
+ //\r
+ inline CMDIChild::CMDIChild() : m_pView(NULL), m_hChildMenu(NULL)\r
+ {\r
+ // Set the MDI Child's menu and accelerator in the constructor, like this ...\r
+ // HMENU hChildMenu = LoadMenu(GetApp()->GetResourceHandle(), _T("MdiMenuView"));\r
+ // HACCEL hChildAccel = LoadAccelerators(GetApp()->GetResourceHandle(), _T("MDIAccelView"));\r
+ // SetHandles(hChildMenu, hChildAccel);\r
+ }\r
+\r
+ inline CMDIChild::~CMDIChild()\r
+ {\r
+ if (IsWindow())\r
+ GetParent()->SendMessage(WM_MDIDESTROY, (WPARAM)m_hWnd, 0L);\r
+\r
+ if (m_hChildMenu)\r
+ ::DestroyMenu(m_hChildMenu);\r
+ }\r
+\r
+ inline HWND CMDIChild::Create(CWnd* pParent /*= NULL*/)\r
+ // We create the MDI child window and then maximize if required.\r
+ // This technique avoids unnecessary flicker when creating maximized MDI children.\r
+ {\r
+ //Call PreCreate in case its overloaded\r
+ PreCreate(*m_pcs);\r
+\r
+ //Determine if the window should be created maximized\r
+ BOOL bMax = FALSE;\r
+ pParent->SendMessage(WM_MDIGETACTIVE, 0L, (LPARAM)&bMax);\r
+ bMax = bMax | (m_pcs->style & WS_MAXIMIZE);\r
+\r
+ // Set the Window Class Name\r
+ TCHAR szClassName[MAX_STRING_SIZE + 1] = _T("Win32++ MDI Child");\r
+ if (m_pcs->lpszClass)\r
+ lstrcpyn(szClassName, m_pcs->lpszClass, MAX_STRING_SIZE);\r
+\r
+ // Set the window style\r
+ DWORD dwStyle;\r
+ dwStyle = m_pcs->style & ~WS_MAXIMIZE;\r
+ dwStyle |= WS_VISIBLE | WS_OVERLAPPEDWINDOW ;\r
+\r
+ // Set window size and position\r
+ int x = CW_USEDEFAULT;\r
+ int y = CW_USEDEFAULT;\r
+ int cx = CW_USEDEFAULT;\r
+ int cy = CW_USEDEFAULT;\r
+ if(m_pcs->cx && m_pcs->cy)\r
+ {\r
+ x = m_pcs->x;\r
+ y = m_pcs->y;\r
+ cx = m_pcs->cx;\r
+ cy = m_pcs->cy;\r
+ }\r
+\r
+ // Set the extended style\r
+ DWORD dwExStyle = m_pcs->dwExStyle | WS_EX_MDICHILD;\r
+\r
+ // Turn off redraw while creating the window\r
+ pParent->SendMessage(WM_SETREDRAW, FALSE, 0L);\r
+\r
+ // Create the window\r
+ if (!CreateEx(dwExStyle, szClassName, m_pcs->lpszName, dwStyle, x, y,\r
+ cx, cy, pParent, FromHandle(m_pcs->hMenu), m_pcs->lpCreateParams))\r
+ throw CWinException(_T("CMDIChild::Create ... CreateEx failed"));\r
+\r
+ if (bMax)\r
+ ShowWindow(SW_MAXIMIZE);\r
+\r
+ // Turn redraw back on\r
+ pParent->SendMessage(WM_SETREDRAW, TRUE, 0L);\r
+ pParent->RedrawWindow(NULL, NULL, RDW_INVALIDATE | RDW_ALLCHILDREN);\r
+\r
+ // Ensure bits revealed by round corners (XP themes) are redrawn\r
+ SetWindowPos(NULL, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_FRAMECHANGED);\r
+\r
+ if (m_hChildMenu)\r
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);\r
+ if (m_hChildAccel)\r
+ GetApp()->SetAccelerators(m_hChildAccel, this);\r
+\r
+ return m_hWnd;\r
+ }\r
+\r
+ inline CMDIFrame* CMDIChild::GetMDIFrame() const\r
+ {\r
+ CMDIFrame* pMDIFrame = (CMDIFrame*)GetParent()->GetParent();\r
+ assert(dynamic_cast<CMDIFrame*>(pMDIFrame));\r
+ return pMDIFrame;\r
+ }\r
+\r
+ inline LRESULT CMDIChild::FinalWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
+ {\r
+ return ::DefMDIChildProc(m_hWnd, uMsg, wParam, lParam);\r
+ }\r
+\r
+ inline void CMDIChild::MDIActivate() const\r
+ {\r
+ GetParent()->SendMessage(WM_MDIACTIVATE, (WPARAM)m_hWnd, 0L);\r
+ }\r
+\r
+ inline void CMDIChild::MDIDestroy() const\r
+ {\r
+ GetParent()->SendMessage(WM_MDIDESTROY, (WPARAM)m_hWnd, 0L);\r
+ }\r
+\r
+ inline void CMDIChild::MDIMaximize() const\r
+ {\r
+ GetParent()->SendMessage(WM_MDIMAXIMIZE, (WPARAM)m_hWnd, 0L);\r
+ }\r
+\r
+ inline void CMDIChild::MDIRestore() const\r
+ {\r
+ GetParent()->SendMessage(WM_MDIRESTORE, (WPARAM)m_hWnd, 0L);\r
+ }\r
+\r
+ inline void CMDIChild::OnCreate()\r
+ {\r
+ // Create the view window\r
+ assert(GetView()); // Use SetView in CMDIChild's constructor to set the view window\r
+ GetView()->Create(this);\r
+ RecalcLayout();\r
+ }\r
+\r
+ inline void CMDIChild::RecalcLayout()\r
+ {\r
+ // Resize the View window\r
+ CRect rc = GetClientRect();\r
+ m_pView->SetWindowPos( NULL, rc.left, rc.top, rc.Width(), rc.Height(), SWP_SHOWWINDOW );\r
+ }\r
+\r
+ inline void CMDIChild::SetHandles(HMENU hMenu, HACCEL hAccel)\r
+ {\r
+ m_hChildMenu = hMenu;\r
+ m_hChildAccel = hAccel;\r
+\r
+ // Note: It is valid to call SetChildMenu before the window is created\r
+ if (IsWindow())\r
+ {\r
+ CWnd* pWnd = GetMDIFrame()->GetActiveMDIChild();\r
+ if (pWnd == this)\r
+ {\r
+ if (m_hChildMenu)\r
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);\r
+\r
+ if (m_hChildAccel)\r
+ GetApp()->SetAccelerators(m_hChildAccel, GetMDIFrame());\r
+ }\r
+ }\r
+ }\r
+\r
+ inline void CMDIChild::SetView(CWnd& wndView)\r
+ // Sets or changes the View window displayed within the frame\r
+ {\r
+ if (m_pView != &wndView)\r
+ {\r
+ // Destroy the existing view window (if any)\r
+ if (m_pView) m_pView->Destroy();\r
+\r
+ // Assign the view window\r
+ m_pView = &wndView;\r
+\r
+ if (m_hWnd)\r
+ {\r
+ // The frame is already created, so create and position the new view too\r
+ assert(GetView()); // Use SetView in CMDIChild's constructor to set the view window\r
+ GetView()->Create(this);\r
+ RecalcLayout();\r
+ }\r
+ }\r
+ }\r
+\r
+ inline LRESULT CMDIChild::WndProcDefault(UINT uMsg, WPARAM wParam, LPARAM lParam)\r
+ {\r
+ switch (uMsg)\r
+ {\r
+ case WM_MDIACTIVATE:\r
+ {\r
+ // This child is being activated\r
+ if (lParam == (LPARAM) m_hWnd)\r
+ {\r
+ GetMDIFrame()->m_hActiveMDIChild = m_hWnd;\r
+ // Set the menu to child default menu\r
+ if (m_hChildMenu)\r
+ GetMDIFrame()->UpdateFrameMenu(m_hChildMenu);\r
+ if (m_hChildAccel)\r
+ GetApp()->SetAccelerators(m_hChildAccel, this);\r
+ }\r
+\r
+ // No child is being activated\r
+ if (0 == lParam)\r
+ {\r
+ GetMDIFrame()->m_hActiveMDIChild = NULL;\r
+ // Set the menu to frame's original menu\r
+ GetMDIFrame()->UpdateFrameMenu(GetMDIFrame()->GetFrameMenu());\r
+ GetApp()->SetAccelerators(GetMDIFrame()->GetFrameAccel(), this);\r
+ }\r
+ }\r
+ return 0L ;\r
+\r
+ case WM_WINDOWPOSCHANGED:\r
+ {\r
+ RecalcLayout();\r
+ break;\r
+ }\r
+ }\r
+ return CWnd::WndProcDefault(uMsg, wParam, lParam);\r
+ }\r
+\r
+\r
+} // namespace Win32xx\r
+\r
+#endif // _WIN32XX_MDI_H_\r
+\r