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

📄 group.cpp

📁 哈夫曼编码解码演示程序
💻 CPP
字号:
// Group1.cpp : implementation file
//

#include "stdafx.h"
#include "Group.h"

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

//////////////////////////////////////////////
// CCISBitmap


CCISBitmap::CCISBitmap()
{
	m_crBlack = 0;
	m_crWhite = RGB(255,255,255);
}

CCISBitmap::~CCISBitmap()
{

}

int CCISBitmap::Width()
{
	BITMAP bm;
	GetBitmap(&bm);
	return bm.bmWidth;
}

int CCISBitmap::Height()
{
	BITMAP bm;
	GetBitmap(&bm);
	return bm.bmHeight;
}

void CCISBitmap::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour)
{
	COLORREF crOldBack = pDC->SetBkColor(m_crWhite);
	COLORREF crOldText = pDC->SetTextColor(m_crBlack);
	CDC dcImage, dcTrans;

	// Create two memory dcs for the image and the mask
	dcImage.CreateCompatibleDC(pDC);
	dcTrans.CreateCompatibleDC(pDC);

	// Select the image into the appropriate dc
	CBitmap* pOldBitmapImage = dcImage.SelectObject(this);

	// Create the mask bitmap
	CBitmap bitmapTrans;
	int nWidth = Width();
	int nHeight = Height();
	bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);

	// Select the mask bitmap into the appropriate dc
	CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);

	// Build mask based on transparent colour
	dcImage.SetBkColor(crColour);
	dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);

	// Do the work - True Mask method - cool if not actual display
	pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
	pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
	pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);

	// Restore settings
	dcImage.SelectObject(pOldBitmapImage);
	dcTrans.SelectObject(pOldBitmapTrans);
	pDC->SetBkColor(crOldBack);
	pDC->SetTextColor(crOldText);
}


/////////////////////////////////////////////////////////////////////////////
// CGroup

IMPLEMENT_DYNCREATE(CGroup, CButton);

CGroup::CGroup()
{
	m_folded = false;
	m_created = false;
	m_IsAttracted = true;
	m_attract = true;
	m_userFont = false;
	m_borders = true;
	m_last = false;
	m_extendLastCtrl = false;
	m_contained = false;

	m_barColor = RGB(0,0,85);
	m_textColor = RGB(255,255,255);
	m_ctrlIndex = 0;
	m_barHeight = 25;
	m_barWidth = -1;
	
	m_toggle = NULL;
	m_bitmap = NULL;
	m_bmpMask = 0;
	m_fontSize = 12;	
}

CGroup::~CGroup()
{
	if(m_toggle!=NULL)
	{
		m_toggle->DestroyWindow();
		delete m_toggle;
	}
	if(m_bitmap!=NULL)
		::DeleteObject(m_bitmap);
}


BEGIN_MESSAGE_MAP(CGroup, CButton)
	//{{AFX_MSG_MAP(CGroup)
	ON_WM_PAINT()
	ON_BN_CLICKED(BUTTON_TOGGLE,OnToggle)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CGroup message handlers

void CGroup::OnPaint() 
{
	CPaintDC dc(this); // device context for painting

	//get the group size
	GetClientRect(m_clRect);

	
	//define the different zones of the control
	if(m_bitmap!=NULL && m_resizeBar && m_barHeight<m_bitmap->Height())
	{
		m_barHeight = m_bitmap->Height()+2;
	}
	
	if(m_barWidth==-1)
	{
		m_barWidth = m_clRect.right;
	}

	if(m_contained)
	{
		m_attract = false;
		m_IsAttracted = false;
	}	


	captionRect = CRect(m_clRect.left+1,m_clRect.top,m_barWidth-1,m_barHeight-1);
	groupRect = CRect(m_clRect.left,m_clRect.top+(m_barHeight-1),m_clRect.right,m_clRect.bottom);
	buttonRect = CRect(m_barWidth-20,m_clRect.top+3,m_barWidth-3,m_clRect.top+(m_barHeight-3));
	
	//first init...
	if(!m_created)
	{
		m_created = true;

		//take reference of the controls contained within the group area
		m_parent = GetParent()->GetWindow (GW_CHILD);
		CWnd* pr = m_parent->GetParent();
		while (m_parent)
		{
			CRect m_copRect;
			GetWindowRect(m_copRect);
			CRect wRect;
			m_parent->GetWindowRect(wRect);
			if(wRect.left>m_copRect.left && wRect.right<m_copRect.right && wRect.top>m_copRect.top && wRect.bottom<m_copRect.bottom)
			{
				m_controls[m_ctrlIndex] = m_parent->GetDlgCtrlID();
				BOOL nID = m_parent->IsKindOf(RUNTIME_CLASS(CGroup));
				//if it is...
				if(nID)
				{
					//get a pointer to the CGroup object
					CGroup* cg = (CGroup*)m_parent;
					cg->m_contained = true;
				}
				m_ctrlIndex++;
			}
			m_parent = m_parent->GetWindow (GW_HWNDNEXT);
		}
	
		//set up the caption font
		if(!m_userFont)
		{
			LOGFONT lf;
			::ZeroMemory(&lf,sizeof(lf));

			lf.lfHeight = MulDiv(m_fontSize,dc.GetDeviceCaps(LOGPIXELSX),72);
			lf.lfWidth = 0;
			lf.lfEscapement = 0;
			lf.lfOrientation = 0;
			lf.lfWeight = FW_BOLD;
			lf.lfItalic = TRUE;
			lf.lfUnderline = FALSE;
			lf.lfStrikeOut = FALSE;
			lf.lfCharSet = DEFAULT_CHARSET;
			lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
			lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
			lf.lfQuality = DEFAULT_QUALITY;
			lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;

			//create the font
			m_font.CreateFontIndirect(&lf);
		}
		//retrieve the control caption
		GetWindowText(m_caption);

		//create the toggle button
		if(!m_toggle)
		{
			m_toggle = new CButton;
			m_toggle->Create("",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON|BS_BITMAP,buttonRect,this,BUTTON_TOGGLE);
			m_toggle->ShowWindow(true);
			m_toggle->SetBitmap(::LoadBitmap(NULL, MAKEINTRESOURCE(32753)));
		}

		//have to be set, otherwise the control will not be redrawn if, for instance, you move the dialog window...
		SetRedraw();

	}

	//assign the font to the device context
	CFont* pOldFont = (CFont*)dc.SelectObject(&m_font);
	CBrush brush;
	brush.CreateSolidBrush(m_barColor);
	CBrush* pOldBrush = (CBrush*)dc.SelectObject(&brush);

	//draw the rectangle of the title bar
	dc.FillRect(captionRect,&brush);

	//restore
	dc.SelectObject(pOldBrush);

	//draw the group border
	if(!m_folded && m_borders)
		dc.Draw3dRect(groupRect,RGB(128,128,128),RGB(255,255,255));
	
	//draw the title bar border
	if(m_barBorders)
		dc.Draw3dRect(CRect(m_clRect.left,m_clRect.top,m_barWidth,m_barHeight),RGB(128,128,128),RGB(255,255,255));
	
	//draw the caption text
	dc.SetBkColor(m_barColor);
	dc.SetTextColor(m_textColor);

	int diffHFont = (int)(((m_barHeight-5) - m_fontSize)*0.5);

	if(m_bitmap==NULL)
	{
		dc.TextOut(m_clRect.left+(int)(m_barHeight*0.3),m_clRect.top+diffHFont,m_caption);
	}
	else
	{
		dc.TextOut(m_clRect.left+(m_bitmap->Width()+2),m_clRect.top+diffHFont,m_caption);
		m_bitmap->DrawTransparent(GetDC(), 1, 1, m_bmpMask);
	}
	dc.SelectObject(pOldBrush);

}

void CGroup::SetTextFont(LOGFONT lf)
{
	m_font.DeleteObject();
	m_font.CreateFontIndirect(&lf);
	m_userFont = true;
}

void CGroup::SetBarHeight(int h)
{
	m_barHeight = h;
	Invalidate();
}

void CGroup::SetBarWidth(int w)
{
	m_barWidth = w;
	Invalidate();
}

void CGroup::SetTextFont (CString face,int size,bool bold,bool italic,bool underline)
{
	CPaintDC dc(this);
	m_fontSize = size;

	LOGFONT lf;
	::ZeroMemory(&lf,sizeof(lf));

	lf.lfHeight = MulDiv(m_fontSize,dc.GetDeviceCaps(LOGPIXELSX),72);
	lf.lfWidth = 0;
	lf.lfEscapement = 0;
	lf.lfOrientation = 0;
	lf.lfWeight = (bold?FW_BOLD:FALSE);
	lf.lfItalic = italic;
	lf.lfUnderline = underline;
	lf.lfStrikeOut = FALSE;
	lf.lfCharSet = DEFAULT_CHARSET;
	lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
	lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
	lf.lfQuality = DEFAULT_QUALITY;
	lf.lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
	strcpy(lf.lfFaceName,face);

	//create the font
	SetTextFont(lf);
}

void CGroup::SetFold(bool toggle)
{
	if(!m_toggle)
	{
		buttonRect = CRect(m_clRect.right-20,m_clRect.top+3,m_clRect.right-3,m_clRect.top+(m_barHeight-3));

		m_toggle = new CButton;
		m_toggle->Create("-",WS_CHILD|WS_VISIBLE|BS_PUSHBUTTON,buttonRect,this,BUTTON_TOGGLE);
		m_toggle->ShowWindow(toggle);
	}
	else
		m_toggle->ShowWindow(toggle);
	
	if(!toggle)
	{
		if(m_folded)
		{
			OnToggle();
		}
	}
}

void CGroup::SetBitmap(UINT bmpID,COLORREF mask,bool resizeBar)
{

	if (bmpID == 0)
	{
		return;
	}

	if(m_bitmap!=NULL)
	{
		m_bitmap->DeleteObject();
	}
	
	m_bitmap = new CCISBitmap;

	m_bmpMask = mask;
	m_resizeBar = resizeBar;
	m_bitmap->LoadBitmap(bmpID);
	Invalidate();
}

void CGroup::OnToggle()
{
	//change the state of the group: expanded / folded
	m_folded=!m_folded;

	//change the image of the button
	// (somehow, I couldn't pass the defines and had to put down the index ?????????)
	m_toggle->SetBitmap(::LoadBitmap(NULL, MAKEINTRESOURCE(m_folded?32752:32753)));
	
	//remove the black focus rectangle in the button
	SetFocus();
	m_toggle->SetButtonStyle(BS_PUSHBUTTON);

	//get the first child window of the main dialog (owner of the group)
	m_parent = GetParent()->GetWindow (GW_CHILD);

	//get the CWnd of the parent window (that would be the main dialog)
	CWnd* pr = m_parent->GetParent();

	//get the screen position of the group
	CRect m_copRect,wRect,rRect;
	GetWindowRect(m_copRect);
	//and get the correct client coords from the dialog
	pr->ScreenToClient(m_copRect);

	while (m_parent)
	{
		//get the screen position of the child window
		m_parent->GetWindowRect(wRect);
		//transform them into client coords from the dialog
		pr->ScreenToClient(wRect);
		rRect = wRect;

		//if the group attracts other groups and the control is not self
		if(m_attract && m_parent!=this)
		{
			//Get the vertical offset between the group and the child window we're processing
			int offset = (m_folded? -(m_clRect.Height() - m_barHeight) : m_clRect.Height() - m_barHeight);
			
			//check if the child window is another CGroup
			BOOL nID = m_parent->IsKindOf(RUNTIME_CLASS(CGroup));

			//if it is...
			if(nID)
			{
				//get a pointer to the CGroup object
				CGroup* cg = (CGroup*)m_parent;

				//if the group can be attracted by other groups
				if(cg->m_IsAttracted)
				{
					//check if the processed child window (attracted group) is below (attraction is only done upward) the group 
					if(wRect.top>m_copRect.top)
					{
						if((wRect.left>=m_copRect.left && wRect.left<=m_copRect.right) ||
						   (wRect.right>=m_copRect.left && wRect.right<=m_copRect.right))
						{
							//look for all the other window contained within the processed child window (attracted group)
							CWnd* m_search = GetParent()->GetWindow(GW_CHILD);

							//variable to store the lowest control in the processed child window (attracted group)
							int indexLowest = -1;
							int currentLow = 0;

							//retrieve the number of control contained within the processed child window (attracted group)
							int numbControls = cg->m_ctrlIndex;

							//for each control
							for(int i=0;i<numbControls;i++)
							{
								int dlgIndex = cg->m_controls[i];
								CRect eRect;
								//get the position of the control
								pr->GetDlgItem(dlgIndex)->GetWindowRect(eRect);
								//check to see if it's the lowest
								if(eRect.bottom>currentLow)
								{
									indexLowest = dlgIndex;
									currentLow = eRect.bottom;
								}
								//offset the rectangle
								eRect.OffsetRect(0,offset);
								pr->ScreenToClient(eRect);
								//and move the control...
								pr->GetDlgItem(dlgIndex)->MoveWindow(eRect);
							}

							//offset the processed child window rectangle...
							rRect.OffsetRect(0,offset);
							//if it has the last flag, change its height
							if(cg->m_last)
								rRect.bottom-=offset;
							//and move it.
							m_parent->MoveWindow(rRect);
							//if the lowest control has the extended flag
							if(cg->m_extendLastCtrl)
							{
								//change its height
								pr->GetDlgItem(indexLowest)->GetWindowRect(rRect);
								pr->ScreenToClient(rRect);
								rRect.bottom-=offset;
								pr->GetDlgItem(indexLowest)->MoveWindow(rRect);
							}
						}
					}
				}
			}
		}
		
		for(int i=0;i<m_ctrlIndex;i++)
		{
			if(m_parent->GetDlgCtrlID() == m_controls[i])
			{
				m_parent->ShowWindow(m_folded?false:true);
				break;
			}
		}
		m_parent = m_parent->GetWindow (GW_HWNDNEXT);
	}
    CRect rect=m_clRect;
	rect.DeflateRect(-5,-5,-5,-5);
    ClientToScreen(&rect);
	GetParent()->InvalidateRect(rect);//RedrawWindow();
	Invalidate();
}
void CGroup::Expand(BOOL bEx)
{
	if(!IsWindow(this->m_hWnd)||!m_toggle)
	{
		if(!bEx)
			m_folded=true;
		return;
	}
	if(bEx&&m_folded)
		OnToggle();
	if(!bEx&&!m_folded)
		OnToggle();
}

⌨️ 快捷键说明

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