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

📄 sizablerebar.cpp

📁 一个多窗口的浏览器的程序benbrowse
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////
// SizableReBar.cpp: implementation of the CSizableReBar class.
//
/////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2001 by Nikolay Denisov. All rights reserved.
//
// This code is free for personal and commercial use, providing this 
// notice remains intact in the source files and all eventual changes are
// clearly marked with comments.
//
// You must obtain the author's consent before you can include this code
// in a software library.
//
// 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.
//
// Please email bug reports, bug fixes, enhancements, requests and
// comments to: nick@actor.ru
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "MenuBar.h"
#include "SizableReBar.h"
#include "ToolBarEx.h"
#include "WinAppEx.h"
#include "..\generaldata.h"

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

/////////////////////////////////////////////////////////////////////////////
// CSizableReBar

LPCTSTR CSizableReBar::m_lpszStateInfoFormat = _T("wID=%04X,cx=%d,fStyle=%08X");
LPCTSTR CSizableReBar::m_lpszStateInfoEntry  = _T("RebarStateInfo (v1.01)");

IMPLEMENT_DYNAMIC( CSizableReBar, CControlBar )

CSizableReBar::CSizableReBar()
{
    m_szCurrent   = CSize( 0, 0 );
    m_bTracking   = false;
    m_cxEdge      = 3;
    m_cyEdge      = 3;
    m_hbmBack     = 0;
    m_bCommonPart = true;
    m_bCustomPart = true;
}

CSizableReBar::~CSizableReBar()
{
}

/////////////////////////////////////////////////////////////////////////////
// Operations

bool CSizableReBar::Create( CWnd* pParentWnd, UINT nID, DWORD dwStyle )
{
    ASSERT_VALID( pParentWnd );     // must have a parent
    ASSERT( !( ( dwStyle & CBRS_SIZE_FIXED ) && ( dwStyle & CBRS_SIZE_DYNAMIC ) ) );

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

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

    dwStyle &= ~CBRS_ALL;       // keep only the generic window styles
    dwStyle |= WS_CLIPCHILDREN; // prevents flashing

    if ( !CWnd::Create( strWndClass, 0, dwStyle, CRect( 0, 0, 0, 0 ), pParentWnd, nID ) )
    {
        return false;
    }

    return true;
}

bool CSizableReBar::AddBar( CWnd* pBar, LPCTSTR pszText, CBitmap* pbmp,
                            DWORD dwStyle, LPCTSTR lpszTitle, bool bAlwaysVisible )
{
    if ( !m_wndReBar.AddBar( pBar, pszText, pbmp, dwStyle ) )
    {
        return false;
    }

    return PostAddBar( pBar, lpszTitle, bAlwaysVisible );
}

bool CSizableReBar::AddBar( CWnd* pBar, COLORREF clrFore, COLORREF clrBack, LPCTSTR pszText,
                            DWORD dwStyle, LPCTSTR lpszTitle, bool bAlwaysVisible )
{
    if ( !m_wndReBar.AddBar( pBar, clrFore, clrBack, pszText, dwStyle ) )
    {
        return false;
    }

    return PostAddBar( pBar, lpszTitle, bAlwaysVisible );
}

bool CSizableReBar::SetBkImage( CBitmap* pbmp )
{
    m_hbmBack = *pbmp;

    REBARBANDINFO rbbi;
    rbbi.cbSize = sizeof( rbbi );
    rbbi.fMask  = RBBIM_BACKGROUND;

    CReBarCtrl& rbCtrl = m_wndReBar.GetReBarCtrl();
    for ( UINT nBand = 0; nBand < rbCtrl.GetBandCount(); nBand++ )
    {
        rbbi.hbmBack = m_hbmBack;
        VERIFY( rbCtrl.SetBandInfo( nBand, &rbbi ) );
    }

    return true;
}

void CSizableReBar::EnableContextMenu( bool bCommonPart /*=true*/, bool bCustomPart /*=true*/ )
{
    m_bCommonPart = bCommonPart;
    m_bCustomPart = bCustomPart;
}

void CSizableReBar::LoadState( LPCTSTR lpszProfileName )
{
    // This function restores index, width and style from the registry for
    // each band in the rebar.

    CString strValue = AfxGetApp()->GetProfileString( lpszProfileName,
        m_lpszStateInfoEntry );
    if ( !strValue.IsEmpty() )
    {
        REBARBANDINFO rbbi;
        rbbi.cbSize = sizeof( rbbi );
        rbbi.fMask  = RBBIM_STYLE | RBBIM_SIZE | RBBIM_ID;

        CReBarCtrl& rbCtrl = m_wndReBar.GetReBarCtrl();
        for ( UINT nBand = 0; nBand < rbCtrl.GetBandCount(); nBand++ )
        {
            CString strBandState;
            VERIFY( AfxExtractSubString( strBandState, strValue, nBand, _T('\n') ) );

            UINT nID, cx, nStyle;
            int nResult = _stscanf( strBandState, m_lpszStateInfoFormat, &nID, &cx, &nStyle );
            ASSERT( nResult == 3 );

            rbCtrl.MoveBand( rbCtrl.IDToIndex( nID ), nBand );
            VERIFY( rbCtrl.GetBandInfo( nBand, &rbbi ) );
            rbbi.cx     = cx;
            rbbi.fStyle = ( rbbi.fStyle & ~( RBBS_HIDDEN | RBBS_BREAK ) ) | nStyle;
            VERIFY( rbCtrl.SetBandInfo( nBand, &rbbi ) );
        }
    }
}

void CSizableReBar::SaveState( LPCTSTR lpszProfileName )
{
    // This function saves index, width and style in the registry for each
    // band in the rebar, so that it could be possible to restore all these
    // settings when the user runs the program next time.

    CString strValue;

    REBARBANDINFO rbbi;
    rbbi.cbSize = sizeof( rbbi );
    rbbi.fMask  = RBBIM_STYLE | RBBIM_SIZE | RBBIM_ID;

    CReBarCtrl& rbCtrl = m_wndReBar.GetReBarCtrl();
    for ( UINT nBand = 0; nBand < rbCtrl.GetBandCount(); nBand++ )
    {
        VERIFY( rbCtrl.GetBandInfo( nBand, &rbbi ) );

        CString strBandState;
        strBandState.Format( m_lpszStateInfoFormat, rbbi.wID, rbbi.cx, rbbi.fStyle );
        strValue += ( strValue.IsEmpty() ? _T("") : _T("\n") ) + strBandState;
    }

    VERIFY( AfxGetApp()->WriteProfileString( lpszProfileName,
        m_lpszStateInfoEntry, strValue ) );
}

CReBarCtrl& CSizableReBar::GetReBarCtrl() const
{
    return m_wndReBar.GetReBarCtrl();
}

/////////////////////////////////////////////////////////////////////////////
// Implementation

bool CSizableReBar::PostAddBar( CWnd* pBar, LPCTSTR lpszTitle, bool bAlwaysVisible )
{
       REBARBANDINFO rbbi;
    rbbi.cbSize = sizeof( rbbi );
    rbbi.fMask  = RBBIM_CHILD | RBBIM_STYLE;

    CReBarCtrl& rbCtrl = m_wndReBar.GetReBarCtrl();
    for ( UINT nBand = 0; nBand < rbCtrl.GetBandCount(); nBand++ )
    {
        VERIFY( rbCtrl.GetBandInfo( nBand, &rbbi ) );
        if ( rbbi.hwndChild == pBar->GetSafeHwnd() )
        {
            UINT nID = ( UINT )pBar->GetDlgCtrlID();
            ASSERT( nID != 0 );
            ASSERT( rbCtrl.IDToIndex( nID ) == -1 );    // ID must be unique!

            // Save bar info for context menu
            BARINFO barinfo;
            barinfo.nID            = nID;
            barinfo.bAlwaysVisible = bAlwaysVisible;
            _tcsncpy( barinfo.szTitle, lpszTitle ? lpszTitle : _T(""), MAX_PATH );
            m_aBars.Add( barinfo );

            // To allow easy finding of parent band index,
            // we set band's ID to dialog control ID of child window.
            rbbi.fMask   = RBBIM_ID | RBBIM_BACKGROUND;
            rbbi.wID     = nID;
            rbbi.hbmBack = m_hbmBack;

            if ( pBar->IsKindOf( RUNTIME_CLASS( CMenuBar ) ) ||
                 pBar->IsKindOf( RUNTIME_CLASS( CToolBarEx ) ) )
            {
                rbbi.fMask  |= RBBIM_STYLE;
                rbbi.fStyle |= RBBS_USECHEVRON;
            }

            VERIFY( rbCtrl.SetBandInfo( nBand, &rbbi ) );
            return true;
        }
    }

    return false;
}

/////////////////////////////////////////////////////////////////////////////
// Overrides

CSize CSizableReBar::CalcFixedLayout( BOOL bStretch, BOOL bHorz )
{
    ASSERT( bStretch ); // the bar is stretched (is not the child of a dockbar)

    m_szCurrent = m_wndReBar.CalcFixedLayout( bStretch, bHorz );

    switch ( GetSizingEdgeHitCode() )
    {
        case HTLEFT:
        case HTRIGHT:
            if ( m_szCurrent.cx > 0 )
            {
                m_szCurrent.cx += m_cxEdge;
            }
            break;
        case HTTOP:
        case HTBOTTOM:
            if ( m_szCurrent.cy > 0 )
            {
                m_szCurrent.cy += m_cyEdge;
            }
            break;
        default:
            ASSERT( false );
            break;
    }

    return m_szCurrent;
}

CSize CSizableReBar::CalcDynamicLayout( int /*nLength*/, DWORD dwMode )
{
    return CalcFixedLayout( dwMode & LM_STRETCH, dwMode & LM_HORZ );
}

BOOL CSizableReBar::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult )
{
    if ( wParam == AFX_IDW_REBAR )
    {
        REBARBANDINFO rbbi;
        rbbi.cbSize = sizeof( rbbi );
        rbbi.fMask  = RBBIM_CHILD;

        // Let child windows handle certain messages
        NMHDR* pNMHDR = ( NMHDR* )lParam;
        switch ( pNMHDR->code )
        {
            case RBN_CHILDSIZE:
            {
                NMREBARCHILDSIZE* lprbcs = ( NMREBARCHILDSIZE* )pNMHDR;
                VERIFY( m_wndReBar.GetReBarCtrl().GetBandInfo( lprbcs->uBand, &rbbi ) );

                ::SendMessage( rbbi.hwndChild, WM_REBAR_CHILDSIZE,
                    ( WPARAM )&lprbcs->rcBand,
                    ( LPARAM )&lprbcs->rcChild );
                break;
            }
            case RBN_CHEVRONPUSHED:
            {
                NMREBARCHEVRON* lpnm = ( NMREBARCHEVRON* )pNMHDR;
                VERIFY( m_wndReBar.GetReBarCtrl().GetBandInfo( lpnm->uBand, &rbbi ) );

                CRect rcChevron( lpnm->rc );
                m_wndReBar.ClientToScreen( rcChevron );
                ::SendMessage( rbbi.hwndChild, WM_REBAR_CHEVRONPUSHED,
                    ( WPARAM )( LPCRECT )rcChevron, lpnm->lParamNM );
                break;
            }
            default:
                break;
        }

        // Forward notifications from the re-bar control to owner/parent
		m_wndReBar.SendMessage( WM_NOTIFY, wParam, lParam );
        *pResult = GetParent()->SendMessage( WM_NOTIFY, wParam, lParam );
        return TRUE;
    }

    return FALSE;
}

void CSizableReBar::OnUpdateCmdUI( CFrameWnd* pTarget, BOOL bDisableIfNoHandler )
{
    UpdateDialogControls( pTarget, bDisableIfNoHandler );
	m_wndReBar.OnUpdateCmdUI( pTarget, bDisableIfNoHandler);
}

/////////////////////////////////////////////////////////////////////////
// CSizableReBar message handlers

BEGIN_MESSAGE_MAP( CSizableReBar, CControlBar )
    //{{AFX_MSG_MAP(CSizableReBar)
    ON_WM_CREATE()
    ON_WM_NCPAINT()
    ON_WM_NCCALCSIZE()
    ON_WM_NCHITTEST()
    ON_WM_CAPTURECHANGED()
    ON_WM_MOUSEMOVE()
    ON_WM_LBUTTONUP()
    ON_WM_NCLBUTTONDOWN()
    ON_WM_SIZE()
    ON_WM_CONTEXTMENU()
    ON_WM_INITMENUPOPUP()
    ON_WM_DRAWITEM()

⌨️ 快捷键说明

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