📄 tearoffrebar.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 + -