www.gusucode.com > VC++指定区域抓图、截屏小程序-源码程序 > VC++指定区域抓图、截屏小程序-源码程序/code/FBCtrls.cpp

    //Download by http://www.NewXing.com
/*
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	文件:FBCtrls.cpp

	版权:Firebird Software Workroom

	声明:本源程序的版权受《中华人民共和国著作权法》以及其
		  它相关法律和条约的保护。任何有机会得到本源程序的
		  个人和机构,未经作者明确授权,不得将本源程序用于
		  任何商业目的(直接的或间接的)。对于非商业目的的使
		  用 (包括复制、传播、编译和修改), 原则上没有特别
		  的限制条款,但请在相关文档中说明其来源,并尊重原
		  作者的署名权。

	编写:秦传安(chings)	1999.12 - 2000.4

	联络:Tel:(0792)6323086	E_mail:chings@163.net
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
#include "fclstd.h"
#include "FBCtrls.h"
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

//######################################################################
//	class CFBToolBar
//	工具栏
//###################################################################
#define RT_TOOLBAR  MAKEINTRESOURCE(241)

struct TOOLBAR_DATA
{
	WORD wVersion;
	WORD wWidth;
	WORD wHeight;
	WORD wItemCount;

	WORD* items()
		{ return (WORD*)(this+1); }
};

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CFBToolBar::CFBToolBar()
{
	m_nHotItem = -1;
}

CFBToolBar::~CFBToolBar()
{
}
//////////////////////////////////////////////////////////////////////////////
//创建函数
BOOL CFBToolBar::Create(CFBWnd* pParent,UINT nStyle,UINT nID)
{
	if(!pParent)return FALSE;

	InitCommonControls();

	nStyle |= WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS |
			  TBSTYLE_BUTTON | TBSTYLE_TOOLTIPS|TBSTYLE_FLAT|TBSTYLE_AUTOSIZE|TBSTYLE_TRANSPARENT|
			  CCS_NOPARENTALIGN|CCS_NOMOVEY|CCS_NODIVIDER|CCS_NORESIZE;

	BOOL bRet  = CFBWnd::Create(TOOLBARCLASSNAME,
						NULL,
						pParent->GetInstance(),
						pParent,
						nStyle,
						NULL);

	if(bRet)
	{
		UINT style = GetClassLong(m_hWnd,GCL_STYLE);
		style |= CS_PARENTDC;
		SetClassLong(m_hWnd,GCL_STYLE,style);
	}

	return bRet;
}
////////////////////////////////////////////////////////////////////////
BOOL CFBToolBar::OnCreate()
{
    SendMessage(m_hWnd,TB_BUTTONSTRUCTSIZE,(WPARAM) sizeof(TBBUTTON),0); 
	return TRUE;
}
////////////////////////////////////////////////////////////////////////
//窗口过程
LRESULT CFBToolBar::WindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
{
	LRESULT lResult = 1;

	switch(msg)
	{
	case WM_COMMAND:
		if(m_pOwner)
			SendMessage(m_pOwner->m_hWnd,msg,wParam,lParam);
		lResult = 0;//WM_COMMAND 消息必须返回 0.
		break;
	case WM_NOTIFY:
		OnNotify((LPNMHDR)lParam,lResult);
		break;
	default:
		lResult = CFBWnd::WindowProc(msg,wParam,lParam);
		break;
	}

	return lResult;
}
///////////////////////////////////////////////////////////////////////////////
BOOL CFBToolBar::LoadToolBar(UINT nID)
{
	if(!m_hWnd)return FALSE;

	HRSRC hRsrc = ::FindResource(GetInstance(), MAKEINTRESOURCE(nID), RT_TOOLBAR);
	if (hRsrc == NULL)
		return FALSE;

	HGLOBAL hGlobal = LoadResource(GetInstance(), hRsrc);
	if (hGlobal == NULL)
		return FALSE;

	TOOLBAR_DATA* pData = (TOOLBAR_DATA*)LockResource(hGlobal);
	if (pData == NULL)
		return FALSE;

	BOOL bResult;
	TBBUTTON tbb;
	memset(&tbb,0,sizeof(TBBUTTON));
	tbb.iString = -1;
	int iImage = 0;

	for (int i = 0; i < pData->wItemCount; i++)
	{
		tbb.fsState = TBSTATE_ENABLED;
		tbb.idCommand = pData->items()[i];
		if(tbb.idCommand == 0)
		{
			tbb.fsStyle = TBSTYLE_SEP;
			tbb.iBitmap = -1;
		}
		else
		{
			tbb.fsStyle = TBSTYLE_BUTTON;
			tbb.iBitmap = iImage++;
		}

		bResult = AddButtons(1,&tbb);

		if(!bResult)return FALSE;
	}

	if(bResult)
	{
		TBADDBITMAP tbab;

		tbab.hInst = GetInstance();
		tbab.nID = nID;
		SendMessage(m_hWnd,TB_ADDBITMAP,(WPARAM)pData->wItemCount,(LPARAM)&tbab);
	}

	UnlockResource(hGlobal);
	FreeResource(hGlobal);

	return bResult;
}
////////////////////////////////////////////////////////////////////////////
void CFBToolBar::OnToolTip(LPTOOLTIPTEXT ptt)
{
	ptt->hinst = GetInstance();

	if(LoadString(GetInstance(),ptt->hdr.idFrom,m_pText,80) == 0)
		return;

	char* pchr = strchr(m_pText,'\n');

	if(pchr)
		pchr[0] = '\0';
	ptt->lpszText = m_pText;

	SendMessage(m_pOwner->m_hWnd,FBWM_NOTIFY,MAKEWPARAM(GetWndID(),FB_TTN_SHOWING),(LPARAM)(pchr+1));
}
/////////////////////////////////////////////////////////////////////
void CFBToolBar::OnNotify(LPNMHDR pNMHDR,LRESULT& lResult)
{
	lResult = 1;
	switch(pNMHDR->code)
	{
	case TTN_NEEDTEXT:
		if(GetHotItem() != m_nHotItem)
			OnToolTip((LPTOOLTIPTEXT)pNMHDR);
		break;
	case TTN_POP:
		SendMessage(m_pOwner->m_hWnd,FBWM_NOTIFY,MAKEWPARAM(GetWndID(),FB_TTN_HIDEN),0);
		break;
	case TBN_DROPDOWN:
		{
			LPNMTOOLBAR pnmtb = (LPNMTOOLBAR)pNMHDR;

			TBBUTTONINFOA tbi;
			tbi.cbSize = sizeof(tbi);
			tbi.dwMask = TBIF_COMMAND |TBIF_LPARAM;
			tbi.idCommand = pnmtb->iItem;

			int nIndex = SendMessage(m_hWnd,TB_COMMANDTOINDEX,(WPARAM)tbi.idCommand,0);

			SendMessage(m_hWnd,TB_GETBUTTONINFO,tbi.idCommand,(LPARAM)&tbi);
			HMENU hMenu = (HMENU)tbi.lParam;
			if(hMenu)
			{
				RECT rc;
				GetButtonRect(nIndex,&rc);
				ClientToScreen(m_hWnd,&rc);
				TrackPopupMenuEx(hMenu,
						TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
						rc.left,rc.bottom,m_pOwner->m_hWnd,NULL);
			}

			lResult = TBDDRET_DEFAULT;
		}
		break;
	case TBN_HOTITEMCHANGE:
		{
			LPNMTBHOTITEM phot = (LPNMTBHOTITEM)pNMHDR;
			if(phot->dwFlags & HICF_LEAVING)
				m_nHotItem = -1;
			else
				m_nHotItem = phot->idNew;
		}
		break;
	default:
		break;
	}
}
/////////////////////////////////////////////////////////////////////////
void CFBToolBar::CheckedButton(UINT uID,BOOL bCheck)
{
	UINT state = SendMessage(m_hWnd,TB_GETSTATE,uID,0);
	if(bCheck)
		state |= TBSTATE_CHECKED;
	else
		state &= ~TBSTATE_CHECKED;
	SendMessage(m_hWnd,TB_SETSTATE,uID,MAKELPARAM(state,0));
}
/////////////////////////////////////////////////////////////////////////////
void CFBToolBar::SetDropDowmBtn(UINT nID,HMENU hMenu)
{
	UINT style = SendMessage(m_hWnd,TB_GETEXTENDEDSTYLE,0,0);
	style |= TBSTYLE_EX_DRAWDDARROWS;
	SendMessage(m_hWnd,TB_SETEXTENDEDSTYLE,0,style);

	TBBUTTONINFOA tbi;
	tbi.cbSize = sizeof(tbi);
	tbi.dwMask = TBIF_STYLE|TBIF_LPARAM;
	tbi.idCommand = nID;

	SendMessage(m_hWnd,TB_GETBUTTONINFO,nID,(LPARAM)&tbi);

	tbi.fsStyle |= TBSTYLE_DROPDOWN;
	tbi.lParam = (LPARAM)hMenu;
	SendMessage(m_hWnd,TB_SETBUTTONINFO,nID,(LPARAM)&tbi);
}


//###################################################################
//	class CMenuBar
//	菜单栏
//###################################################################


#define MB_POPUPMENU		WM_USER+500
//////////////////////////////////////////////////////////////////////
//  构造函数和析构函数
//////////////////////////////////////////////////////////////////////

CMenuBar::CMenuBar()
{
	m_hMenu			= NULL;
}

CMenuBar::~CMenuBar()
{

}
////////////////////////////////////////////////////////////////////////////////
CMenuBar*		pMenuBar	= NULL;
HHOOK			g_hMsgHook	= NULL;
////////////////////////////////////////////////////////////////////////////////
LRESULT CMenuBar::MenuInputFilter(int nCode, WPARAM wParam, LPARAM lParam)
{
	MSG* pMsg = (MSG*)lParam;

	if(!pMenuBar || nCode!=MSGF_MENU)
		return CallNextHookEx(g_hMsgHook,nCode,wParam,lParam);
	if(pMenuBar->OnMenuInput(pMsg))
		return TRUE;
	else
		return CallNextHookEx(g_hMsgHook,nCode,wParam,lParam);
}
////////////////////////////////////////////////////////////////////////////
//	函数: LoadMenu
//	参数: hMenu		菜单句柄
//		  hMainWnd	主窗口句柄
//		  bRemove	是否移去窗口的主菜单
//	说明: 将菜单加载到工具栏上. 由于CMenuBar 是将主菜单从主窗口上剥离下来
//		  再加载到工具栏上, 所以应提供主窗口句柄以便向主窗口发送有关消息并让
//		  主窗口跟踪菜单命令
////////////////////////////////////////////////////////////////////////////
BOOL CMenuBar::LoadMenu(HMENU hMenu,BOOL bRemove)
{
	if(!m_hWnd || !hMenu)return FALSE;

	TBBUTTON		tbb; 
	int				i,nStr;
	BOOL			bRet;

	memset(&tbb,0,sizeof(TBBUTTON));

	tbb.fsState = TBSTATE_ENABLED;
	tbb.fsStyle = TBSTYLE_BUTTON|TBSTYLE_AUTOSIZE;

	m_nItemCount = GetMenuItemCount(hMenu);//菜单项目计数
	SetImageSize(0,0);//没有图标, 置图标尺寸为0.

	for(i=0;i<m_nItemCount;i++)
	{
		GetMenuString(hMenu,i,m_pText,80,MF_BYPOSITION);
		nStr = AddString(m_pText);
		tbb.iBitmap = -1;
		tbb.dwData = NULL;
		tbb.iString = nStr;
		tbb.idCommand = i+1;

		bRet = AddButtons(1,&tbb);

		if(!bRet)return FALSE;
	}

	if(bRemove)
		SetMenu(m_pOwner->m_hWnd,NULL);

	m_hMenu = hMenu;

	return bRet;
}
///////////////////////////////////////////////////////////////////////
//窗口过程
LRESULT CMenuBar::WindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
{
	LRESULT lResult = 1;

	if(msg == WM_LBUTTONDOWN)
		OnLButtonDown(wParam,LOWORD(lParam),HIWORD(lParam));
	else if(msg == MB_POPUPMENU)
		OnPopupMenu();
	else
		lResult = CFBToolBar::WindowProc(msg,wParam,lParam);

	return lResult;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//	函数: OnLButtonDown
void CMenuBar::OnLButtonDown(UINT fwKey,LONG x,LONG y)
{
	m_ptMouse.x = x;
	m_ptMouse.y = y;

	int nTest = SendMessage(m_hWnd,TB_HITTEST,0,(LPARAM)&m_ptMouse);

	if(nTest<0 || nTest>=m_nItemCount)
		return;

	m_nPressed = nTest;
	TrackPopup();
}
//////////////////////////////////////////////////////////////////////////
//跟踪弹出子菜单
/////////////////////////////////////////////////////////////////////////
void CMenuBar::TrackPopup()
{
	HMENU hSubMenu = GetSubMenu(m_hMenu,m_nPressed);//得到子菜单句柄
	if(hSubMenu == NULL)return;

	m_bTrack = TRUE;
	PressButton(m_nPressed,TRUE);//压下按钮

	//得到按钮矩形
	RECT rc;
	GetButtonRect(m_nPressed,&rc);
	ClientToScreen(m_hWnd,&rc);

	TPMPARAMS tpm;
	tpm.cbSize = sizeof(tpm);
	tpm.rcExclude = rc;

	//设置钩子函数
	pMenuBar = this;
	g_hMsgHook = SetWindowsHookEx(WH_MSGFILTER,
			MenuInputFilter, NULL, GetCurrentThreadId());

	//跟踪菜单弹出
	TrackPopupMenuEx(hSubMenu,
				TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
				rc.left,rc.bottom,m_pOwner->m_hWnd,&tpm);

	PressButton(m_nPressed,FALSE);
	UnhookWindowsHookEx(g_hMsgHook);//解除钩子函数

	g_hMsgHook = NULL;
	pMenuBar = NULL;
}
/////////////////////////////////////////////////////////////////////////////////
BOOL CMenuBar::OnMenuInput(MSG* pMsg)
{
	BOOL bResult = FALSE;

	switch(pMsg->message)
	{
	case WM_MOUSEMOVE:
		{
			POINT pt;
			pt.x = LOWORD(pMsg->lParam);
			pt.y = HIWORD(pMsg->lParam);
			ScreenToClient(m_hWnd,&pt);
			if(m_ptMouse.x == pt.x && m_ptMouse.y == pt.y)
				return TRUE;
		
			m_ptMouse.x = pt.x;
			m_ptMouse.y = pt.y;

			int nTest = SendMessage(m_hWnd,TB_HITTEST,0,(LPARAM)&pt);

			if(nTest>=0 && nTest<m_nItemCount && nTest != m_nPressed)
			{
				PressButton(m_nPressed,FALSE);
				PostMessage(m_pOwner->m_hWnd,WM_CANCELMODE,0,0);
				m_nPressed = nTest;
				PostMessage(m_hWnd,MB_POPUPMENU,0,0);
				bResult = TRUE;
			}
		}
		break;
	case WM_LBUTTONDOWN:
		{
			POINT pt;
			pt.x = LOWORD(pMsg->lParam);
			pt.y = HIWORD(pMsg->lParam);
			ScreenToClient(m_hWnd,&pt);
			PostMessage(m_pOwner->m_hWnd,FBWM_NOTIFY,MAKEWPARAM(GetWndID(),FB_TTN_HIDEN),0);

			int nTest = SendMessage(m_hWnd,TB_HITTEST,0,(LPARAM)&pt);

			if(nTest<0)
				m_bTrack = FALSE;
			else if(nTest == m_nPressed)
			{
				m_bTrack = FALSE;
				PostMessage(m_pOwner->m_hWnd,WM_CANCELMODE,0,0);
				bResult = TRUE;
			}
		}
		break;
	case WM_KEYDOWN:
		{
			TCHAR vkey = pMsg->wParam;
			if(vkey == VK_LEFT)
			{
				PressButton(m_nPressed,FALSE);
				m_nPressed --;
				PostMessage(m_pOwner->m_hWnd,WM_CANCELMODE,0,0);
				PostMessage(m_hWnd,MB_POPUPMENU,0,0);
				bResult = TRUE;
			}
			else if(vkey == VK_RIGHT)
			{
				PressButton(m_nPressed,FALSE);
				m_nPressed ++;
				PostMessage(m_pOwner->m_hWnd,WM_CANCELMODE,0,0);
				PostMessage(m_hWnd,MB_POPUPMENU,0,0);
				bResult = TRUE;
			}
			else if (vkey == VK_ESCAPE)
			{
				PostMessage(m_pOwner->m_hWnd,FBWM_NOTIFY,MAKEWPARAM(GetWndID(),FB_TTN_HIDEN),0);
				PostMessage(m_pOwner->m_hWnd,WM_CANCELMODE,0,0);
				m_bTrack = FALSE;
				bResult = TRUE;
			}
		}
		break;
	case WM_MENUSELECT:
		OnMenuSelect(pMsg->wParam,pMsg->lParam);
		break;
	default:
		break;
	}

	return bResult;
}
////////////////////////////////////////////////////////////////////////////
void CMenuBar::OnPopupMenu()
{
	if(m_nPressed<0)
		m_nPressed = m_nItemCount - 1;
	if(m_nPressed>=m_nItemCount)
		m_nPressed = 0;
	TrackPopup();
}
//////////////////////////////////////////////////////////////////////////////
void CMenuBar::OnMenuSelect(WPARAM wParam,LPARAM lParam)
{
	UINT uItem = (UINT) LOWORD(wParam);
	if(!LoadString(GetInstance(),uItem,m_pText,80))
	{
		strcpy(m_pText,"\n就绪");
	}

	char* pchr = strchr(m_pText,'\n');
	if(pchr >= (m_pText+80))
	{
		strcpy(m_pText,"\n就绪");
		pchr = m_pText;
	}
	SendMessage(m_pOwner->m_hWnd,FBWM_NOTIFY,MAKEWPARAM(GetWndID(),FB_TTN_SHOWING),(LPARAM)pchr+1);
}
/////////////////////////////////////////////////////////////////////////
void CMenuBar::CheckMenuItem(UINT uID,BOOL bCheck)
{
	UINT flag;
	if(bCheck)
		flag = MF_CHECKED;
	else
		flag = MF_UNCHECKED;
	::CheckMenuItem(m_hMenu,uID,flag);
}
/////////////////////////////////////////////////////////////////////////
BOOL CMenuBar::GetMenuItemCheckState(UINT uID)
{
	MENUITEMINFO miif;
	miif.cbSize = sizeof(miif);
	miif.fMask = MIIM_ID|MIIM_STATE;
	miif.wID =uID;
	GetMenuItemInfo(m_hMenu,uID,FALSE,&miif);

	if(miif.fState&MFS_CHECKED)
		return TRUE;
	else
		return FALSE;
}
//////////////////////////////////////////////////////////////////////
BOOL CMenuBar::EnableMenuItem(UINT uID,BOOL bEnable)
{
	MENUITEMINFO miif;
	miif.cbSize = sizeof(miif);
	miif.fMask = MIIM_ID|MIIM_STATE;
	miif.wID =uID;
	if(bEnable)
		miif.fState = MFS_ENABLED;
	else
		miif.fState = MFS_DISABLED;
	
	return SetMenuItemInfo(m_hMenu,uID,FALSE,&miif);
}

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

//###################################################################
//	class CFBStatusBar
//	状态栏
//###################################################################

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CFBStatusBar::CFBStatusBar()
{

}

CFBStatusBar::~CFBStatusBar()
{

}
/////////////////////////////////////////////////////////////////////
CFBStatusBar::Create(CFBWnd* pParent,UINT uID)
{
	if(!pParent)return FALSE;

	InitCommonControls();

	UINT nStyle = WS_VISIBLE|WS_CHILD|WS_CLIPSIBLINGS|
				  CCS_NOPARENTALIGN|CCS_NODIVIDER|CCS_NORESIZE |
				  WS_CLIPCHILDREN|SBARS_SIZEGRIP;

	return CFBWnd::Create(STATUSCLASSNAME,
						NULL,
						pParent->GetInstance(),
						pParent,
						nStyle);
}
////////////////////////////////////////////////////////////////////////////
LRESULT CFBStatusBar::WindowProc(UINT msg,WPARAM wParam,LPARAM lParam)
{
	if(msg == FBWM_SETSIZE)
	{
		if(IsShow())
			OnSetSize((LPRECT)lParam);

		return 1;
	}
	else if(msg == WM_LBUTTONUP || msg == WM_LBUTTONDBLCLK)
		return DefWindowProc(m_hWnd,msg,wParam,lParam);
	else
		return CFBWnd::WindowProc(msg,wParam,lParam);

}
////////////////////////////////////////////////////////////////////////////////////////////
void CFBStatusBar::SetText(int nIndex,LPCTSTR strText)
{
	if(nIndex<0 || nIndex>m_nParts)return;

	SendMessage(m_hWnd,SB_SETTEXT,(WPARAM)nIndex,(LPARAM)strText);

}
////////////////////////////////////////////////////////////////////////////////////////////
void CFBStatusBar::SetParts(int nParts,LPINT lpParts)
{
	if(!nParts)return;

	m_nParts = nParts;
	SendMessage(m_hWnd, SB_SETPARTS, (WPARAM) m_nParts,(LPARAM)lpParts);
}
////////////////////////////////////////////////////////////////////////////////////////////
void CFBStatusBar::OnSetSize(LPRECT pRect)
{
	RECT rc;
	CopyRect(&rc,pRect);
	int pParts[32];
	SendMessage(m_hWnd,SB_GETPARTS,(WPARAM)m_nParts,(LPARAM)pParts);
	int space = (int)(pRect->right - pRect->left - pParts[m_nParts-1])/m_nParts;
	int sp = 0;
	for(int i=0;i<m_nParts;i++)
	{
		sp += space;
		pParts[i] += sp;
	}
	SendMessage(m_hWnd, SB_SETPARTS, (WPARAM) m_nParts,(LPARAM)pParts);

	rc.top = rc.bottom - 20;
	SetWindowPos(m_hWnd,NULL,rc.left,rc.top,
				rc.right - rc.left,rc.bottom - rc.top,
				SWP_NOZORDER|SWP_NOACTIVATE|SWP_NOCOPYBITS);
	pRect->bottom -= rc.bottom - rc.top;
}
//////////////////////////////////////////////////////////////////////