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

📄 tearoffrebar.cpp

📁 软件参考Windows操作系统下的画图程序
💻 CPP
字号:
// TearoffReBar.cpp : implementation file
//

#include "stdafx.h"
#include "TearoffReBar.h"

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

/////////////////////////////////////////////////////////////////////////////
// CTearOffReBar

IMPLEMENT_DYNAMIC(CTearOffReBar, CReBar)

CTearOffReBar::CTearOffReBar()
:	m_hwndBand(NULL)
{
}

BEGIN_MESSAGE_MAP(CTearOffReBar, CReBar)
	//{{AFX_MSG_MAP(CTearOffReBar)
	ON_NOTIFY_REFLECT_EX(RBN_BEGINDRAG, OnBeginDrag) 
	ON_NOTIFY_REFLECT_EX(RBN_ENDDRAG, OnEndDrag) 
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

UINT CTearOffReBar::BandFromHWND(HWND hwnd)
{
	REBARBANDINFO rbi;
	memset(&rbi, 0, sizeof(rbi));
	rbi.cbSize = sizeof(rbi);
	rbi.fMask  = RBBIM_CHILD;

	for (UINT i = 0, iMax = SendMessage(RB_GETBANDCOUNT) ; i < iMax ; i++)
	{
		SendMessage(RB_GETBANDINFO, i, (LPARAM)&rbi);
		if (rbi.hwndChild == hwnd)
			return i;
	}

	return UINT_MAX;
}

/////////////////////////////////////////////////////////////////////////////
// CTearOffReBar message handlers

BOOL CTearOffReBar::OnBeginDrag(NMHDR* pNotifyStruct, LRESULT* result)
{
	NMREBAR* pnmrb = reinterpret_cast<NMREBAR*>(pNotifyStruct);

	// cache info about the band that is being dragged:
	REBARBANDINFO rbi;
	memset(&rbi, 0, sizeof(rbi));
	rbi.cbSize = sizeof(rbi);
	rbi.fMask  = RBBIM_CHILD;
	SendMessage(RB_GETBANDINFO, pnmrb->uBand, (LPARAM)&rbi);
	m_hwndBand = rbi.hwndChild;
											 
	return TRUE;
}

BOOL CTearOffReBar::OnEndDrag(NMHDR* pNotifyStruct, LRESULT* result)
{
	m_hwndBand = NULL;
	return TRUE;
}

void CTearOffReBar::OnMouseMove(UINT nFlags, CPoint pt) 
{
	// default:
	CReBar::OnMouseMove(nFlags, pt);

	// ensure dragging:
	if (this != GetCapture() || NULL == m_hwndBand)	return;

	// are we going to tear off?
	CRect rcl; GetClientRect(&rcl);
	rcl.InflateRect(10, 10);
	if (rcl.PtInRect(pt))
		return;

	// we're done tracking...
	ReleaseCapture();

	// we'll need these:
	UINT				uBand  = BandFromHWND(m_hwndBand);
	CFrameWnd*		pFrame = reinterpret_cast<CFrameWnd*>(AfxGetMainWnd());
	ASSERT_KINDOF(CFrameWnd, pFrame);
	CControlBar*	pBar   = reinterpret_cast<CControlBar*>(CWnd::FromHandle(m_hwndBand));
	ASSERT_KINDOF(CControlBar, pBar);
	DWORD dwStyle = pBar->m_dwStyle;

	// retrieve and cache band information:
	REBARBANDINFO rbi;
	char aszBuff[_MAX_PATH];
	memset(&rbi, 0, sizeof(rbi));
	rbi.cbSize = sizeof(rbi);
	rbi.fMask  = RBBIM_BACKGROUND | RBBIM_CHILDSIZE | RBBIM_COLORS | RBBIM_HEADERSIZE | RBBIM_IDEALSIZE | RBBIM_ID | RBBIM_IMAGE | RBBIM_LPARAM | RBBIM_SIZE | RBBIM_STYLE | RBBIM_TEXT | RBBIM_CHILD;
	rbi.cch	  = sizeof(aszBuff);
	rbi.lpText = aszBuff;
	SendMessage(RB_GETBANDINFO, uBand, (LPARAM)&rbi);

	// hide then delete the band:
	SendMessage(RB_SHOWBAND, uBand, FALSE);
	SendMessage(RB_DELETEBAND, uBand);
	pBar->ShowWindow(SW_SHOW);
	pBar->SetOwner(pFrame);

	// determine where to float the bar at:
	MapWindowPoints(NULL, &pt, 1);
	SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));

	// float the bar:
	pBar->EnableDocking(CBRS_ALIGN_ANY);
	CPoint ptCreate(pt); ptCreate.Offset(-10,-10);
	pFrame->FloatControlBar(pBar, ptCreate);
	pBar->EnableDocking(0);

	// pass the cached band info to the new frame to store:
	CMiniReBarDockFrameWnd* pMiniFrame = (CMiniReBarDockFrameWnd*)pBar->GetParentFrame();
	pMiniFrame->SetRebarBandInfo(rbi, dwStyle);

	// user continues to drag the new parent-frame:
	pBar->GetParentFrame()->SendMessage(WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM(pt.x, pt.y));
	m_hwndBand = NULL;
	AfxGetMainWnd()->RedrawWindow();
}




/////////////////////////////////////////////////////////////////////////////
// CMiniReBarDockFrameWnd

IMPLEMENT_DYNCREATE(CMiniReBarDockFrameWnd, CMiniDockFrameWnd)

CMiniReBarDockFrameWnd::CMiniReBarDockFrameWnd()
{
	memset(&m_rbi, 0, sizeof(m_rbi));
}

void CMiniReBarDockFrameWnd::SetRebarBandInfo(REBARBANDINFO& rbi, DWORD dwStyle)
{
	// copy rebar-band info:
	memcpy(&m_rbi, &rbi, sizeof(rbi));
	m_rbi.cch	 = sizeof(m_aszBuff);
	m_rbi.lpText = m_aszBuff;
	if (rbi.fMask & RBBIM_TEXT)
		strcpy(m_rbi.lpText, rbi.lpText);

	// cache bar style;
	m_dwStyle = dwStyle;
}

/////////////////////////////////////////////////////////////////////////////
// CMiniReBarDockFrameWnd message handlers

BEGIN_MESSAGE_MAP(CMiniReBarDockFrameWnd, CMiniDockFrameWnd)
	//{{AFX_MSG_MAP(CMiniReBarDockFrameWnd)
	ON_WM_NCLBUTTONDOWN()
	ON_WM_MOVING()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


void CMiniReBarDockFrameWnd::OnNcLButtonDown(UINT nHitTest, CPoint point) 
{
	// bypass CMiniDockFrameWnd:
	// (this enables full-window-drag for the window, which is disabled by CMiniDockFrameWnd)
	CMiniFrameWnd::OnNcLButtonDown(nHitTest, point);
}

CTearOffReBar* CMiniReBarDockFrameWnd::CalcDockingReBar(DWORD* pdwInsertPos, bool* pbHorizontal)
{
	// we'll be dealing with the frame, parent of the rebars:
	CFrameWnd* pFrame = reinterpret_cast<CFrameWnd*>(AfxGetMainWnd());
	ASSERT_KINDOF(CFrameWnd, pFrame);

	// find the rebar;  if more rebars exist (sides, bottom), extend this function to locate the 
	// correct one...
	CTearOffReBar* pReBar = NULL;
	CPoint pt; GetCursorPos(&pt);

	// get bar:
	pReBar = reinterpret_cast<CTearOffReBar*>(pFrame->GetDlgItem(AFX_IDW_REBAR));
	if (NULL == pReBar) return NULL;
	ASSERT_KINDOF(CTearOffReBar, pReBar);

	// get bar rectangle:
	CRect rclBar; pReBar->GetWindowRect(&rclBar);
	rclBar.InflateRect(4, 4);

	if (rclBar.PtInRect(pt))
	{
		*pbHorizontal = rclBar.Width() > rclBar.Height(); // this exists in case you have side-mounted rebars...
		*pdwInsertPos = (*pbHorizontal ? (pt.y < (rclBar.top+rclBar.bottom) / 2 ? 0 : -1) : (pt.x < rclBar.left ? 0 : -1) );
		return pReBar;
	}

	// nothing found:
	return NULL;
}

void CMiniReBarDockFrameWnd::OnMoving(UINT fwSide, LPRECT pRect) 
{
	// default:
	CMiniDockFrameWnd::OnMoving(fwSide, pRect);

	// are we going to dock?
	DWORD dwInsertPos(0);
	bool  bHorizontal(false);
	CTearOffReBar* pRebar = CalcDockingReBar(&dwInsertPos, &bHorizontal);
	if (NULL == pRebar) return;

	// get the toolbar...
	CControlBar* pBar = (CControlBar*)GetWindow(GW_CHILD)->GetWindow(GW_CHILD);
	pBar->m_dwStyle = m_dwStyle;
	pBar->CalcFixedLayout(0, bHorizontal);

	// insert a new band into the rebar:
	pRebar->SendMessage(RB_INSERTBAND, dwInsertPos, (LPARAM)&m_rbi);
	CRect rclReBar; pBar->GetWindowRect(&rclReBar);
	CPoint pt(rclReBar.left-5, rclReBar.top+5);
	m_wndDockBar.RemoveControlBar(pBar);
	pBar->m_pDockBar = NULL;

	// fake a button click so the dragging operation 
	//  moves seamlessly into the rebar internal dragging code:
	::MapWindowPoints(NULL, pRebar->GetSafeHwnd(), &pt, 1);
	pRebar->SetActiveWindow();
	pRebar->PostMessage(WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(pt.x, pt.y));
}

⌨️ 快捷键说明

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