dockmanager.cpp

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

CPP
802
字号
		// if this is in the caption then eat it
		if (IsDocked() && wp == HTCAPTION)
		{
			// activate the window first
			ScSendMessage(WM_ACTIVATE, WA_CLICKACTIVE, NULL);
			return 0;
		}
		break;

	case WM_NCLBUTTONDOWN:
		// if this is in the caption and the main window in maxed
		// then eat
		if (IsDocked() && wp == HTCAPTION && Maximized())
		{
			// activate the window first
			ScSendMessage(WM_ACTIVATE, WA_CLICKACTIVE, NULL);
			return 0;
		}
		break;

	case WM_NCLBUTTONDBLCLK:
		if (wp == HTCAPTION)
		{
			// toggle the docked state
			if (IsDocked())
				UnDock();
			else
				Dock(m_nLastDockPos);

			// and eat the message
			return 0;
		}
		break;

	case WM_NCHITTEST:
		if (IsDocked())
		{
			UINT nHitTest = ScDefault(hRealWnd);

			// if the main window is _not_ unmaximized then don't let the 
			// docked window be resized on it's docked edge
			// because its not intuitive and causes no end of trouble :)
			if (!Maximized())
			{
				switch (m_nDockPos)
				{
				case DMP_LEFT:
					if (nHitTest == HTRIGHT || nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT)
						nHitTest = HTCLIENT;
					break;

				case DMP_RIGHT:
					if (nHitTest == HTLEFT || nHitTest == HTTOPLEFT || nHitTest == HTBOTTOMLEFT)
						nHitTest = HTCLIENT;
					break;

				case DMP_BELOW:
					if (nHitTest == HTTOP || nHitTest == HTTOPLEFT || nHitTest == HTTOPRIGHT)
						nHitTest = HTCLIENT;
					break;

				default:
					ASSERT(0);
					break;
				}
			}
			// else main window is maximized so _only_ let it be resized on its
			// docked edge and resize the main window afterwards
			else 
			{
				switch (m_nDockPos)
				{
				case DMP_LEFT:
					if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT ||
						nHitTest == HTLEFT || nHitTest == HTTOPLEFT || 
						nHitTest == HTBOTTOMLEFT ||	nHitTest == HTTOP || nHitTest == HTBOTTOM)
					{
						nHitTest = HTCLIENT;
					}
					break;

				case DMP_RIGHT:
					if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT ||
						nHitTest == HTRIGHT || nHitTest == HTTOPLEFT || 
						nHitTest == HTBOTTOMLEFT ||	nHitTest == HTTOP || nHitTest == HTBOTTOM)
					{
						nHitTest = HTCLIENT;
					}
					break;

				case DMP_BELOW:
					if (nHitTest == HTTOPRIGHT || nHitTest == HTBOTTOMRIGHT ||
						nHitTest == HTRIGHT || nHitTest == HTTOPLEFT || 
						nHitTest == HTBOTTOMLEFT ||	nHitTest == HTLEFT || nHitTest == HTBOTTOM)
					{
						nHitTest = HTCLIENT;
					}
					break;

				default:
					ASSERT(0);
					break;
				}
			}

			return nHitTest;
		}
		break;

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

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

			OnMinMaxInfo(pMMI, FALSE);
			return lr;
		}

	case WM_WINDOWPOSCHANGED:
		// if the dock window is being shown/hidden and the main window is maximized 
		// then adjust the main window rect
		if (IsDocked() && Maximized())
		{
			LPWINDOWPOS lpwp = (LPWINDOWPOS)lp;

			if (lpwp->flags & (SWP_SHOWWINDOW | SWP_HIDEWINDOW))
			{
				LRESULT lr = ScDefault(hRealWnd);
				
				OnMaximize();
				
				return lr;
			}
		}
		break;
	}

	return ScDefault(hRealWnd);
}

void CDockManager::OnMinMaxInfo(LPMINMAXINFO pMMI, BOOL /*bMain*/)
{
	if (Maximized())
	{
   		CSize sizeMin = GetMinMaximizedSize();
		CRect rWork = GetWorkArea();
		
		if (m_nDockPos == DMP_BELOW)
		{
			pMMI->ptMinTrackSize.y = sizeMin.cy;
			pMMI->ptMaxTrackSize.y = rWork.Height() - sizeMin.cy;
		}
		else
		{
			pMMI->ptMinTrackSize.x = sizeMin.cx;
			pMMI->ptMaxTrackSize.x = rWork.Width() - sizeMin.cx;
		}
	}
	else
	{
   		CSize sizeMin;
		if (m_nDockPos == DMP_BELOW)
		{
			sizeMin.cx = max(m_sizeMainMin.cx, m_sizeDockMin.cx);
			sizeMin.cy = m_sizeDockMin.cy;
		}
		else
		{
			sizeMin.cx = m_sizeDockMin.cx;
			sizeMin.cy = max(m_sizeMainMin.cy, m_sizeDockMin.cy);
		}
		
		pMMI->ptMinTrackSize.y = max(sizeMin.cy, pMMI->ptMinTrackSize.y);
		pMMI->ptMinTrackSize.x = max(sizeMin.cx, pMMI->ptMinTrackSize.x);
	}
}

void CDockManager::UpdateDockWindowPos(BOOL /*bJustRestored*/)
{
	ASSERT (IsDocked());

	if (!IsDocked())
		return;

	CRect rMain, rDock;

	GetWindowRect(rMain);
	::GetWindowRect(ScGetHwnd(), rDock);

	if (Maximized())
	{
		CRect rWorkArea = GetWorkArea();

		switch (m_nDockPos)
		{
		case DMP_LEFT:
			rDock.top = rMain.top;
			rDock.bottom = rMain.bottom;
			rDock.left = rWorkArea.left;
			rDock.right = rMain.left;
			break;

		case DMP_RIGHT:
			rDock.top = rMain.top;
			rDock.bottom = rMain.bottom;
			rDock.right = rWorkArea.right;
			rDock.left = rMain.right;
			break;

		case DMP_BELOW:
			rDock.left = rMain.left;
			rDock.right = rMain.right;
			rDock.bottom = rWorkArea.bottom;
			rDock.top = rMain.bottom;
			break;

		default:
			ASSERT(0);
			return;
		}
	}
	else // not maximized
	{
		switch (m_nDockPos)
		{
		case DMP_LEFT:
			rDock.top = rMain.top;
			rDock.bottom = rMain.bottom;
			rDock.left = rMain.left - rDock.Width();
			rDock.right = rMain.left;
			break;

		case DMP_RIGHT:
			rDock.top = rMain.top;
			rDock.bottom = rMain.bottom;
			rDock.right = rMain.right + rDock.Width();
			rDock.left = rMain.right;
			break;

		case DMP_BELOW:
			rDock.left = rMain.left;
			rDock.right = rMain.right;
			rDock.bottom = rMain.bottom + rDock.Height();
			rDock.top = rMain.bottom;
			break;

		default:
			ASSERT(0);
			return;
		}
	}

	MoveWindow(ScGetCWnd(), rDock);
}

void CDockManager::UpdateMainWindowPos()
{
	ASSERT (IsDocked());

	if (!IsDocked())
		return;

	CRect rMain, rDock;

	GetWindowRect(rMain);
	::GetWindowRect(ScGetHwnd(), rDock);

	// if the main window is maximized then shrink/enlarge
	// the window
	if (Maximized())
	{
		rMain = GetWorkArea();

		switch (m_nDockPos)
		{
		case DMP_LEFT:
			rMain.left = rDock.right;
			break;

		case DMP_RIGHT:
			rMain.right = rDock.left;
			break;

		case DMP_BELOW:
			rMain.bottom = rDock.top;
			break;

		default:
			ASSERT(0);
			return;
		}
	}
	// else just move the main window
	else
	{
		switch (m_nDockPos)
		{
		case DMP_LEFT:
			rMain.top = rDock.top;
			rMain.bottom = rDock.bottom;
			rMain.right = rDock.right + rMain.Width();
			rMain.left = rDock.right;
			break;

		case DMP_RIGHT:
			rMain.top = rDock.top;
			rMain.bottom = rDock.bottom;
			rMain.left = rDock.left - rMain.Width();
			rMain.right = rDock.left;
			break;

		case DMP_BELOW:
			rMain.left = rDock.left;
			rMain.right = rDock.right;
			rMain.top = rDock.top - rMain.Height();
			rMain.bottom = rDock.top;
			break;

		default:
			ASSERT(0);
			return;
		}
	}

	MoveWindow(GetCWnd(), rMain);
}

void CDockManager::MoveWindow(CWnd* pWnd, CRect rect)
{
	CRect rOrg;
	pWnd->GetWindowRect(rOrg);

	// don't move if nuthin's changed
	if (rect != rOrg)
		pWnd->SetWindowPos(NULL, rect.left, rect.top, rect.Width(), rect.Height(),
							SWP_NOACTIVATE | SWP_NOZORDER);
}

CRect CDockManager::GetUnDockedRect()
{
	if (IsDocked())
		return m_rUndocked;

	// else
	CRect rect;
	::GetWindowRect(ScGetHwnd(), rect);

	return rect;
}

CRect CDockManager::GetWorkArea(BOOL bMaximized)
{
	CRect rWorkArea(0, 0, 0, 0);

	HMONITOR hMonitor = MonitorFromWindow(GetHwnd(), MONITOR_DEFAULTTONEAREST);
	ASSERT (hMonitor);

	if (hMonitor)
	{
		MONITORINFO mi; 
		mi.cbSize = sizeof(mi);
		GetMonitorInfo(hMonitor, &mi);

		rWorkArea = mi.rcWork;

      if (bMaximized)
         rWorkArea.InflateRect(4, 4);
	}

	return rWorkArea;
}

CSize CDockManager::GetMinMaximizedSize()
{
   CSize sizeMin = GetWorkArea().Size();
   
   if (IsDocked() && ::IsWindowVisible(ScGetHwnd()))
   {
      switch (m_nDockPos)
      {
      case DMP_LEFT:
      case DMP_RIGHT:
         sizeMin.cx = MINMAXSIZE;
         break;
      
      case DMP_BELOW:
         sizeMin.cy = MINMAXSIZE;
         break;
      
      default:
         ASSERT(0);
      }
   }
   
   return sizeMin;
}

⌨️ 快捷键说明

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