MFC带自动水平滚动条ListBox

示例代码: http://download.csdn.net/detail/ayang1986/9586701


// HorzListBox.h : 头文件
//

/*****************************************************************
作者:ayang1986
版本:v1.0 (2016.7.26)
说明:适用于MFC,CListBox子类, 自动水平滚动条
*****************************************************************/

#pragma once

// class SBTree

class SBTNode
{
public:
	int key;
	unsigned int account;

private:
	friend class SBTree;
	SBTNode *p, *left, *right;
	unsigned int Size;

public:
	SBTNode(int _key)
	{
		key = _key;
		Size = 1;
		account = 1;
		left = NULL;
		right = NULL;
	};
};

class SBTree
{
private:
	void LeftRotate(SBTNode* x);//左旋函数 
	void RightRotate(SBTNode* x);//右旋函数 
	SBTNode* DeleteSuccessor(SBTNode* x);
	void Empty(SBTNode* &x);//清空指定子树		
	bool Insert(int k, SBTNode* &z);//插入函数
	SBTNode* Search(SBTNode* x, int k); //中序检索函数 

	SBTNode *Root, *Nil;//根节点、哨兵节点 
	unsigned int NUM;

public:
	SBTree()
	{
		Nil = new SBTNode(0);
		Nil->Size = 0;
		Nil->account = 0;
		Nil->left = Nil;
		Nil->right = Nil;
		NUM = 0;
		Root = Nil;
	};//构造函数 

	~SBTree()
	{
		delete Nil;
		Empty();
	};//析构函数 

	SBTNode* Insert(int k);//插入函数 
	void Delete(int k);//删除函数,若找不到所输入元素则返回 
	void Maintain(SBTNode* x, bool IsRight);//主调整函数 
	SBTNode* Search(int k);//中序检索函数 		
	SBTNode* Successor(SBTNode* x);//后继 
	SBTNode* Predecessor(SBTNode* x);//前趋 
	SBTNode* Minimum(SBTNode* x = NULL);//最小值 
	SBTNode* Maximum(SBTNode* x = NULL);//最大值 
	void  Print(SBTNode* &x);// 升序打印指定子树 
	void  Print();// 升序打印整棵树 
	void  Empty();//清空整棵树 
	unsigned int Count(); //整棵树元素个数 
};

// CHorzListBox

class CHorzListBox : public CListBox
{
	DECLARE_DYNAMIC(CHorzListBox)

public:
	CHorzListBox();
	virtual ~CHorzListBox();

protected:
	DECLARE_MESSAGE_MAP()

public:
	int AddString(LPCTSTR lpszItem);
	int DeleteString(UINT nIndex);
	int InsertString(int nIndex, LPCTSTR lpszItem);
	void ResetContent();

	int Dir(UINT attr, LPCTSTR lpszWildCard);	// 该函数没有设置宽度接口, 屏蔽该函数

	void Print();

private:
	//BOOL IsVertVisible();	// 垂直滚动条是否可见

	int GetHorzWidth(int nIndex);		// 获取字串宽度
	void UpdateHorzScrollBar(int nWidth, BOOL blAdd);	// 更新水平滚动条

	SBTree	m_treeWidth;
};

// HorzListBox.cpp : 实现文件
//

#include "stdafx.h"
#include "MFCListBox.h"
#include "HorzListBox.h"

// SBTree

void SBTree::LeftRotate(SBTNode* x)
{
	SBTNode*y = x->right;
	x->right = y->left;
	if (y->left != Nil)
	{
		y->left->p = x;
	};
	y->p = x->p;
	if (x->p == Nil)
	{
		Root = y;
	}
	else{
		if (x == x->p->left)
		{
			x->p->left = y;
		}
		else{
			x->p->right = y;
		};
	};
	x->p = y;
	y->left = x;
	y->Size = x->Size;
	x->Size = x->left->Size + x->right->Size + 1;//Size的维护 
}

void SBTree::RightRotate(SBTNode* x)
{
	SBTNode*y = x->left;
	x->left = y->right;
	if (y->right != Nil)
	{
		y->right->p = x;
	};
	y->p = x->p;
	if (x->p == Nil)
	{
		Root = y;
	}
	else{
		if (x == x->p->right)
		{
			x->p->right = y;
		}
		else{
			x->p->left = y;
		};
	};
	x->p = y;
	y->right = x;
	y->Size = x->Size;
	x->Size = x->left->Size + x->right->Size + 1;//Size的维护 
}


SBTNode* SBTree::Insert(int k)
{
	SBTNode*x = Root, *y = Nil;
	while (x != Nil)
	{
		if (k == x->key)
		{
			x->account++;
			NUM++;
			y = x;
			x = x->p;
			while (x != Nil)
			{
				x->Size--;
				x = x->p;
			};
			return y;
		};//若有相同元素则计数加1,恢复先祖的Size 
		x->Size++;
		y = x;
		if (k < x->key)
		{
			x = x->left;
		}
		else{
			x = x->right;
		};
	};
	SBTNode* z = new SBTNode(k);
	z->p = y;
	if (y == Nil)
	{
		Root = z;
	}
	else{
		if (k < y->key)
		{
			y->left = z;
		}
		else{
			y->right = z;
		};
	};
	z->left = Nil;
	z->right = Nil;
	while (y != Nil)
	{
		Maintain(y, k >= y->key);
		y = y->p;
	};

	return z;
}

void SBTree::Delete(int k)
{
	SBTNode*z = Root, *w = Nil;
	while (k != z->key && z != Nil)
	{
		z->Size--;
		w = z;
		if (k < z->key)
		{
			z = z->left;
		}
		else{
			z = z->right;
		};
	};
	if (z == Nil)
	{
		while (w != Nil)
		{
			w->Size++;
			w = w->p;
		};//若没找到,则恢复先祖的Size 
	}
	else{
		if (z->account > 1)
		{
			z->account--;
			NUM--;
			while (w != Nil)
			{
				w->Size++;
				w = w->p;
			};
			return;
		};//若计数大于1,则计数减1,并恢复先祖的Size 
		SBTNode*y, *x;
		if (z->left == Nil || z->right == Nil)
		{
			y = z;
		}
		else{
			y = DeleteSuccessor(z);
		};
		if (y->left != Nil)
		{
			x = y->left;
		}
		else{
			x = y->right;
		};
		x->p = y->p;
		if (y->p == Nil)
		{
			Root = x;
		}
		else{
			if (y == y->p->left)
			{
				y->p->left = x;
			}
			else{
				y->p->right = x;
			};
		};
		if (y != z)
		{
			z->key = y->key;
			z->account = y->account;
		};
		delete y;
	};
}

//删除中使用的后继函数,一边搜索,一边减小Size 
SBTNode* SBTree::DeleteSuccessor(SBTNode* x)
{
	x->Size--;
	x = x->right;
	while (x->left != Nil)
	{
		x->Size--;
		x = x->left;
	};
	return x;
}

void SBTree::Maintain(SBTNode* x, bool IsRight)
{
	if (IsRight)
	{
		if (x->right->right->Size > x->left->Size)
		{
			LeftRotate(x);
		}
		else{
			if (x->right->left->Size > x->left->Size)
			{
				RightRotate(x->right);
				LeftRotate(x);
			}
			else{
				return;
			};
		};
	}
	else{
		if (x->left->left->Size > x->right->Size)
		{
			RightRotate(x);
		}
		else{
			if (x->left->right->Size > x->right->Size)
			{
				LeftRotate(x->left);
				RightRotate(x);
			}
			else{
				return;
			};
		};
	};
	Maintain(x->p->left, false);
	Maintain(x->p->right, true);
	Maintain(x->p, true);
	Maintain(x->p, false);
}

SBTNode* SBTree::Successor(SBTNode* x)
{
	if (x->right != Nil)
		return Minimum(x->right);
	SBTNode*y = x->p;
	while (y != Nil && x == y->right)
	{
		x = y;
		y = y->p;
	};
	return y;
}

SBTNode* SBTree::Predecessor(SBTNode* x)
{
	if (x->right != Nil)
		return Minimum(x->right);
	SBTNode*y = x->p;
	while (y != Nil && x == y->right)
	{
		x = y;
		y = y->p;
	};
	return y;
}

SBTNode* SBTree::Minimum(SBTNode* x)
{
	if (x == NULL) x = Root;
	while (x->left != Nil)
	{
		x = x->left;
	};
	return x;
}

SBTNode* SBTree::Maximum(SBTNode* x)
{
	if (x == NULL) x = Root;
	while (x->right != Nil)
	{
		x = x->right;
	};
	return x;
}

SBTNode* SBTree::Search(int k)
{
	return Search(Root, k);
}

SBTNode* SBTree::Search(SBTNode* x, int k)
{
	while (x != Nil && k != x->key)
	{
		if (k < x->key)
		{
			x = x->left;
		}
		else{
			x = x->right;
		};
	};
	return x;
}

void SBTree::Print(SBTNode* &x)
{
	if (x->left != Nil)
		Print(x->left);

	TRACE("%d ( %d )\n", x->key, x->account);

	if (x->right != Nil)
		Print(x->right);
}

void SBTree::Print()
{
	if (Root == Nil)
	{
		TRACE("Empty tree!\n");
		return;
	};
	Print(Root);
}

void SBTree::Empty()
{
	if (Root != Nil)
	{
		Empty(Root);
		Root = Nil;
		NUM = 0;
	};
}

void SBTree::Empty(SBTNode* &x)
{
	if (x->left != Nil)
		Empty(x->left);
	if (x->right != Nil)
		Empty(x->right);
	delete x;
}

unsigned int SBTree::Count()
{
	return (Root->Size + NUM);
}

// CHorzListBox

IMPLEMENT_DYNAMIC(CHorzListBox, CListBox)

CHorzListBox::CHorzListBox()
{
}

CHorzListBox::~CHorzListBox()
{
}


BEGIN_MESSAGE_MAP(CHorzListBox, CListBox)
END_MESSAGE_MAP()


// CHorzListBox 消息处理程序
int CHorzListBox::AddString(LPCTSTR lpszItem)
{
	int nIndex = CListBox::AddString(lpszItem);
	if (nIndex != LB_ERR)
	{
		int nWidth = GetHorzWidth(nIndex);
		UpdateHorzScrollBar(nWidth, TRUE);
	}

	return nIndex;
}

int CHorzListBox::DeleteString(UINT nIndex)
{
	int nWidth = GetHorzWidth(nIndex);
	int nRtIndex = CListBox::DeleteString(nIndex);
	if (nRtIndex != LB_ERR)
	{
		UpdateHorzScrollBar(nWidth, FALSE);
	}

	return nRtIndex;
}

int CHorzListBox::InsertString(int nIndex, LPCTSTR lpszItem)
{
	int nRtIndex = CListBox::InsertString(nIndex, lpszItem);
	if ((nRtIndex != LB_ERR) && (nRtIndex != LB_ERRSPACE))
	{
		int nWidth = GetHorzWidth(nRtIndex);
		UpdateHorzScrollBar(nWidth, TRUE);
	}

	return nRtIndex;
}

void CHorzListBox::ResetContent()
{
	CListBox::ResetContent();
	SetHorizontalExtent(0);

	m_treeWidth.Empty();
}

int CHorzListBox::Dir(UINT attr, LPCTSTR lpszWildCard)
{
	ASSERT(FALSE);
	return LB_ERR;
}

//=======================================================================
// 垂直滚动条是否可见
//BOOL CHorzListBox::IsVertVisible()
//{
//	SCROLLBARINFO scrollbarInfo = { 0 };
//	scrollbarInfo.cbSize = sizeof(SCROLLBARINFO);
//	GetScrollBarInfo(OBJID_VSCROLL, &scrollbarInfo);
//	if (scrollbarInfo.rgstate[0] & STATE_SYSTEM_INVISIBLE)
//	{
//		return FALSE;
//	}
//	else
//	{
//		return TRUE;
//	}
//}

//=======================================================================
// 获取字串宽度
int CHorzListBox::GetHorzWidth(int nIndex)
{
	CString    str;
	CSize      sz;
	TEXTMETRIC tm;

	CDC* pDC = GetDC();
	CFont* pFont = GetFont();

	CFont* pOldFont = pDC->SelectObject(pFont);	// Select the listbox font, save the old font
	pDC->GetTextMetrics(&tm);		// Get the text metrics for avg char width

	GetText(nIndex, str);
	sz = pDC->GetTextExtent(str);
	sz.cx += tm.tmAveCharWidth;	// Add the avg width to prevent clipping

	pDC->SelectObject(pOldFont);	// Select the old font back into the DC
	ReleaseDC(pDC);

	return sz.cx;
}

//=======================================================================
// 更新水平滚动条
// blAdd: TRUE 增加, FALSE 删除
void CHorzListBox::UpdateHorzScrollBar(int nWidth, BOOL blAdd)
{
	if (blAdd)
	{
		int nMax = m_treeWidth.Maximum()->key;
		m_treeWidth.Insert(nWidth);
		if (nMax < nWidth)
		{
			SetHorizontalExtent(nWidth);
		}
	}
	else
	{
		m_treeWidth.Delete(nWidth);
		int nMax = m_treeWidth.Maximum()->key;
		if (nMax < nWidth)
		{
			SetHorizontalExtent(nMax);
		}
	}
}

void CHorzListBox::Print()
{
	m_treeWidth.Print();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值