rovershen 阅读(902) 评论(0)
#if !defined(AFX_CREDITCTRL_H__1EBA78B2_65A4_4E08_B5E0_64683CC611F1__INCLUDED_)
#define AFX_CREDITCTRL_H__1EBA78B2_65A4_4E08_B5E0_64683CC611F1__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
// CreditCtrl.h : header file
//
#include <afxtempl.h>
/////////////////////////////////////////////////////////////////////////////
/*
Copyright:

MFC Credit Control V1.2
Written by: Rover Shen
Email:		rovershen@cmmail.com
Date:		2003/05/12


You may use this controll freely, but should NOT remove this copyright information.

*/
// CCreditCtrl window

class CCreditCtrl : public CWnd
{
// Construction
	class StringItem
	{
	friend class CCreditCtrl;
	private:
		CString strText;
		CString strLink;
		HBITMAP hBitmap;
		CFont*	pFont;
		BOOL	bOwnColor;
		BOOL	bVisited;
		COLORREF rgbColor;
		int		nStartX;
		int		nGap;
		CRect	m_rt;
		StringItem(LPCTSTR text,LPCTSTR link,int startx=0,CFont*ft=NULL,BOOL color=FALSE,
			COLORREF rgb=0,int gap=0):strText(text),strLink(link),nStartX(startx),pFont(ft),
			bOwnColor(color),rgbColor(rgb),bVisited(FALSE),hBitmap(0),nGap(gap)
		{
		}
		StringItem(HBITMAP hBit,int startx=0,LPCTSTR link="",int gap=0):strText(""),strLink(link),
			hBitmap(hBit),pFont(0),bOwnColor(0),rgbColor(0),bVisited(FALSE),
			nStartX(startx),nGap(gap)
		{
		}
		virtual ~StringItem()
		{
			strText.Empty();
			strLink.Empty();
			if(hBitmap)
				DeleteObject(hBitmap);
			if(pFont)
				delete pFont;
		}
	};
	typedef StringItem* LPSI;
/////////////////////////////
public:
	CCreditCtrl();

// Attributes
public:
private:
	COLORREF m_bgColor;
	COLORREF m_fgColor;
	COLORREF m_lkColor;
	COLORREF m_lkVisited;
	CFont*	m_pFont;
	CFont*	m_plkFont;
	BOOL	m_iDir;//0:R->L 1:B->T
	int		m_xCur;
	int		m_yCur;
	CSize	m_Size;
	CSize	m_cSize;
	CBitmap m_Bitmap;
	HBITMAP m_bkImage;
	BOOL	m_bTileImage;
	HCURSOR m_hArrow;
	HCURSOR m_hHand;
	BOOL	bTimer;
	CArray<LPSI,LPSI> m_Array;
	BOOL	bFlag;
	CToolTipCtrl m_wndTips;
	int		m_iLinks;
// Operations
public:

// Overrides
	// ClassWizard generated virtual function overrides
	//{{AFX_VIRTUAL(CCreditCtrl)
	public:
	virtual BOOL PreTranslateMessage(MSG* pMsg);
	protected:
	virtual void PreSubclassWindow();
	//}}AFX_VIRTUAL

// Implementation
public:
	void SetBkImage(HBITMAP hImage,BOOL bTile=TRUE);
	void UpdateTips();
	void AddBitmap(HBITMAP hBit,int gap=0,int startx=0,LPCTSTR link="");
	void SetScrollDirection(BOOL bVert=TRUE);
	void SetDefaultValues(int dir,COLORREF bgColor,COLORREF fgColor=0,
		COLORREF lnkColor=0xff0000,COLORREF lnkVisited=0xff);
	void AddText(LPCTSTR text,LPCTSTR link="",int gap=0,int startx=0,CFont*ft=0,BOOL color=0,
		COLORREF rgb=0);
	void SetFont(CFont*pFont);
	virtual ~CCreditCtrl();

	// Generated message map functions
protected:
	void BuildBitmap();
	void RefreshWindow(CDC*pDC);
	//{{AFX_MSG(CCreditCtrl)
	afx_msg void OnDestroy();
	afx_msg void OnTimer(UINT nIDEvent);
	afx_msg void OnPaint();
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	//}}AFX_MSG
	afx_msg LRESULT OnMouseLeave(WPARAM wParam,LPARAM lParam);
	DECLARE_MESSAGE_MAP()
};

/////////////////////////////////////////////////////////////////////////////

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_CREDITCTRL_H__1EBA78B2_65A4_4E08_B5E0_64683CC611F1__INCLUDED_)


// CreditCtrl.cpp : implementation file
//

#include "stdafx.h"
#include "CreditCtrl.h"
#include <windowsx.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma message("WARNING: This control was written by Rover Shen. You may use it but can't remove copyright information.")
/////////////////////////////////////////////////////////////////////////////
// CCreditCtrl

CCreditCtrl::CCreditCtrl():bFlag(0),m_xCur(0),m_yCur(0),m_fgColor(RGB(0,0,0)),
m_bgColor(GetSysColor(COLOR_BTNFACE)),m_lkColor(RGB(0,0,255)),m_lkVisited(RGB(255,0,0)),
m_iDir(1),m_plkFont(0),bTimer(0),m_iLinks(0),m_bkImage(0)
{
}

CCreditCtrl::~CCreditCtrl()
{
}


BEGIN_MESSAGE_MAP(CCreditCtrl, CWnd)
	//{{AFX_MSG_MAP(CCreditCtrl)
	ON_WM_DESTROY()
	ON_WM_TIMER()
	ON_WM_PAINT()
	ON_WM_SETCURSOR()
	ON_WM_MOUSEMOVE()
	ON_WM_LBUTTONDOWN()
	//}}AFX_MSG_MAP
	ON_MESSAGE(WM_MOUSELEAVE,OnMouseLeave)
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CCreditCtrl message handlers

void CCreditCtrl::PreSubclassWindow() 
{
	CWnd::PreSubclassWindow();
	m_pFont=GetFont();
	LOGFONT lf;
	m_pFont->GetLogFont(&lf);
	lf.lfUnderline=TRUE;
	m_plkFont=new CFont;
	m_plkFont->CreateFontIndirect(&lf);
	m_hArrow=LoadCursor(0,IDC_ARROW);
	m_hHand=LoadCursor(0,IDC_HAND);
	TRACKMOUSEEVENT tme;
	tme.cbSize = sizeof(tme);
	tme.hwndTrack = m_hWnd;
	tme.dwFlags = TME_LEAVE;
	_TrackMouseEvent(&tme);
	m_wndTips.Create(this,TTS_ALWAYSTIP);
}

void CCreditCtrl::SetFont(CFont *pFont)
{
	m_pFont=pFont;
	bFlag=FALSE;
}
/*
StringItem(LPCTSTR text,LPCTSTR link,int startx=0,CFont*ft=NULL,BOOL color=FALSE,
COLORREF rgb=0):strText(text),strLink(link),nStartX(startx),pFont(ft),
bOwnColor(color),rgbColor(rgb)

 */

void CCreditCtrl::AddText(LPCTSTR text, LPCTSTR link,int gap, int startx,CFont*ft,BOOL color,COLORREF rgb)
{
	LPSI pItem=new StringItem(text,link,startx,ft,color,rgb,gap);
	m_Array.Add(pItem);
	bFlag=FALSE;
}

void CCreditCtrl::OnDestroy() 
{
	KillTimer(1);
	CWnd::OnDestroy();
	int count=m_Array.GetSize();
	for(int i=0;i<count;i++)
		delete m_Array.GetAt(i);
	m_Array.RemoveAll();
	if(m_plkFont)
		delete m_plkFont;
	if(m_bkImage)
		DeleteObject(m_bkImage);
}

void CCreditCtrl::OnTimer(UINT nIDEvent) 
{
//0:R->L 1:B->T
	if(m_iDir==0)
		m_xCur++;
	else
		m_yCur++;
	if(m_xCur+m_cSize.cx>m_Size.cx)
		m_xCur=0;
	if(m_yCur+m_cSize.cy>m_Size.cy)
		m_yCur=0;
	CClientDC dc(this);
	RefreshWindow(&dc);
	CWnd::OnTimer(nIDEvent);
}

void CCreditCtrl::OnPaint() 
{
	CPaintDC dc(this); // device context for painting
	RefreshWindow(&dc);
}

BOOL CCreditCtrl::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	CPoint pt;
	GetCursorPos(&pt);
	ScreenToClient(&pt);
	pt.Offset(m_xCur,m_yCur);
	int count=m_Array.GetSize();
	if(count==0)
		return CWnd::OnSetCursor(pWnd, nHitTest, message);
	BOOL bLink=FALSE;
	for(int i=0;i<count;i++){
		LPSI pItem=m_Array.GetAt(i);
		if(!pItem->strLink.IsEmpty()){
			if(pItem->m_rt.PtInRect(pt)){
				bLink=TRUE;
				break;
			}
		}
	}
	if(bLink)
		SetCursor(m_hHand);
	else
		SetCursor(m_hArrow);
	return TRUE;
}
/*
void SaveBmp(HBITMAP hBit,CWnd*pWnd)
{
	CClientDC dc(pWnd);
	CBitmap bm;
	bm.Attach(hBit);
	BITMAP btm;
	bm.GetBitmap(&btm);
	DWORD size=btm.bmWidthBytes*btm.bmHeight;
	LPSTR lpData=(LPSTR)GlobalAllocPtr(GPTR,size);
	/////////////////////////////////////////////
	BITMAPINFOHEADER bih;
	bih.biBitCount=btm.bmBitsPixel;
	bih.biClrImportant=0;
	bih.biClrUsed=0;
	bih.biCompression=0;
	bih.biHeight=btm.bmHeight;
	bih.biPlanes=1;
	bih.biSize=sizeof(BITMAPINFOHEADER);
	bih.biSizeImage=size;
	bih.biWidth=btm.bmWidth;
	bih.biXPelsPerMeter=0;
	bih.biYPelsPerMeter=0;
	GetDIBits(dc,bm,0,bih.biHeight,lpData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);
	//////////////////////////////
	static int filecount=0;
	CString name;
	name.Format("d:\\pict%04d.bmp",filecount++);
	BITMAPFILEHEADER bfh;
	bfh.bfReserved1=bfh.bfReserved2=0;
	bfh.bfType=((WORD)('M'<< 8)|'B');
	bfh.bfSize=54+size;
	bfh.bfOffBits=54;
	CFile bf;
	if(bf.Open(name,CFile::modeCreate|CFile::modeWrite)){
		bf.WriteHuge(&bfh,sizeof(BITMAPFILEHEADER));
		bf.WriteHuge(&bih,sizeof(BITMAPINFOHEADER));
		bf.WriteHuge(lpData,size);
		bf.Close();
	}
	GlobalFreePtr(lpData);
	bm.Detach();
}
*/

void CCreditCtrl::RefreshWindow(CDC *pDC)
{
	if(!bFlag){
		bFlag=TRUE;
///////////////////////////
		BuildBitmap();
///////////////////////////
		return;
	}
	CDC dc;
	dc.CreateCompatibleDC(pDC);
	CBitmap*pOldBmp=dc.SelectObject(&m_Bitmap);
	pDC->BitBlt(0,0,m_cSize.cx,m_cSize.cy,&dc,m_xCur,m_yCur,SRCCOPY);
	dc.SelectObject(pOldBmp);
}

void CCreditCtrl::SetDefaultValues(int dir, COLORREF bgColor, COLORREF fgColor,
	COLORREF lnkColor,COLORREF lnkVisited)
{
	if(dir>=0&&dir<5)
		m_iDir=dir;
	m_bgColor=bgColor;
	m_fgColor=fgColor;
	m_lkColor=lnkColor;
	m_lkVisited=lnkVisited;
	bFlag=FALSE;
}

void CCreditCtrl::BuildBitmap()
{
	if(m_Bitmap.m_hObject)
		m_Bitmap.DeleteObject();
	CDC*desktop=CDC::FromHandle(::GetDC(0));
	CDC dc;
	CFont*pOldFont=NULL;
	CBitmap*pOldBmp=NULL;
	int starty=0,startx=0;
	CRect rt,wrt;
	GetClientRect(&wrt);
	m_Size=wrt.Size();
	m_cSize=m_Size;
	dc.CreateCompatibleDC(desktop);
	dc.SetBkMode(TRANSPARENT);
	dc.SetBkColor(m_bgColor);
	int count=m_Array.GetSize();
	UINT flag=DT_EXTERNALLEADING;
	if(m_iDir)
		flag|=DT_WORDBREAK;
	for(int j=0;j<2;j++){	//1:calculate 2:draw
		for(int i=0;i<count;i++){//all items in Array
			LPSI pItem=m_Array.GetAt(i);
			if(!pItem->hBitmap){	//text item
				if(pItem->bVisited)
					dc.SetTextColor(m_lkVisited);
				else{
					if(pItem->bOwnColor)
						dc.SetTextColor(pItem->rgbColor);
					else{
						if(pItem->strLink.IsEmpty())
							dc.SetTextColor(m_fgColor);
						else
							dc.SetTextColor(m_lkColor);
					}
				}
				if(pItem->pFont){
					CFont*pTemp=dc.SelectObject(pItem->pFont);
					if(pOldFont==0)
						pOldFont=pTemp;
				}
				else{
					CFont*pTemp;
					if(pItem->strLink.IsEmpty())
						pTemp=dc.SelectObject(m_pFont);
					else
						pTemp=dc.SelectObject(m_plkFont);
					if(pOldFont==0)
						pOldFont=pTemp;
				}
				if(j==0){	//calculate
					starty+=pItem->nGap;
					if(!m_iDir){	//vertical
						rt.top=starty;
						rt.left=rt.right=pItem->nStartX;
						rt.bottom=wrt.Height();
					}
					else{	//horizontal
						rt.top=rt.bottom=starty;
						rt.left=pItem->nStartX;
						rt.right=wrt.Width();
					}
					dc.DrawText(pItem->strText,&rt,flag|DT_CALCRECT);
					pItem->m_rt=rt;
					starty+=rt.Height();
					if(startx<rt.right)
						startx=rt.right;
				}
				else{	//draw
					pItem->m_rt.OffsetRect(m_cSize);
					dc.DrawText(pItem->strText,&pItem->m_rt,flag);
				}
			}
			else{	//bitmap
				if(j==0){	//cal
					BITMAP bm;
					CBitmap*bmp=CBitmap::FromHandle(pItem->hBitmap);
					bmp->GetBitmap(&bm);
					starty+=pItem->nGap;
					pItem->m_rt=CRect(CPoint(pItem->nStartX,starty),CSize(bm.bmWidth,bm.bmHeight));
					dc.DrawState(pItem->m_rt.TopLeft(),pItem->m_rt.Size(),
						bmp,DST_BITMAP);
					starty+=bm.bmHeight;
					if(startx<bm.bmWidth+pItem->nStartX)
						startx=bm.bmWidth+pItem->nStartX;
				}
				else{	//draw
					CBitmap*bmp=CBitmap::FromHandle(pItem->hBitmap);
					pItem->m_rt.OffsetRect(m_cSize);
					dc.DrawState(pItem->m_rt.TopLeft(),pItem->m_rt.Size(),
						bmp,DST_BITMAP);
				}
			}
		}
		if(j==0){
			if(m_iDir)
				m_Size.cy=starty;
			else
				m_Size.cx=startx;
			m_Size.cx+=wrt.Width()*2;
			m_Size.cy+=wrt.Height()*2;
			m_Bitmap.CreateCompatibleBitmap(desktop,m_Size.cx,m_Size.cy);
			pOldBmp=dc.SelectObject(&m_Bitmap);
			if(!m_bkImage)
				dc.FillSolidRect(0,0,m_Size.cx,m_Size.cy,m_bgColor);
			else{
				CBrush br;
				CBitmap tbm;
				tbm.Attach(m_bkImage);
				br.CreatePatternBrush(&tbm);
				CRect prc(CPoint(0,0),m_Size);
				dc.FillRect(&prc,&br);
				tbm.Detach();
			}
		}
	}
	if(m_iDir)
		m_xCur=m_cSize.cx;
	else
		m_yCur=m_cSize.cy;
	dc.SelectObject(pOldFont);
	dc.SelectObject(pOldBmp);
	UpdateTips();
}

LRESULT CCreditCtrl::OnMouseLeave(WPARAM wParam,LPARAM lParam)
{
	if(!bTimer){
		bTimer=TRUE;
		SetTimer(1,20,0);
		m_wndTips.Activate(FALSE);
	}
	return 0;
}

void CCreditCtrl::OnMouseMove(UINT nFlags, CPoint point) 
{
	if(bTimer){
		KillTimer(1);
		bTimer=FALSE;
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE;
		_TrackMouseEvent(&tme);
		UpdateTips();
		m_wndTips.Activate(TRUE);
	}
	CWnd::OnMouseMove(nFlags, point);
}

void CCreditCtrl::OnLButtonDown(UINT nFlags, CPoint point) 
{
	CPoint pt=point;
	pt.Offset(m_xCur,m_yCur);	
	int count=m_Array.GetSize();
	if(count==0){
		CWnd::OnLButtonDown(nFlags, point);
		return;
	}
	BOOL bLink=FALSE;
	LPSI pItem=NULL;
	for(int i=0;i<count;i++){
		pItem=m_Array.GetAt(i);
		if(!pItem->strLink.IsEmpty()){
			if(pItem->m_rt.PtInRect(pt)){
				bLink=TRUE;
				break;
			}
		}
	}
	if(bLink){
		pItem->bVisited=TRUE;
		BuildBitmap();
		ShellExecute(NULL, _T("open"), pItem->strLink, NULL,NULL, SW_SHOWNORMAL);
	}
	CWnd::OnLButtonDown(nFlags, point);
}

void CCreditCtrl::SetScrollDirection(BOOL bVert)
{
	m_iDir=bVert;
	BuildBitmap();
	if(bVert){
		m_xCur=m_cSize.cx;
		m_yCur=0;
	}
	else{
		m_xCur=0;
		m_yCur=m_cSize.cy;
	}
}

void CCreditCtrl::AddBitmap(HBITMAP hBit, int gap,int startx,LPCTSTR link)
{
	LPSI pItem=new StringItem(hBit,startx,link,gap);
	m_Array.Add(pItem);
	bFlag=FALSE;
}

void CCreditCtrl::UpdateTips()
{
	if(bTimer)
		return;
	for(int i=m_iLinks;i>0;i--)
		m_wndTips.DelTool(this,i);
	m_iLinks=0;
	LPSI pItem=NULL;
	int count=m_Array.GetSize();
	CPoint pt;
	GetCursorPos(&pt);
	ScreenToClient(&pt);
	CRect rt;
	for(int j=0;j<count;j++){
		pItem=m_Array.GetAt(j);
		if(!pItem->strLink.IsEmpty()){
			m_iLinks++;
			rt=pItem->m_rt;
			rt.OffsetRect(-m_xCur,-m_yCur);
			m_wndTips.AddTool(this,pItem->strLink,&rt,m_iLinks);
		}
	}
	m_wndTips.Update();
}

BOOL CCreditCtrl::PreTranslateMessage(MSG* pMsg) 
{
	if(pMsg->message==WM_MOUSEMOVE)
		m_wndTips.RelayEvent(pMsg);	
	return CWnd::PreTranslateMessage(pMsg);
}

void CCreditCtrl::SetBkImage(HBITMAP hImage, BOOL bTile)
{
	if(m_bkImage)
		DeleteObject(m_bkImage);
	m_bkImage=hImage;
	m_bTileImage=bTile;
	bFlag=FALSE;
}

发表评论
切换编辑模式