📄 ooextoolbar.cpp
字号:
// @mfunc: (FUNCTIONAL)
// <c COOExToolBar>
// Call when ever the system color are changing. Trap to rebuild
// the toolbar image list with the good background color.
// @end =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void COOExToolBar::OnSysColorChange( void )
{
// Call the base class method.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
CToolBar::OnSysColorChange();
}
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// @mfunc: (FUNCTIONAL)
// <c COOExToolBar>
// Call when the toolbar is moved. There is a bug when the tool
// bar is in flat mode, and in vertical position. The separator
// are not count in the height, so the last button is not completly
// displayed.
// @end =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void COOExToolBar::OnWindowPosChanging( LPWINDOWPOS _pWindowPos )
{
// Default processing
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
if( m_bOldFloating != ( IsFloating()?true:false ) )
{
m_bOldFloating = !m_bOldFloating;
_pWindowPos->flags |= SWP_DRAWFRAME;
}
CToolBar::OnWindowPosChanging( _pWindowPos );
}
// @end =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Start =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// MFC Overloaded method.
// The following stuff is to make the command update UI mechanism
// work properly for flat tool bars. The main idea is to convert
// a "checked" button state into a "pressed" button state. Changed
// lines marked with "PD"
// ------------------------------------------------------------------------
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// @mfunc: (FUNCTIONAL)
// <c CCoolCmdUI>
// Came from Paul Dilascia Article.
// @end =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void CCoolCmdUI::Enable( BOOL bOn )
{
m_bEnableChanged = TRUE;
CToolBar* pToolBar = ( CToolBar* ) m_pOther;
ASSERT( pToolBar != NULL );
ASSERT_KINDOF( CToolBar, pToolBar );
ASSERT( m_nIndex < m_nIndexMax );
UINT nNewStyle = pToolBar->GetButtonStyle( m_nIndex ) & ~TBBS_DISABLED;
if ( !bOn )
{
nNewStyle |= TBBS_DISABLED;
// WINBUG: If a button is currently pressed and then is disabled
// COMCTL32.DLL does not unpress the button, even after the mouse
// button goes up! We work around this bug by forcing TBBS_PRESSED
// off when a button is disabled.
nNewStyle &= ~TBBS_PRESSED;
}
ASSERT( !( nNewStyle & TBBS_SEPARATOR ) );
pToolBar->SetButtonStyle( m_nIndex, nNewStyle );
}
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
// @mfunc: (FUNCTIONAL)
// <c CCoolCmdUI>
// Came from Paul Dilascia Article.
// @end =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void CCoolCmdUI::SetCheck( int nCheck )
{
ASSERT( nCheck >= 0 && nCheck <= 2 ); // 0=>off, 1=>on, 2=>indeterminate
CToolBar* pToolBar = ( CToolBar* ) m_pOther;
ASSERT( pToolBar != NULL );
ASSERT_KINDOF( CToolBar, pToolBar );
ASSERT( m_nIndex < m_nIndexMax );
UINT nOldStyle = pToolBar->GetButtonStyle( m_nIndex ); // PD
UINT nNewStyle = nOldStyle &
~( TBBS_PRESSED | TBBS_INDETERMINATE ); // PD
if ( nCheck == 1 )
nNewStyle |= TBBS_PRESSED; // PD
else if ( nCheck == 2 )
nNewStyle |= TBBS_INDETERMINATE;
// Following is to fix display bug for TBBS_CHECKED:
// If new state is unchecked, repaint--but only if style actually changing.
// (Otherwise will end up with flicker)
//
if ( nNewStyle != nOldStyle ) {
ASSERT( !( nNewStyle & TBBS_SEPARATOR ) );
pToolBar->SetButtonStyle( m_nIndex, nNewStyle );
pToolBar->Invalidate();
}
}
// @end =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
/*CSize COOExToolBar::CalcDynamicLayout(int nLength, DWORD dwMode)
{
if ((nLength == -1) &&
!(dwMode & LM_MRUWIDTH) && !(dwMode & LM_COMMIT) &&
((dwMode & LM_HORZDOCK) || (dwMode & LM_VERTDOCK)))
{
return CalcFixedLayout(dwMode & LM_STRETCH, dwMode & LM_HORZDOCK);
}
return CalcLayout(dwMode, nLength);
}
*/
//////////////////
// 1998 Microsoft Systems Journal - Paul DiLascia
// This is the all-important function that gets the true size of a button,
// instead of using m_sizeButton. And it's virtual, so you can override if
// my algorithm doesn't work, as will surely be the case in some circumstances.
//
CSize COOExToolBar::GetButtonSize(TBBUTTON* pData, int iButton)
{
// Get the actual size of the button, not what's in m_sizeButton.
// Make sure to do SendMessage instead of calling MFC's GetItemRect,
// which has all sorts of bad side-effects! (Go ahead, take a look at it.)
//
CRect rc;
SendMessage(TB_GETITEMRECT, iButton, (LPARAM)&rc);
CSize sz = rc.Size();
////////////////
// Now must do special case for various versions of comctl32.dll,
//
DWORD dwStyle = pData[iButton].fsStyle;
if ((pData[iButton].fsState & TBSTATE_WRAP)) {
if (dwStyle & TBSTYLE_SEP) {
// this is the last separator in the row (eg vertically docked)
// fudge the height, and ignore the width. TB_GETITEMRECT will return
// size = (8 x 22) even for a separator in vertical toolbar
//
sz.cy = sz.cx;
sz.cx = 0; // separator takes no width if it's the last one
} else if (dwStyle & TBSTYLE_DROPDOWN ) {//&&
//!m_bShowDropdownArrowWhenVertical) {
// ignore width of dropdown
sz.cx = 0;
}
}
return sz;
}
//////////////////
// 1998 Microsoft Systems Journal - Paul DiLascia
// I renamed this from _GetButton.
//
void COOExToolBar::GetButton(int nIndex, TBBUTTON* pButton) const
{
CToolBar* pBar = (CToolBar*)this;
VERIFY(pBar->SendMessage(TB_GETBUTTON, nIndex, (LPARAM)pButton));
// TBSTATE_ENABLED == TBBS_DISABLED so invert it
pButton->fsState ^= TBSTATE_ENABLED;
}
//////////////////
// 1998 Microsoft Systems Journal - Paul DiLascia
// I renamed this from _SetButton.
//
void COOExToolBar::SetButton(int nIndex, TBBUTTON* pButton)
{
// get original button state
TBBUTTON button;
VERIFY(SendMessage(TB_GETBUTTON, nIndex, (LPARAM)&button));
// prepare for old/new button comparsion
button.bReserved[0] = 0;
button.bReserved[1] = 0;
// TBSTATE_ENABLED == TBBS_DISABLED so invert it
pButton->fsState ^= TBSTATE_ENABLED;
pButton->bReserved[0] = 0;
pButton->bReserved[1] = 0;
// nothing to do if they are the same
if (memcmp(pButton, &button, sizeof(TBBUTTON)) != 0)
{
// don't redraw everything while setting the button
DWORD dwStyle = GetStyle();
ModifyStyle(WS_VISIBLE, 0);
VERIFY(SendMessage(TB_DELETEBUTTON, nIndex, 0));
VERIFY(SendMessage(TB_INSERTBUTTON, nIndex, (LPARAM)pButton));
ModifyStyle(0, dwStyle & WS_VISIBLE);
// invalidate appropriate parts
if (((pButton->fsStyle ^ button.fsStyle) & TBSTYLE_SEP) ||
((pButton->fsStyle & TBSTYLE_SEP) && pButton->iBitmap != button.iBitmap))
{
// changing a separator
Invalidate(FALSE);
}
else
{
// invalidate just the button
CRect rect;
if (SendMessage(TB_GETITEMRECT, nIndex, (LPARAM)&rect))
InvalidateRect(rect, FALSE); // don't erase background
}
}
}
//////////////////
// 1998 Microsoft Systems Journal - Paul DiLascia
// Make the parent frame my owner. This is important for status bar
// prompts to work.
//
////////////////////////////////////////////////////////////////
// 1998 Microsoft Systems Journal - Paul DiLascia
// Stuff below is copied from MFC, my mods marked **PD**
#ifdef _MAC
#define CX_OVERLAP 1
#else
#define CX_OVERLAP 0
#endif
/*CSize COOExToolBar::CalcSize(TBBUTTON* pData, int nCount)
{
ASSERT(pData != NULL && nCount > 0);
CPoint cur(0,0);
CSize sizeResult(0,0);
int cyTallestOnRow = 0;
for (int i = 0; i < nCount; i++)
{
if (pData[i].fsState & TBSTATE_HIDDEN)
continue;
// **PD** Load actual size of button into local var
// that obscures CToolBar::m_sizeButton.
CSize m_sizeButton = GetButtonSize(pData, i);
// **PD** I also changed the logic below to be more correct.
cyTallestOnRow = max(cyTallestOnRow, m_sizeButton.cy);
sizeResult.cx = max(cur.x + m_sizeButton.cx, sizeResult.cx);
sizeResult.cy = max(cur.y + m_sizeButton.cy, sizeResult.cy);
cur.x += m_sizeButton.cx - CX_OVERLAP;
if (pData[i].fsState & TBSTATE_WRAP)
{
cur.x = 0;
cur.y += cyTallestOnRow;
cyTallestOnRow = 0;
if (pData[i].fsStyle & TBSTYLE_SEP)
cur.y += m_sizeButton.cy;
}
}
return sizeResult;
}
int COOExToolBar::WrapToolBar(TBBUTTON* pData, int nCount, int nWidth)
{
ASSERT(pData != NULL && nCount > 0);
int nResult = 0;
int x = 0;
for (int i = 0; i < nCount; i++)
{
pData[i].fsState &= ~TBSTATE_WRAP;
if (pData[i].fsState & TBSTATE_HIDDEN)
continue;
int dx, dxNext;
// **PD** Load actual size of button into local var
// that obscures CToolBar::m_sizeButton.
CSize m_sizeButton = GetButtonSize(pData, i);
dx = m_sizeButton.cx;
dxNext = dx - CX_OVERLAP;
if (x + dx > nWidth)
{
BOOL bFound = FALSE;
for (int j = i; j >= 0 && !(pData[j].fsState & TBSTATE_WRAP); j--)
{
// Find last separator that isn't hidden
// a separator that has a command ID is not
// a separator, but a custom control.
if ((pData[j].fsStyle & TBSTYLE_SEP) &&
(pData[j].idCommand == 0) &&
!(pData[j].fsState & TBSTATE_HIDDEN))
{
bFound = TRUE; i = j; x = 0;
pData[j].fsState |= TBSTATE_WRAP;
nResult++;
break;
}
}
if (!bFound)
{
for (int j = i - 1; j >= 0 && !(pData[j].fsState & TBSTATE_WRAP); j--)
{
// Never wrap anything that is hidden,
// or any custom controls
if ((pData[j].fsState & TBSTATE_HIDDEN) ||
((pData[j].fsStyle & TBSTYLE_SEP) &&
(pData[j].idCommand != 0)))
continue;
bFound = TRUE; i = j; x = 0;
pData[j].fsState |= TBSTATE_WRAP;
nResult++;
break;
}
if (!bFound)
x += dxNext;
}
}
else
x += dxNext;
}
return nResult + 1;
}
*/
//////////////////////////////////////////////////////////////////////////
// 1998 Microsoft Systems Journal - Paul DiLascia
// Functions below are NOT modified. They're only here because they
// call the modified functions above, which are NOT virtual.
/*
void COOExToolBar::SizeToolBar(TBBUTTON* pData, int nCount, int nLength, BOOL bVert)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -