dockmanager.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 802 行 · 第 1/2 页

CPP
802
字号
// DockManager.cpp: implementation of the CDockManager class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DockManager.h"
#include "holdredraw.h"
#include "autoflag.h"

#include <multimon.h>

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

const int MINMAXSIZE = GetSystemMetrics(SM_CYCAPTION) * 4;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CDockManager::CDockManager() : 
	m_nDockPos(DMP_UNDOCKED), 
	m_nLastDockPos(DMP_RIGHT),
	m_nWidthDocked(-1), 
	m_nWidthDockedMax(-1), 
	m_nHeightDocked(-1), 
	m_nHeightDockedMax(-1), 
	m_bResizeUpdate(TRUE),
	m_bSizeUpdate(TRUE),
	m_sizeMainMin(-1, -1),
	m_sizeDockMin(-1, -1)
{

}

CDockManager::~CDockManager()
{

}

BOOL CDockManager::Initialize(CWnd* pMainWnd, CWnd* pDockWnd, 
							  DM_POS nPos, DM_POS nLastPos,
							  int nWidthDocked, int nWidthDockedMax,
							  int nHeightDocked, int nHeightDockedMax)
{
	if (!HookWindow(*pMainWnd) || !ScHookWindow(*pDockWnd))
		return FALSE;

	m_nLastDockPos = nLastPos;
	m_nWidthDocked = nWidthDocked;
	m_nWidthDockedMax = nWidthDockedMax;
	m_nHeightDocked = nHeightDocked;
	m_nHeightDockedMax = nHeightDockedMax;

	return Dock(nPos);
}

BOOL CDockManager::Dock(DM_POS nPos)
{
	if (nPos == DMP_UNDOCKED)
		return UnDock();

	if (IsDocked() && m_nDockPos == nPos)
		return TRUE;

	BOOL bDocked = IsDocked();
	m_nDockPos = nPos;

	CRect rDock;
	ScGetCWnd()->GetWindowRect(rDock);

	// save window pos if not currently docked
	if (!bDocked)
		m_rUndocked = rDock;
	
	// and restore previous width
	if (nPos == DMP_BELOW)
	{
		int nHeight = GetDockedHeight(Maximized());
		
		if (nHeight != -1)
		{
			rDock.bottom = rDock.top + nHeight;

			CAutoFlag af(m_bResizeUpdate, FALSE);
			CAutoFlag af2(m_bSizeUpdate, FALSE);
			MoveWindow(ScGetCWnd(), rDock);
		}
	}
	else
	{
		int nWidth = GetDockedWidth(Maximized());
		
		if (nWidth != -1)
		{
			rDock.right = rDock.left + nWidth;

			CAutoFlag af(m_bResizeUpdate, FALSE);
			CAutoFlag af2(m_bSizeUpdate, FALSE);
			MoveWindow(ScGetCWnd(), rDock);
		}
	}

	// also restore main window pos if maximized
	if (Maximized())
		OnMaximize();
	else
		UpdateDockWindowPos();

	return TRUE;
}

BOOL CDockManager::UnDock()
{
	if (!IsDocked())
		return TRUE;

	m_nLastDockPos = m_nDockPos;
	m_nDockPos = DMP_UNDOCKED;

	// restore window pos
	ScGetCWnd()->MoveWindow(m_rUndocked);

	// also restore main window pos if maximized
	if (Maximized())
		OnMaximize();

	return TRUE;
}

LRESULT CDockManager::WindowProc(HWND /*hRealWnd*/, UINT msg, WPARAM wp, LPARAM lp)
{
	if (!IsDocked())
		return Default();

	switch (msg)
	{
	case WM_MOVE:
		{
			LRESULT lr = Default();

			if (m_bResizeUpdate)
				UpdateDockWindowPos();

			return lr;
		}
		break;

	case WM_SIZE:
		{
			LRESULT lr = Default();

			if (m_bResizeUpdate)
				UpdateDockWindowPos();

			return lr;
		}
		break;

	case WM_SYSCOMMAND:
		if (wp == SC_MAXIMIZE || wp == SC_RESTORE)
		{
			CAutoFlag af(m_bResizeUpdate, FALSE);
			LRESULT lr = Default();

			if (wp == SC_MAXIMIZE)
				OnMaximize();
			else
				OnRestore();
			
			return lr;
		}
		break;

	case WM_NCLBUTTONDBLCLK:
		if (wp == HTCAPTION)
		{
			CAutoFlag af(m_bResizeUpdate, FALSE);
			BOOL bIsZoomed = Maximized();

			LRESULT lr = Default();

			if (!bIsZoomed)
				OnMaximize();
			else
				OnRestore();

			return lr;
		}
		break;

	case WM_NCLBUTTONDOWN:
		// if this is in the caption and the main window in maxed
		// then eat
		if (wp == HTCAPTION && Maximized())
		{
			// activate the window first
			SendMessage(WM_ACTIVATE, WA_CLICKACTIVE, NULL);
			return 0;
		}
		break;
		
	case WM_GETMINMAXINFO:
		{
			// if the main window is zoomed then don't restrict how far
			// the docked window can be resized
			LRESULT lr = Default();

			// save off our last min size
			LPMINMAXINFO pMMI = (LPMINMAXINFO)lp;
			m_sizeMainMin = pMMI->ptMinTrackSize;

			OnMinMaxInfo(pMMI, TRUE);
			return lr;
		}

	}

	return Default();
}

void CDockManager::OnMaximize()
{
	ASSERT (Maximized());

	BOOL bDockVisible = ::IsWindowVisible(ScGetHwnd());
	CRect rMain = GetWorkArea();
	
	if (bDockVisible && IsDocked())
	{
		CRect rDock;
		::GetWindowRect(ScGetHwnd(), rDock);
		
		switch (m_nDockPos)
		{
		case DMP_LEFT:
			if (m_nWidthDockedMax == -1)
				rMain.left += min(rDock.Width(), rMain.Width() / 2);
			else
				rMain.left += m_nWidthDockedMax;
			break;
			
		case DMP_RIGHT:
			if (m_nWidthDockedMax == -1)
				rMain.right -= min(rDock.Width(), rMain.Width() / 2);
			else
				rMain.right -= m_nWidthDockedMax;
			break;

		case DMP_BELOW:
			if (m_nHeightDockedMax == -1)
				rMain.bottom -= min(rDock.Height(), rMain.Height() / 2);
			else
				rMain.bottom -= m_nHeightDockedMax;
			break;

		default:
			ASSERT(0);
			return;
		}
	}

	MoveWindow(GetCWnd(), rMain);

	if (IsDocked())
		UpdateDockWindowPos();
}

void CDockManager::OnRestore()
{
	ASSERT (!Maximized());

	BOOL bDockVisible = ::IsWindowVisible(ScGetHwnd());

	if (bDockVisible && IsDocked())
	{
		CRect rDock;
		GetWindowRect(rDock);
		
		switch (m_nDockPos)
		{
		case DMP_LEFT:
			if (m_nWidthDocked != -1)
			{
				rDock.right = rDock.left;
				rDock.left -= m_nWidthDocked;
			}
			break;

		case DMP_RIGHT:
			if (m_nWidthDocked != -1)
			{
				rDock.left = rDock.right;
				rDock.right += m_nWidthDocked;
			}
			break;

		case DMP_BELOW:
			if (m_nHeightDocked != -1)
			{
				rDock.top = rDock.bottom;
				rDock.bottom += m_nHeightDocked;
			}
			break;

		default:
			ASSERT(0);
			return;
		}

		MoveWindow(ScGetCWnd(), rDock);
	}
}

LRESULT CDockManager::ScWindowProc(HWND hRealWnd, UINT msg, WPARAM wp, LPARAM lp)
{

	switch (msg)
	{
	case WM_MOVE:
		if (IsDocked())
		{
			LRESULT lr = ScDefault(hRealWnd);

			if (m_bResizeUpdate)
				UpdateMainWindowPos();

			return lr;
		}
		break;

	case WM_SIZE:
		if (IsDocked())
		{
			LRESULT lr = ScDefault(hRealWnd);

			if (m_bResizeUpdate)
				UpdateMainWindowPos();

			// save dock width
			if (m_bSizeUpdate && ::IsWindowVisible(ScGetHwnd()))
			{
				CRect rDock;
				::GetWindowRect(ScGetHwnd(), rDock);

				if (Maximized())
				{
					if (m_nDockPos == DMP_BELOW)
						m_nHeightDockedMax = rDock.Height();
					else
						m_nWidthDockedMax = rDock.Width();
				}
				else
				{
					if (m_nDockPos == DMP_BELOW)
						m_nHeightDocked = rDock.Height();
					else
						m_nWidthDocked = rDock.Width();
				}
			}
			
			return lr;
		}
		break;

	case WM_SYSCOMMAND:
		if (IsDocked())
		{
			switch (wp)
			{
			// hide system menu
			case SC_KEYMENU:
			case SC_MOUSEMENU:
				return 0;
			
			// don't allow docked window to be minimized or maximized directly
			// instead, send the message to the main window
			case SC_MAXIMIZE:
			case SC_MINIMIZE:
				return SendMessage(msg, wp, lp);

			// if the dock window is being closed and the main window is maximized
			// then readjust the main window rect
			case SC_CLOSE:
				if (Maximized())
				{
					LRESULT lr = ScDefault(hRealWnd);

					OnMaximize();

					return lr;
				}
				break;
			}
		}
		break;

	case WM_NCRBUTTONDOWN:

⌨️ 快捷键说明

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