⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tabbedmdi.cpp

📁 These listed libraries are written in WTL. But it s really hard to mix both MFC & WTL together. Obvi
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include "stdafx.h"
#include "TabbedMDI.h"
#include <afxpriv.h>

using namespace WTL4MFC;
using namespace WTL::DockSplitTab;

IMPLEMENT_DYNCREATE(CTabbedMDIFrameWnd, CDockingMDIFrameWnd)

BEGIN_MESSAGE_MAP(CTabbedMDIFrameWnd, CDockingMDIFrameWnd)
	ON_UPDATE_COMMAND_UI_RANGE(ID_WINDOW_ARRANGE, ID_WINDOW_TILE_VERT, & CTabbedMDIFrameWnd::OnUpdateMDIWindowCmd)
END_MESSAGE_MAP()

void CTabbedMDIFrameWnd::OnUpdateMDIWindowCmd(CCmdUI* pCmdUI)
{
	// We don't want handling for MDI commands
	pCmdUI->Enable(FALSE);
}

HMENU CTabbedMDIFrameWnd::GetWindowMenuPopup(HMENU hMenuBar)
{
	int iCount = ::GetMenuItemCount(hMenuBar);

	// In a standard MDI menu, "Window" & "Help" are the 2 last sub-menus
	return (iCount >= 2)? ::GetSubMenu(hMenuBar, iCount-2) : NULL;
}

BOOL CTabbedMDIFrameWnd::PreTranslateMessage(MSG* pMsg)
{
	if(WM_COMMAND == pMsg->message)
	{
		// menu or accelerator within range of MDI children
		ASSERT(AFX_IDM_FIRST_MDICHILD == 0xFF00);
		if( (pMsg->lParam == NULL) && ((LOWORD(pMsg->wParam) & 0xf000) == 0xf000) )
		{
			m_wndMDIClient.SetActiveChildByMenuId(LOWORD(pMsg->wParam));
			return TRUE;
		}
	}
	else if	(WM_KEYDOWN == pMsg->message)
	{
		if(__super::PreTranslateMessage(pMsg))
		{
			// This message is handled by __super, should return immediately
			return TRUE;
		}

		if(	(pMsg->wParam == VK_F6) &&
			(GetKeyState(VK_CONTROL) < 0) &&			// Ctrl-F6
			(m_wndMDIClient.GetChildCount() > 1) &&		// More than one MDI child
			(NULL == this->GetActiveView()) )			// Still in MDI mode
		{
			::SendMessage(m_hWndMDIClient, WM_MDINEXT, NULL, (GetKeyState(VK_SHIFT) < 0) );
			return TRUE;
		}
		else if( (pMsg->wParam == VK_F4) &&
			(GetKeyState(VK_CONTROL) < 0) &&			// Ctrl-F4
			(m_wndMDIClient.GetChildCount() > 0) &&		// At least one 
			(NULL == this->GetActiveView()) )			// Still in MDI mode
		{
			CMDIChildWnd* pWnd = MDIGetActive();
			ASSERT_KINDOF(CTabbedMDIChildWnd, pWnd);
			pWnd->SendMessage(WM_CLOSE, 0, 0);
			return TRUE;
		}

		return FALSE;
	}
	return __super::PreTranslateMessage(pMsg);
}

// virtual
BOOL CTabbedMDIFrameWnd::CreateClient(LPCREATESTRUCT lpCreateStruct, CMenu* pWindowMenu)
{
	ASSERT(NULL == m_hWndMDIClient);

	class CMDICreationHookWnd : public CWnd
	{
		CMDIClientHooker* m_pMDIClientWithSplitter;
		virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
		{
			// This is the first message
			ASSERT(WM_NCCREATE == message);

			// Un-subclassing
			HWND hWnd = this->UnsubclassWindow();
			CWindow(hWnd).ModifyStyleEx(WS_EX_CLIENTEDGE, 0, SWP_FRAMECHANGED);
			m_pMDIClientWithSplitter->SubclassWindow(hWnd);

			// Modify style and forward message to WTL library
			return ::SendMessage(hWnd, message, wParam, lParam);
		}

	public:
		CMDICreationHookWnd(CMDIClientHooker* pMDIClientWithSplitter)
			: m_pMDIClientWithSplitter(pMDIClientWithSplitter)
		{
		}
	};

	CMDICreationHookWnd wndHooker(&this->m_wndMDIClient);
	AfxHookWindowCreate(&wndHooker);
	return __super::CreateClient(lpCreateStruct, pWindowMenu);
}

//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(CTabbedMDIChildWnd, CMDIChildWnd)

BEGIN_MESSAGE_MAP(CTabbedMDIChildWnd, CMDIChildWnd)
	ON_WM_WINDOWPOSCHANGING()
	ON_WM_SIZE()
	ON_WM_MOUSEACTIVATE()
	ON_WM_DESTROY()
	ON_WM_MDIACTIVATE()
	ON_WM_NCCREATE()
	ON_MESSAGE(WM_SETTEXT, OnSetText)
END_MESSAGE_MAP()

CTabbedMDIChildWnd::CTabbedMDIChildWnd()
: m_blInChangeParent(FALSE)
, m_hWndMDIClient(NULL)
{
}

HWND CTabbedMDIChildWnd::ChangeParent(HWND hWndNewParent)
{
	m_blInChangeParent = TRUE;
	HWND hWndOldParent = (HWND) ::SetWindowLongPtr(m_hWnd,
		GWLP_HWNDPARENT, (LONG_PTR) hWndNewParent);
	m_blInChangeParent = FALSE;

	return hWndOldParent;
}

LRESULT CTabbedMDIChildWnd::WindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	return (m_blInChangeParent)? 0 : __super::WindowProc(nMsg, wParam, lParam);
}

LRESULT CTabbedMDIChildWnd::DefWindowProc(UINT nMsg, WPARAM wParam, LPARAM lParam)
{
	return ::DefWindowProc(m_hWnd, nMsg, wParam, lParam);
}

BOOL CTabbedMDIChildWnd::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (!__super::OnNcCreate(lpCreateStruct))
		return FALSE;

	// Keep the MDI client for later use
	m_hWndMDIClient = ::GetParent(m_hWnd);
	return TRUE;
}

void CTabbedMDIChildWnd::OnWindowPosChanging(WINDOWPOS* lpwndpos)
{
	// Skip behavior of CMDIChildWnd class
	::DefWindowProc(m_hWnd, WM_WINDOWPOSCHANGING, 0, (LPARAM) lpwndpos);
}

void CTabbedMDIChildWnd::OnSize(UINT nType, int cx, int cy)
{
	// Trick: Change its parent temporarily
	HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
	__super::OnSize(nType, cx, cy);
	ChangeParent(hWndOldParent);
}

void CTabbedMDIChildWnd::OnDestroy()
{
	// Skip behavior of CMDIChildWnd class
	// Otherwise, we will meet a lot of trouble :-(
	CFrameWnd::OnDestroy();
}

CWnd* CTabbedMDIChildWnd::GetMessageBar()
{
	CFrameWnd* pFrameWnd = (CFrameWnd*) CWnd::FromHandlePermanent(::GetParent((HWND)m_hWndMDIClient));
	ASSERT_KINDOF(CFrameWnd, pFrameWnd);
	return pFrameWnd->GetMessageBar();
}

void CTabbedMDIChildWnd::ActivateFrame(int nCmdShow)
{
	// Trick: Change its parent temporarily
	HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
	__super::ActivateFrame(SW_NORMAL);
	ChangeParent(hWndOldParent);
}

void CTabbedMDIChildWnd::OnUpdateFrameTitle(BOOL bAddToTitle)
{
	// Trick: Change its parent temporarily
	HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
	__super::OnUpdateFrameTitle(bAddToTitle);
	ChangeParent(hWndOldParent);
}

void CTabbedMDIChildWnd::OnUpdateFrameMenu(BOOL bActive, CWnd* pActivateWnd, HMENU hMenuAlt)
{
	// Trick: Change its parent temporarily
	HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
	__super::OnUpdateFrameMenu(bActive, pActivateWnd, hMenuAlt);
	ChangeParent(hWndOldParent);
}

int CTabbedMDIChildWnd::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message)
{
	int nResult = CFrameWnd::OnMouseActivate(pDesktopWnd, nHitTest, message);
	if( (nResult != MA_NOACTIVATE) && (nResult == MA_NOACTIVATEANDEAT) )
	{
		// frame want to activate so activate this window
		::SendMessage((HWND) m_hWndMDIClient, WM_MDIACTIVATE, (WPARAM) m_hWnd, 0);
	}
	return nResult;
}

void CTabbedMDIChildWnd::OnMDIActivate(BOOL bActivate, CWnd* pActivateWnd, CWnd* pDeactivateWnd)
{
	// Trick: Change its parent temporarily
	HWND hWndOldParent = ChangeParent(m_hWndMDIClient);
	__super::OnMDIActivate(bActivate, pActivateWnd, pDeactivateWnd);
	ChangeParent(hWndOldParent);
}

BOOL CTabbedMDIChildWnd::DestroyWindow()
{
	ChangeParent(m_hWndMDIClient);
	return __super::DestroyWindow();
}

LRESULT CTabbedMDIChildWnd::OnSetText(WPARAM, LPARAM lParam)
{
	LPCTSTR szWindowText = (LPCTSTR) lParam;
	LRESULT lRes = Default();
	::SendMessage((HWND) m_hWndMDIClient, WM_SETTEXT, (WPARAM) m_hWnd, lParam);
	return lRes;
}

void CTabbedMDIFrameWnd::CMDIClientHooker::ClearMenu()
{
	if(m_hSubMenu)
	{
		// Clear the menu
		ASSERT(::IsMenu(m_hSubMenu));
		for(int i = GetMenuItemCount(m_hSubMenu)-m_iOriginalMenuItemCount;
			i > 0; --i)
		{
			VERIFY(DeleteMenu(m_hSubMenu, m_iOriginalMenuItemCount, MF_BYPOSITION));
		}
	}
}

void CTabbedMDIFrameWnd::CMDIClientHooker::RefreshMenu()
{
	if(NULL == m_hSubMenu)
	{
		return;
	}
	ClearMenu();

	CString strWindowText;
	CString strMenuText;
	CMenu menu;
	menu.Attach(m_hSubMenu);

	// Add or remove a separator if needed
	if(m_iOriginalMenuItemCount > 0)
	{
		if (0  != menu.GetMenuItemID(m_iOriginalMenuItemCount - 1))
		{
			menu.AppendMenu(MF_SEPARATOR);
		}
		else if(m_iOriginalMenuItemCount == 1)
		{
			// Remove the separator
			m_iOriginalMenuItemCount = 0;
			menu.RemoveMenu(0, MF_BYPOSITION);
		}
	}

	for(size_t i=0; i<m_ZOrder.size(); ++i)
	{
		HWND hWndChild = m_ZOrder[i];
		ASSERT(::IsWindow(hWndChild));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -