📄 flatbar.cpp
字号:
else if (bDynamic && (m_dwStyle & CBRS_FLOATING))
SizeToolBar(pData, nCount, m_nMRUWidth);
else
SizeToolBar(pData, nCount, (dwMode & LM_HORZ) ? 32767 : 0);
}
sizeResult = CalcSize(pData, nCount);
if (dwMode & LM_COMMIT)
{
_AFX_CONTROLPOS* pControl = NULL;
int nControlCount = 0;
BOOL bIsDelayed = m_bDelayedButtonLayout;
m_bDelayedButtonLayout = FALSE;
for(int i = 0; i < nCount; i++)
if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
nControlCount++;
if (nControlCount > 0)
{
pControl = new _AFX_CONTROLPOS[nControlCount];
nControlCount = 0;
for(int i = 0; i < nCount; i++)
{
if ((pData[i].fsStyle & TBSTYLE_SEP) && (pData[i].idCommand != 0))
{
pControl[nControlCount].nIndex = i;
pControl[nControlCount].nID = pData[i].idCommand;
CRect rect;
GetItemRect(i, &rect);
ClientToScreen(&rect);
pControl[nControlCount].rectOldPos = rect;
nControlCount++;
}
}
}
if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
m_nMRUWidth = sizeResult.cx;
for (i = 0; i < nCount; i++)
SetButton(i, &pData[i]); // **PD** renamed from _SetButton
if (nControlCount > 0)
{
for (int i = 0; i < nControlCount; i++)
{
CWnd* pWnd = GetDlgItem(pControl[i].nID);
if (pWnd != NULL)
{
CRect rect;
pWnd->GetWindowRect(&rect);
CPoint pt = rect.TopLeft() - pControl[i].rectOldPos.TopLeft();
GetItemRect(pControl[i].nIndex, &rect);
pt = rect.TopLeft() + pt;
pWnd->SetWindowPos(NULL, pt.x, pt.y, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
}
}
delete[] pControl;
}
m_bDelayedButtonLayout = bIsDelayed;
}
delete[] pData;
}
//BLOCK: Adjust Margins
{
CRect rect; rect.SetRectEmpty();
CalcInsideRect(rect, (dwMode & LM_HORZ));
sizeResult.cy -= rect.Height();
sizeResult.cx -= rect.Width();
CSize size = CControlBar::CalcFixedLayout((dwMode & LM_STRETCH), (dwMode & LM_HORZ));
sizeResult.cx = max(sizeResult.cx, size.cx);
sizeResult.cy = max(sizeResult.cy, size.cy);
}
return sizeResult;
}
CSize CFlatToolBar::CalcFixedLayout(BOOL bStretch, BOOL bHorz)
{
DWORD dwMode = bStretch ? LM_STRETCH : 0;
dwMode |= bHorz ? LM_HORZ : 0;
return CalcLayout(dwMode);
}
CSize CFlatToolBar::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);
}
/////////////////////////////////////////////////////////////////////////////
// CToolBar attribute access
// **PD** I renamed this from _GetButton.
//
void CFlatToolBar::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;
}
// **PD** I renamed this from _SetButton.
//
void CFlatToolBar::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
}
}
}
////////////////////////////////////////////////////////////////
// End FixTb code.
////////////////////////////////////////////////////////////////
////////////////
// Load override modifies the style after loading toolbar.
//
BOOL CFlatToolBar::LoadToolBar(LPCTSTR lpszResourceName)
{
if (!CToolBar::LoadToolBar(lpszResourceName))
return FALSE;
ModifyStyle(0, TBSTYLE_FLAT); // make it flat
return TRUE;
}
//#define ILLUSTRATE_DISPLAY_BUG // remove comment to see the bug
//////////////////
// MFC doesn't handle moving a TBSTYLE_FLAT toolbar correctly.
// The simplest way to fix it is to repaint the old rectangle and
// toolbar itself whenever the toolbar moves.
//
void CFlatToolBar::OnWindowPosChanging(LPWINDOWPOS lpwp)
{
CToolBar::OnWindowPosChanging(lpwp);
#ifndef ILLUSTRATE_DISPLAY_BUG
if (!(lpwp->flags & SWP_NOMOVE)) { // if moved:
CRect rc; // Fill rectangle with..
GetWindowRect(&rc); // ..my (toolbar) rectangle.
CWnd* pParent = GetParent(); // get parent (dock bar/frame) win..
pParent->ScreenToClient(&rc); // .. and convert to parent coords
// Ask parent window to paint the area beneath my old location.
// Typically, this is just solid grey. The area won't get painted until
// I send WM_NCPAINT after the move, in OnWindowPosChanged below.
//
pParent->InvalidateRect(&rc); // paint old rectangle
}
#endif
}
//////////////////
// Now toolbar has moved: repaint old area
//
void CFlatToolBar::OnWindowPosChanged(LPWINDOWPOS lpwp)
{
CToolBar::OnWindowPosChanged(lpwp);
#ifndef ILLUSTRATE_DISPLAY_BUG
if (!(lpwp->flags & SWP_NOMOVE)) { // if moved:
// Now paint my non-client area at the new location.
// This is the extra bit of border space surrounding the buttons.
// Without this, you will still have a partial display bug (try it!)
//
SendMessage(WM_NCPAINT);
}
#endif
}
////////////////////////////////////////////////////////////////
// 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"
void CFlatOrCoolBarCmdUI::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);
}
// Take your pick:
#define MYTBBS_CHECKED TBBS_CHECKED // use "checked" state
//#define MYTBBS_CHECKED TBBS_PRESSED // use pressed state
//////////////////
// This is the only function that has changed: instead of TBBS_CHECKED,
// I use TBBS_PRESSED--PD
//
void CFlatOrCoolBarCmdUI::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 &
~(MYTBBS_CHECKED | TBBS_INDETERMINATE); // PD
if (nCheck == 1)
nNewStyle |= MYTBBS_CHECKED; // 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();
}
}
void CFlatOrCoolBarCmdUI::SetText(LPCTSTR)
{
// ignore for now, but you should really set the text
}
//////////////////
// This function is mostly copied from CToolBar/BARTOOL.CPP. The only thing
// that's different is I instantiated a CFlatOrCoolBarCmdUI instead of
// CToolCmdUI.
//
void CFlatToolBar::OnUpdateCmdUI(CFrameWnd* pTarget, BOOL bDisableIfNoHndler)
{
CFlatOrCoolBarCmdUI state; // <<<< This is the only line that's different--PD
state.m_pOther = this;
state.m_nIndexMax = (UINT)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; state.m_nIndex++)
{
// get button state
TBBUTTON button;
VERIFY(DefWindowProc(TB_GETBUTTON, state.m_nIndex, (LPARAM)&button));
// TBSTATE_ENABLED == TBBS_DISABLED so invert it
button.fsState ^= TBSTATE_ENABLED;
state.m_nID = button.idCommand;
// ignore separators
if (!(button.fsStyle & TBSTYLE_SEP))
{
// allow the toolbar itself to have update handlers
if (CWnd::OnCmdMsg(state.m_nID, CN_UPDATE_COMMAND_UI, &state, NULL))
continue;
// allow the owner to process the update
state.DoUpdate(pTarget, bDisableIfNoHndler);
}
}
// update the dialog controls added to the toolbar
UpdateDialogControls(pTarget, bDisableIfNoHndler);
}
//////////////////
// Make the parent frame my owner. This is important for status bar
// prompts to work. Note that when you create the CCoolToolBar in
// CYourCoolBar::OnCreateBands, you must also set CBRS_FLYBY in the
// the CCoolToolBar style!
//
BOOL CFlatToolBar::OnNcCreate(LPCREATESTRUCT lpCreateStruct)
{
CFrameWnd* pFrame = GetParentFrame();
ASSERT_VALID(pFrame);
SetOwner(pFrame);
return CToolBar::OnNcCreate(lpCreateStruct);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -