【MFC】CSplitterWnd 重载限定窗口调整范围

 前言:

void CSplitterWnd::GetColumnInfo(int col, int& cxCur, int& cxMin) ;在使用拆分窗口时我的需要是想调整窗口大小在一定范围 不允许过小和隐藏,通过文档得知此代码设置窗口的当前宽度和最小宽度,但是在实际使用发现在调整窗口小于设定的cxMin时,竟然让窗口消失了,这完全与我的需求背道而驰,因此通过分析源码找到了 较为完美的解决方案,并记录笔记,欢迎朋友们交流互相学习。

 注:CSplitterWndEx是继承的CSplitterWnd 只是分割符更加好看了 没有其它拓展功能。

只能点击 【添加类(C)...】  手动继承CSplitterWndEx, 头文件如下设计 重载两个重要的 方法

#pragma once
#include "afxsplitterwndex.h"
class CUserSplitter :
	public CSplitterWndEx
{
public:
	CUserSplitter();
	virtual ~CUserSplitter();
	virtual void TrackRowSize(int y, int row);
	virtual void TrackColumnSize(int x, int col);
	DECLARE_MESSAGE_MAP()
};

其中TrackRowSize 是根据名称便知是调整行的尺寸的,源码中实现方法如下:

//路径 ..\atlmfc\src\mfc\winsplit.cpp  877行
void CSplitterWnd::TrackRowSize(int y, int row)
{
	ASSERT_VALID(this);
	ASSERT(m_nRows > 1);

	CPoint pt(0, y);
	ClientToScreen(&pt);
	GetPane(row, 0)->ScreenToClient(&pt);
	m_pRowInfo[row].nIdealSize = pt.y;      // new size
	if (pt.y < m_pRowInfo[row].nMinSize)
	{//这里的判断是说如果当前行的新Size小于 设定的nMinSize 则移除这一行 
		// resized too small
		m_pRowInfo[row].nIdealSize = 0; // make it go away    
		if (GetStyle() & SPLS_DYNAMIC_SPLIT)
			DeleteRow(row);
	}
	else if (m_pRowInfo[row].nCurSize + m_pRowInfo[row+1].nCurSize
			< pt.y + m_pRowInfo[row+1].nMinSize)
	{//这个判断是说如果当前区域的下一行小于最小的nMinSize则移除下一行
		// not enough room for other pane
		if (GetStyle() & SPLS_DYNAMIC_SPLIT)
			DeleteRow(row + 1);
	}
}

根据它的判断方式我们便可以最小的改动去实现 限定窗口在一定范围内的缩放

首先重载如下

#include "UserSplitter.h"


CUserSplitter::CUserSplitter()
{
}


CUserSplitter::~CUserSplitter()
{
}
void CUserSplitter::TrackRowSize(int y, int row)
{
	ASSERT_VALID(this);
	ASSERT(m_nRows > 1);

	CPoint pt(0, y);
	ClientToScreen(&pt);
	GetPane(row, 0)->ScreenToClient(&pt);
	m_pRowInfo[row].nIdealSize = pt.y;      // new size
	if (pt.y < m_pRowInfo[row].nMinSize)
	{
		// resized too small
		m_pRowInfo[row].nIdealSize = m_pRowInfo[row].nMinSize; // 如果小于最小 则设为最小
		/*if (GetStyle() & SPLS_DYNAMIC_SPLIT)
			DeleteRow(row);*/
	}
	else if (m_pRowInfo[row].nCurSize + m_pRowInfo[row + 1].nCurSize
		< pt.y + m_pRowInfo[row + 1].nMinSize)
	{//如果挤压旁边太小 则重新设定大小
		// not enough room for other pane
		/*if (GetStyle() & SPLS_DYNAMIC_SPLIT)
			DeleteRow(row + 1);*/
		m_pColInfo[row].nIdealSize = m_pColInfo[row].nCurSize + m_pColInfo[row + 1].nCurSize- m_pColInfo[row + 1].nMinSize;
	}
}
void CUserSplitter::TrackColumnSize(int x, int col)
{
	ASSERT_VALID(this);
	ASSERT(m_nCols > 1);

	CPoint pt(x, 0);
	ClientToScreen(&pt);
	GetPane(0, col)->ScreenToClient(&pt);
	m_pColInfo[col].nIdealSize = pt.x;      // new size
	if (pt.x < m_pColInfo[col].nMinSize)
	{
		// resized too small
		m_pColInfo[col].nIdealSize = m_pColInfo[col].nMinSize; // make it go away
		/*if (GetStyle() & SPLS_DYNAMIC_SPLIT)
			DeleteColumn(col);*/
	}
	else if (m_pColInfo[col].nCurSize + m_pColInfo[col + 1].nCurSize
		< pt.x + m_pColInfo[col + 1].nMinSize)
	{
		// not enough room for other pane
		/*if (GetStyle() & SPLS_DYNAMIC_SPLIT)
			DeleteColumn(col + 1);*/
		m_pColInfo[col].nIdealSize = m_pColInfo[col].nCurSize + m_pColInfo[col + 1].nCurSize- m_pColInfo[col + 1].nMinSize;
	}
}

从上面代码可知,要限定大小则需要m_pColInfo 数组的数据

则使用时可以做如下设计

BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext)
{
	// TODO: 在此添加专用代码和/或调用基类
	int rec = m_SplitWnd.CreateStatic(this, 1, 2);
	m_SplitWnd.CreateView(0, 0, RUNTIME_CLASS(CUserTreeView), CSize(100, 100), pContext);
	m_SplitWnd.CreateView(0, 1, RUNTIME_CLASS(CUserTabView), CSize(100, 100), pContext);

	return  rec;
	//return CFrameWndEx::OnCreateClient(lpcs, pContext);
}
void CMainFrame::OnSize(UINT nType, int cx, int cy)
{
	CFrameWndEx::OnSize(nType, cx, cy);
	// TODO: 在此处添加消息处理程序代码
	m_SplitWnd.SetColumnInfo(0, static_cast<int>(cx*0.2), static_cast<int>(cx*0.1));
	m_SplitWnd.SetColumnInfo(1, static_cast<int>(cx*0.8), static_cast<int>(cx*0.6));
	m_SplitWnd.RecalcLayout();
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值