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

📄 tabbedmdi.h

📁 一款最完整的工业组态软源代码
💻 H
📖 第 1 页 / 共 5 页
字号:
	}

	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		DestroyTabWindow();

		// Say that we didn't handle it so that anyone else
		//  interested gets to handle the message
		bHandled = FALSE;
		return 0;
	}

	LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		if(m_TabCtrl)
		{
			// Let the tabs do all the drawing as flicker-free as possible
			return 1;
		}

		bHandled = FALSE;
		return 0;
	}

	LRESULT OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		RECT rect = {0};
		GetClientRect(&rect);

		m_TabCtrl.SetWindowPos(NULL, &rect, SWP_NOZORDER | SWP_NOACTIVATE);
		m_TabCtrl.UpdateLayout();

		bHandled = TRUE;

		return 0;
	}

	LRESULT OnContextMenu(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = TRUE;

		int nIndex = -1;

		POINT ptPopup = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
		if(ptPopup.x == -1 && ptPopup.y == -1)
		{
			nIndex = m_TabCtrl.GetCurSel();
			RECT rect = {0};
			if(nIndex >= 0)
			{
				// If there is a selected item, popup the menu under the node,
				// if not, pop it up in the top left of the tree view
				m_TabCtrl.GetItemRect(nIndex, &rect);
			}
			::MapWindowPoints(m_hWnd, NULL, (LPPOINT)&rect, 2);
			ptPopup.x = rect.left;
			ptPopup.y = rect.bottom;
		}
		else
		{
			POINT ptClient = ptPopup;
			::MapWindowPoints(NULL, m_hWnd, &ptClient, 1);
			CTCHITTESTINFO tchti = { 0 };
			tchti.pt = ptClient;
			//If we become templated, pT->HitTest(&tchti);
			nIndex = m_TabCtrl.HitTest(&tchti);
		}

		if( nIndex >= 0 )
		{
			TTabCtrl::TItem* pItem = m_TabCtrl.GetItem(nIndex);

			HWND hWndChild = pItem->GetTabView();
			if(hWndChild != NULL)
			{
				::SendMessage(hWndChild, UWM_MDICHILDSHOWTABCONTEXTMENU, wParam, MAKELPARAM(ptPopup.x, ptPopup.y));
			}
		}

		return 0;
	}

	LRESULT OnClick(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
	{
		// If they left click on an item, set focus on the tab view,
		// but only if the view was already the active tab view
		// (otherwise our code to reduce flicker when switching
		// MDI children when maximized doesn't kick in).
		NMCTCITEM* item = (NMCTCITEM*)pnmh;
		if(item && (item->iItem >= 0) && (item->iItem == m_TabCtrl.GetCurSel()))
		{
			TTabCtrl::TItem* pItem = m_TabCtrl.GetItem(item->iItem);
			if(pItem->UsingTabView())
			{
				::SetFocus(pItem->GetTabView());
			}
		}

		bHandled = FALSE;
		return 0;
	}

	LRESULT OnAcceptItemDrag(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
	{
		// If finished dragging, set focus on the tab view.
		NMCTC2ITEMS* item = (NMCTC2ITEMS*)pnmh;
		if(item && (item->iItem2 >= 0))
		{
			TTabCtrl::TItem* pItem = m_TabCtrl.GetItem(item->iItem2);
			if(pItem->UsingTabView())
			{
				::SetFocus(pItem->GetTabView());
			}
		}

		bHandled = FALSE;
		return 0;
	}

	LRESULT OnCancelItemDrag(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
	{
		// If finished dragging, set focus on the tab view.
		NMCTCITEM* item = (NMCTCITEM*)pnmh;
		if(item && (item->iItem >= 0))
		{
			TTabCtrl::TItem* pItem = m_TabCtrl.GetItem(item->iItem);
			if(pItem->UsingTabView())
			{
				::SetFocus(pItem->GetTabView());
			}
		}

		bHandled = FALSE;
		return 0;
	}

	LRESULT OnDeleteItem(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& bHandled)
	{
		bHandled = FALSE;
		return 0;
	}

	LRESULT OnSelChanging(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& bHandled)
	{
		bHandled = FALSE;
		return 0;
	}

	LRESULT OnSelChange(int /*idCtrl*/, LPNMHDR /*pnmh*/, BOOL& bHandled)
	{
		int nNewTab = m_TabCtrl.GetCurSel();

		if(nNewTab >= 0)
		{
			TTabCtrl::TItem* pItem = m_TabCtrl.GetItem(nNewTab);
			if(pItem->UsingTabView())
			{
				HWND hWndNew = pItem->GetTabView();
				HWND hWndOld = (HWND)::SendMessage(m_hWndMDIClient, WM_MDIGETACTIVE, 0, NULL);
				if( hWndNew != hWndOld )
				{
					// We don't want any flickering when switching the active child
					//  when the child is maximized (when its not maximized, there's no flicker).
					//  There's probably more than one way to do this, but how we do
					//  it is to turn off redrawing for the MDI client window,
					//  activate the new child window, turn redrawing back on for
					//  the MDI client window, and force a redraw (not just a simple
					//  InvalidateRect, but an actual RedrawWindow to include
					//  all the child windows ).
					//  It might be nice to just turn off/on drawing for the window(s)
					//  that need it, but if you watch the messages in Spy++,
					//  the default implementation of the MDI client is forcing drawing
					//  to be on for the child windows involved.  Turning drawing off
					//  for the MDI client window itself seems to solve this problem.
					//

					LRESULT nResult = 0;

					WINDOWPLACEMENT wpOld = {0};
					wpOld.length = sizeof(WINDOWPLACEMENT);
					::GetWindowPlacement(hWndOld, &wpOld);
					if(wpOld.showCmd == SW_SHOWMAXIMIZED)
					{
						nResult = ::SendMessage(m_hWndMDIClient, WM_SETREDRAW, FALSE, 0);
					}

					nResult = ::SendMessage(m_hWndMDIClient, WM_MDIACTIVATE, (LPARAM)hWndNew, 0);

					WINDOWPLACEMENT wpNew = {0};
					wpNew.length = sizeof(WINDOWPLACEMENT);
					::GetWindowPlacement(hWndNew, &wpNew);
					if(wpNew.showCmd == SW_SHOWMINIMIZED)
					{
						::ShowWindow(hWndNew, SW_RESTORE);
					}

					if(wpOld.showCmd == SW_SHOWMAXIMIZED)
					{
						nResult = ::SendMessage(m_hWndMDIClient, WM_SETREDRAW, TRUE, 0);
						::RedrawWindow(m_hWndMDIClient, NULL, NULL,
							//A little more forceful if necessary: RDW_ERASE | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN);
							RDW_INVALIDATE | RDW_ALLCHILDREN);
					}
				}
			}
		}

		bHandled = FALSE;
		return 0;
	}

	LRESULT OnTabClose(int /*idCtrl*/, LPNMHDR pnmh, BOOL& bHandled)
	{
		LPNMCTCITEM pnmCustomTab = (LPNMCTCITEM)pnmh;
		if(pnmCustomTab)
		{
			if(pnmCustomTab->iItem >= 0)
			{
				TTabCtrl::TItem* pItem = m_TabCtrl.GetItem(pnmCustomTab->iItem);
				if(pItem)
				{
					::PostMessage(pItem->GetTabView(), WM_SYSCOMMAND, SC_CLOSE, 0L);
				}
			}
		}
		bHandled = FALSE;
		return 0;
	}

// Overrides from CCustomTabOwnerImpl
public:

	void OnAddFirstTab()
	{
		if(this->IsWindowVisible() == FALSE)
		{
			RECT rcMDIClient;
			::GetWindowRect(m_hWndMDIClient, &rcMDIClient);
			::MapWindowPoints(NULL, ::GetParent(m_hWndMDIClient), (LPPOINT)&rcMDIClient, 2);

			this->ShowWindow(SW_SHOW);

			// the MDI client resizes and shows our window when
			//  handling messages related to SetWindowPos
			::SetWindowPos(
				m_hWndMDIClient, NULL,
				rcMDIClient.left, rcMDIClient.top,
				(rcMDIClient.right - rcMDIClient.left),(rcMDIClient.bottom - rcMDIClient.top),
				SWP_NOZORDER);
		}

		customTabOwnerClass::OnAddFirstTab();
	}

	void OnRemoveLastTab()
	{
		if(this->IsWindowVisible() == TRUE)
		{
			RECT rcTabs;
			m_TabCtrl.GetWindowRect(&rcTabs);
			::MapWindowPoints(NULL, m_TabCtrl.GetParent(), (LPPOINT)&rcTabs, 2);

			this->ShowWindow(SW_HIDE);

			RECT rcMDIClient;
			::GetWindowRect(m_hWndMDIClient, &rcMDIClient);
			::MapWindowPoints(NULL, ::GetParent(m_hWndMDIClient), (LPPOINT)&rcMDIClient, 2);

			// the MDI client resizes and shows our window when
			//  handling messages related to SetWindowPos

			// TODO: Is there a better way to do this?
			//  We're basically hiding the tabs and
			//  resizing the MDI client area to "cover up"
			//  where the tabs were
			DWORD dwStyle = m_TabCtrl.GetStyle();
			if(CTCS_BOTTOM == (dwStyle & CTCS_BOTTOM))
			{
				::SetWindowPos(
					m_hWndMDIClient, NULL,
					rcMDIClient.left, rcMDIClient.top,
					(rcMDIClient.right - rcMDIClient.left),
					(rcMDIClient.bottom - rcMDIClient.top) + (rcTabs.bottom - rcTabs.top),
					SWP_NOZORDER);
			}
			else
			{
				::SetWindowPos(
					m_hWndMDIClient, NULL,
					rcMDIClient.left, rcMDIClient.top - (rcTabs.bottom - rcTabs.top),
					(rcMDIClient.right - rcMDIClient.left),
					(rcMDIClient.bottom - rcMDIClient.top) + (rcTabs.bottom - rcTabs.top),
					SWP_NOZORDER);
			}
		}

		customTabOwnerClass::OnRemoveLastTab();
	}

	void SetTabAreaHeight(int nNewTabAreaHeight)
	{
		if(m_bKeepTabsHidden)
		{
			m_nTabAreaHeight = 0;
		}
		else if(m_nTabAreaHeight != nNewTabAreaHeight)
		{
			int nOldTabAreaHeight = m_nTabAreaHeight;

			m_nTabAreaHeight = nNewTabAreaHeight;

			//T* pT = static_cast<T*>(this);
			//pT->UpdateLayout();
			//Invalidate();

			if(this->IsWindowVisible() == TRUE)
			{

				RECT rcMDIClient;
				::GetWindowRect(m_hWndMDIClient, &rcMDIClient);
				::MapWindowPoints(NULL, this->GetParent(), (LPPOINT)&rcMDIClient, 2);

				// Don't ask me why these two lines are necessary.
				// Take these lines out if you want to
				// convince yourself that they are :-)
				rcMDIClient.top -= nOldTabAreaHeight;
				rcMDIClient.bottom += nOldTabAreaHeight;

				// The tab resize/reposition logic happens when handling WM_WINDOWPOSCHANGING.
				// If that ever changes, make the appropriate change here.
				::SetWindowPos(
					m_hWndMDIClient, NULL,
					rcMDIClient.left, rcMDIClient.top,
					(rcMDIClient.right - rcMDIClient.left),(rcMDIClient.bottom - rcMDIClient.top),
					SWP_NOZORDER | SWP_NOACTIVATE);
			}
		}
	}
};

template< class TTabCtrl >
class CMDITabOwner :
	public CMDITabOwnerImpl<CMDITabOwner, TTabCtrl>
{
};

/////////////////////////////////////////////////////////////////////////////
//
// CTabbedMDIClient
//
/////////////////////////////////////////////////////////////////////////////

template< class TTabCtrl = CDotNetTabCtrl<CTabViewTabItem>, class TTabOwner = CMDITabOwner<TTabCtrl> >
class CTabbedMDIClient : public CWindowImpl<CTabbedMDIClient, CWindow>
{
public:
	// Expose the type of tab control and tab owner
	typedef typename TTabCtrl TTabCtrl;
	typedef typename TTabOwner TTabOwner;

protected:
	typedef CWindowImpl<CTabbedMDIClient, CWindow> baseClass;
	typedef CTabbedMDIClient< TTabCtrl, TTabOwner > thisClass;

// Member variables
protected:
	HWND m_hWndTabOwnerParent;
	TTabOwner m_MdiTabOwner;
	BOOL m_bUseMDIChildIcon;
	BOOL m_bHideMDITabsWhenMDIChildNotMaximized;
	bool m_bSubclassed;
	bool m_bDrawFlat;

// Constructors
public:
	CTabbedMDIClient() :
		m_hWndTabOwnerParent(NULL),
		m_bUseMDIChildIcon(FALSE),
		m_bHideMDITabsWhenMDIChildNotMaximized(FALSE),
		m_bSubclassed(false),
		m_bDrawFlat(false)
	{
		ATLASSERT(UWM_MDICHILDACTIVATIONCHANGE != 0 && "The TabbedMDI Messages didn't get registered properly");
		if(m_bDrawFlat)
		{
			m_MdiTabOwner.ModifyTabStyles(0,CTCS_FLATEDGE);
		}
	}

	virtual ~CTabbedMDIClient()
	{
		if(this->IsWindow() && m_bSubclassed)
		{
			this->UnsubclassWindow(TRUE);
		}
	}

// Methods

⌨️ 快捷键说明

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