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

📄 bcgsizingcontrolbar.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//*******************************************************************************
// COPYRIGHT NOTES
// ---------------
// This source code is a part of BCGControlBar library.
// You may use, compile or redistribute it as part of your application 
// for free. You cannot redistribute it as a part of a software development 
// library without the agreement of the author. If the sources are 
// distributed along with the application, you should leave the original 
// copyright notes in the source code without any changes.
// This code can be used WITHOUT ANY WARRANTIES on your own risk.
// 
// Stas Levin <stas@iet.co.il>
//*******************************************************************************

/////////////////////////////////////////////////////////////////////////
// Copyright (C) 1998, 1999 by Cristi Posea
// All rights reserved
//
// THIS SOURCE CODE WAS INCLUDED INTO THE BCGCONTROLBAR LIBRARY UNDER THE
// PERSONAL PERMISSION OF CRISTI POSEA.
//
// Use and distribute freely, except: don't remove my name from the
// source or documentation (don't take credit for my work), mark your
// changes (don't get me blamed for your possible bugs), don't alter
// or remove this notice.
// No warrantee of any kind, express or implied, is included with this
// software; use at your own risk, responsibility for damages (if any) to
// anyone resulting from the use of this software rests entirely with the
// user.
//
// This class is intended to be used as a base class. Do not simply add
// your code to this file - instead create a new class derived from
// CBCGSizingControlBar and put there what you need.
// Modify this file only to fix bugs, and don't forget to send me a copy.
//
// Send bug reports, bug fixes, enhancements, requests, flames, etc.,
// and I'll try to keep a version up to date.  I can be reached at:
//    cristip@dundas.com
//
// More details at MFC Programmer's SourceBook
// http://www.codeguru.com/docking/docking_window.shtml or search
// www.codeguru.com for my name if the article was moved.
//
/////////////////////////////////////////////////////////////////////////
//
// Acknowledgements:
//  o   Thanks to Harlan R. Seymour (harlans@dundas.com) for his continuous
//      support during development of this code.
//  o   Thanks to Dundas Software for the opportunity to test this code
//      on real-life applications.
//      If you don't know who they are, visit them at www.dundas.com .
//      Their award winning components and development suites are
//      a pile of gold.
//  o   Thanks to Chris Maunder (chrism@dundas.com) who came with the
//      simplest way to query "Show window content while dragging" system
//      setting.
//  o   Thanks to Zafir Anjum (zafir@codeguru.com) for publishing this
//      code on his cool site (www.codeguru.com).
//  o   Some ideas for the gripper came from the CToolBarEx flat toolbar
//      by Joerg Koenig (Joerg.Koenig@rhein-neckar.de). Also he inspired
//      me on writing this notice:) . Thanks, Joerg!
//  o   Thanks to Jakawan Ratiwanich (jack@alpha.fsec.ucf.edu) and to
//      Udo Schaefer (Udo.Schaefer@vcase.de) for the dwStyle bug fix under
//      VC++ 6.0.
//  o   And, of course, many thanks to all of you who used this code,
//      for the invaluable feedback I received.
//      
// Partialy modified by Stas Levin - stas@iet.co.il.
// The following features were added:
//
//	o	Drawing splitter bar between the control bars
//	o	Change cursor when mouse is over splitter bar
//	o	Expand/Contract control bars
//	o	Button tooltips
//
/////////////////////////////////////////////////////////////////////////


// BCGSizingControlBar.cpp : implementation file
//

#include "stdafx.h"
#include "BCGSizingControlBar.h"
#include "BCGControlBarImpl.h"
#include "BCGtoolbar.h"
#include "bcglocalres.h"
#include "bcgbarres.h"
#include "BCGDockBar.h"
#include "globals.h"
#include "RegPath.h"
#include "BCGDockContext.h"

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

/////////////////////////////////////////////////////////////////////////////
// CBCGSizingControlBar

static const CString strSCBProfile = _T("BCGSizingControlBar");
static const UINT uiHotBtnTimerId = 1;
static const UINT uiHotBtnTimerDelay = 10;

CSCBArray CBCGSizingControlBar::m_arrBars; // static member

/////////////////////////////////////////////////////////////////////////////
// All CBCGSizingControlBar collection:
CObList	gAllSizingControlBars;

IMPLEMENT_DYNAMIC(CBCGSizingControlBar, CControlBar);

CBCGSizingControlBar::CBCGSizingControlBar()
{
    m_szMin = CSize (33, 32);
    m_szHorz = CSize(200, 200);
    m_szVert = CSize(200, 200);
    m_szFloat = CSize(200, 200);
    m_bTracking = FALSE;
    m_bKeepSize = FALSE;
    m_bParentSizing = FALSE;
	m_cxEdge = 7;
    m_nDockBarID = 0;
    m_dwSCBStyle = 0;
	m_bMaximized = FALSE;
	m_nTrackingPushedButton = -1;

	m_Buttons [0].m_nHit = HTCLOSE;
	m_Buttons [1].m_nHit = HTMAXBUTTON;

	m_Buttons [0].m_uiTT = IDS_BCGBARRES_HIDE_BAR;
	m_Buttons [1].m_uiTT = IDS_BCGBARRES_EXPAND_BAR;

	m_bIsSingleInRow = FALSE;

	m_ptOld = CPoint (0, 0);
	m_szMaxT = CSize (0, 0);
	m_szOld = CSize (0, 0);
}

CBCGSizingControlBar::~CBCGSizingControlBar()
{
}

BEGIN_MESSAGE_MAP(CBCGSizingControlBar, CControlBar)
    //{{AFX_MSG_MAP(CBCGSizingControlBar)
    ON_WM_CREATE()
    ON_WM_NCPAINT()
    ON_WM_NCCALCSIZE()
    ON_WM_NCHITTEST()
    ON_WM_CAPTURECHANGED()
    ON_WM_LBUTTONUP()
    ON_WM_MOUSEMOVE()
    ON_WM_NCLBUTTONDOWN()
    ON_WM_LBUTTONDOWN()
    ON_WM_LBUTTONDBLCLK()
    ON_WM_RBUTTONDOWN()
    ON_WM_WINDOWPOSCHANGING()
    ON_WM_PAINT()
	ON_WM_SETCURSOR()
	ON_WM_NCMOUSEMOVE()
	ON_WM_NCLBUTTONDBLCLK()
	ON_WM_TIMER()
	ON_WM_DESTROY()
	ON_WM_NCRBUTTONUP()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

BOOL CBCGSizingControlBar::Create(LPCTSTR lpszWindowName, CWnd* pParentWnd,
                               CSize sizeDefault, BOOL bHasGripper,
                               UINT nID, DWORD dwStyle)
{
    // must have a parent
    ASSERT_VALID(pParentWnd);
    // cannot be both fixed and dynamic
    // (CBRS_SIZE_DYNAMIC is used for resizng when floating)
    ASSERT (!((dwStyle & CBRS_SIZE_FIXED) &&
              (dwStyle & CBRS_SIZE_DYNAMIC)));

    m_dwStyle = dwStyle & CBRS_ALL; // save the control bar styles

    m_szHorz = sizeDefault; // set the size members
    m_szVert = sizeDefault;
    m_szFloat = sizeDefault;

    m_cyGripper = bHasGripper ? 12 : 0; // set the gripper width

    // register and create the window - skip CControlBar::Create()
    CString wndclass = ::AfxRegisterWndClass(CS_DBLCLKS,
        ::LoadCursor(NULL, IDC_ARROW),
        ::GetSysColorBrush(COLOR_BTNFACE), 0);

    dwStyle &= ~CBRS_ALL; // keep only the generic window styles
    dwStyle |= WS_CLIPCHILDREN; // prevents flashing
    if (!CWnd::Create(wndclass, lpszWindowName, dwStyle,
        CRect(0, 0, 0, 0), pParentWnd, nID))
        return FALSE;

    SetBarStyle (GetBarStyle() | CBRS_SIZE_DYNAMIC);

    return TRUE;
}
//**********************************************************************************
void CBCGSizingControlBar::EnableDocking(DWORD dwDockStyle)
{
	// By Erwin Tratar

	CControlBar::EnableDocking(dwDockStyle);

	if (m_pDockContext != NULL) 
	{
		delete m_pDockContext;
		m_pDockContext = NULL;
	}

	if (m_pDockContext == NULL)
	{
		m_pDockContext = new CBCGDockContext (this);
	}
}

/////////////////////////////////////////////////////////////////////////
// CBCGSizingControlBar message handlers

int CBCGSizingControlBar::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
    if (CControlBar::OnCreate(lpCreateStruct) == -1)
        return -1;

    m_arrBars.Add(this);        // register
    
    m_dwSCBStyle |= SCBS_SHOWEDGES;

	EnableToolTips ();

	m_wndToolTip.Create (this);
	m_wndToolTip.Activate (TRUE);

	CBCGLocalResource localRes;
	for (int i = 0; i < CBCGSIZINGCONTROLBAR_BUTTONS_NUM; i ++)
	{
		CSCBButton& btn = m_Buttons [i];

		CRect rectDummy;
		rectDummy.SetRectEmpty ();

		m_wndToolTip.AddTool (this, btn.m_uiTT, &rectDummy, i + 1);
	}

	if (globalData.m_hcurStretch == NULL)
	{
		globalData.m_hcurStretch = AfxGetApp ()->LoadCursor (AFX_IDC_HSPLITBAR);
	}

	if (globalData.m_hcurStretchVert == NULL)
	{
		globalData.m_hcurStretchVert = AfxGetApp ()->LoadCursor (AFX_IDC_VSPLITBAR);
	}

	gAllSizingControlBars.AddTail (this);
    return 0;
}

void CBCGSizingControlBar::OnDestroy() 
{
	for (POSITION pos = gAllSizingControlBars.GetHeadPosition (); pos != NULL;)
	{
		POSITION posSave = pos;

		CBCGSizingControlBar* pBar = (CBCGSizingControlBar*) gAllSizingControlBars.GetNext (pos);
		ASSERT (pBar != NULL);

		if (CWnd::FromHandlePermanent (pBar->m_hWnd) != NULL)
		{
			ASSERT_VALID (pBar);

			if (pBar == this)
			{
				gAllSizingControlBars.RemoveAt (posSave);
				break;
			}
		}
	}

	CControlBar::OnDestroy();
}

BOOL CBCGSizingControlBar::DestroyWindow() 
{
    int nPos = FindSizingBar(this);
    ASSERT(nPos >= 0);

    m_arrBars.RemoveAt(nPos);   // unregister

    return CControlBar::DestroyWindow();
}

const BOOL CBCGSizingControlBar::IsFloating() const
{
    return !IsHorzDocked() && !IsVertDocked();
}

const BOOL CBCGSizingControlBar::IsHorzDocked() const
{
    return (m_nDockBarID == AFX_IDW_DOCKBAR_TOP ||
        m_nDockBarID == AFX_IDW_DOCKBAR_BOTTOM);
}

const BOOL CBCGSizingControlBar::IsVertDocked() const
{
    return (m_nDockBarID == AFX_IDW_DOCKBAR_LEFT ||
        m_nDockBarID == AFX_IDW_DOCKBAR_RIGHT);
}

const BOOL CBCGSizingControlBar::IsSideTracking() const
{
    // don't call this when not tracking
    ASSERT(m_bTracking && !IsFloating());

    return (m_htEdge == HTLEFT || m_htEdge == HTRIGHT) ?
        IsHorzDocked() : IsVertDocked();
}

CSize CBCGSizingControlBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
    if (bStretch) // the bar is stretched (is not the child of a dockbar)
        if (bHorz)
            return CSize(32767, m_szHorz.cy);
        else
            return CSize(m_szVert.cx, 32767);

    // dirty cast - using CBCGDockBar to access protected CDockBar members
    CBCGDockBar* pDockBar = (CBCGDockBar*) m_pDockBar;

    // force imediate RecalcDelayShow() for all sizing bars on the row
    // with delayShow/delayHide flags set to avoid IsVisible() problems
    CSCBArray arrSCBars;
    GetRowSizingBars(arrSCBars);
    AFX_SIZEPARENTPARAMS layout;
    layout.hDWP = pDockBar->m_bLayoutQuery ?
        NULL : ::BeginDeferWindowPos(arrSCBars.GetSize());

    for (int i = 0; i < arrSCBars.GetSize(); i++)
	{
		arrSCBars[i]->RecalcDelayShow(&layout);
	}

	m_bIsSingleInRow = (arrSCBars.GetSize() < 2);

    if (layout.hDWP != NULL)
        ::EndDeferWindowPos(layout.hDWP);

    // get available length
    CRect rc = pDockBar->m_rectLayout;
    if (rc.IsRectEmpty())
        m_pDockSite->GetClientRect(&rc);

    int nLengthAvail = bHorz ? rc.Width(): rc.Height() - 2;

    if (IsVisible() && !IsFloating() &&
        m_bParentSizing && arrSCBars[0] == this)
        if (NegociateSpace(nLengthAvail, (bHorz != FALSE)))
            AlignControlBars();

    m_bParentSizing = FALSE;
    
    CSize szRet = bHorz ? m_szHorz : m_szVert;

	szRet.cx = max(m_szMin.cx, szRet.cx);
	szRet.cy = max(m_szMin.cy, szRet.cy);

    return szRet;
}

CSize CBCGSizingControlBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
    if (dwMode & (LM_HORZDOCK | LM_VERTDOCK)) // docked ?
    {
        if (nLength == -1)
            m_bParentSizing = TRUE;

        return CControlBar::CalcDynamicLayout(nLength, dwMode);
    }

    if (dwMode & LM_MRUWIDTH) return m_szFloat;
    if (dwMode & LM_COMMIT) return m_szFloat; // already committed

    ((dwMode & LM_LENGTHY) ? m_szFloat.cy : m_szFloat.cx) = nLength;

    m_szFloat.cx = max(m_szFloat.cx, m_szMin.cx);
    m_szFloat.cy = max(m_szFloat.cy, m_szMin.cy);

    return m_szFloat;
}

void CBCGSizingControlBar::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
{
    // force non-client recalc if moved or resized
    lpwndpos->flags |= SWP_FRAMECHANGED;

    CControlBar::OnWindowPosChanging(lpwndpos);

    // find on which side are we docked
    m_nDockBarID = GetParent()->GetDlgCtrlID();

    if (!IsFloating())
        if (lpwndpos->flags & SWP_SHOWWINDOW)
            m_bKeepSize = TRUE;
}

/////////////////////////////////////////////////////////////////////////
// Mouse Handling
//
void CBCGSizingControlBar::OnLButtonDown(UINT nFlags, CPoint point) 
{
    if (m_pDockBar != NULL)
    {
///// By Erwin Tratar
		KillTimer (uiHotBtnTimerId);
//// 

		for (int i = 0; i < CBCGSIZINGCONTROLBAR_BUTTONS_NUM; i ++)
		{
			CSCBButton& btn = m_Buttons [i];
			if (btn.m_bFocused || btn.m_bPushed)
			{
				btn.m_bFocused = btn.m_bPushed = FALSE;
				m_nTrackingPushedButton = -1;

				RedrawWindow (btn.GetRect (), NULL,
					RDW_INVALIDATE | RDW_UPDATENOW | RDW_FRAME);
			}
		}

		CRect rcBar;
		GetWindowRect (rcBar);

		CRect rcClient;
	    GetClientRect(rcClient);
        ClientToScreen(&rcClient);
  
        // start the drag
        ASSERT(m_pDockContext != NULL);
        ClientToScreen(&point);

		if( rcClient.PtInRect(point) ) 
		{
	        m_pDockContext->StartDrag(point);
		}
		else if ( rcBar.PtInRect(point) ) 
		{
			UINT nHitTest = OnNcHitTest(point);
			OnNcLButtonDown(nHitTest,point);
		}
    }
    else
        CWnd::OnLButtonDown(nFlags, point);
}

void CBCGSizingControlBar::OnLButtonDblClk(UINT nFlags, CPoint point) 
{
    if (m_pDockBar != NULL)
    {
        // toggle docking
        ASSERT(m_pDockContext != NULL);
        m_pDockContext->ToggleDocking();
    }
    else
        CWnd::OnLButtonDblClk(nFlags, point);
}

void CBCGSizingControlBar::OnNcLButtonDown(UINT nHitTest, CPoint point) 
{
    if (IsFloating())
    {
        CControlBar::OnNcLButtonDown(nHitTest, point);
        return;
    }

    if (m_bTracking) return;

⌨️ 快捷键说明

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