📄 bartool.cpp
字号:
button.iString = -1;
if (lpIDArray != NULL)
{
// add new buttons to the common control
int iImage = 0;
for (int i = 0; i < nIDCount; i++)
{
button.fsState = TBSTATE_ENABLED;
if ((button.idCommand = *lpIDArray++) == 0)
{
// separator
button.fsStyle = TBSTYLE_SEP;
// width of separator includes 8 pixel overlap
ASSERT(_afxComCtlVersion != -1);
if ((GetStyle() & TBSTYLE_FLAT) || _afxComCtlVersion == VERSION_IE4)
button.iBitmap = 6;
else
button.iBitmap = 8;
}
else
{
// a command button with image
button.fsStyle = TBSTYLE_BUTTON;
button.iBitmap = iImage++;
}
if (!DefWindowProc(TB_ADDBUTTONS, 1, (LPARAM)&button))
return FALSE;
}
}
else
{
// add 'blank' buttons
button.fsState = TBSTATE_ENABLED;
for (int i = 0; i < nIDCount; i++)
{
ASSERT(button.fsStyle == TBSTYLE_BUTTON);
if (!DefWindowProc(TB_ADDBUTTONS, 1, (LPARAM)&button))
return FALSE;
}
}
m_nCount = (int)DefWindowProc(TB_BUTTONCOUNT, 0, 0);
m_bDelayedButtonLayout = TRUE;
return TRUE;
}
#ifdef AFX_CORE3_SEG
#pragma code_seg(AFX_CORE3_SEG)
#endif
/////////////////////////////////////////////////////////////////////////////
// CToolBar attribute access
void CToolBar::_GetButton(int nIndex, TBBUTTON* pButton) const
{
CToolBar* pBar = (CToolBar*)this;
VERIFY(pBar->DefWindowProc(TB_GETBUTTON, nIndex, (LPARAM)pButton));
// TBSTATE_ENABLED == TBBS_DISABLED so invert it
pButton->fsState ^= TBSTATE_ENABLED;
}
void CToolBar::_SetButton(int nIndex, TBBUTTON* pButton)
{
// get original button state
TBBUTTON button;
VERIFY(DefWindowProc(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(DefWindowProc(TB_DELETEBUTTON, nIndex, 0));
VERIFY(DefWindowProc(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();
}
else
{
// invalidate just the button
CRect rect;
if (DefWindowProc(TB_GETITEMRECT, nIndex, (LPARAM)&rect))
InvalidateRect(rect);
}
}
}
int CToolBar::CommandToIndex(UINT nIDFind) const
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
CToolBar* pBar = (CToolBar*)this;
return (int)pBar->DefWindowProc(TB_COMMANDTOINDEX, nIDFind, 0);
}
UINT CToolBar::GetItemID(int nIndex) const
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
TBBUTTON button;
_GetButton(nIndex, &button);
return button.idCommand;
}
void CToolBar::GetItemRect(int nIndex, LPRECT lpRect) const
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
// handle any delayed layout
if (m_bDelayedButtonLayout)
((CToolBar*)this)->Layout();
// now it is safe to get the item rectangle
CToolBar* pBar = (CToolBar*)this;
if (!pBar->DefWindowProc(TB_GETITEMRECT, nIndex, (LPARAM)lpRect))
SetRectEmpty(lpRect);
}
void CToolBar::Layout()
{
ASSERT(m_bDelayedButtonLayout);
m_bDelayedButtonLayout = FALSE;
BOOL bHorz = (m_dwStyle & CBRS_ORIENT_HORZ) != 0;
if ((m_dwStyle & CBRS_FLOATING) && (m_dwStyle & CBRS_SIZE_DYNAMIC))
((CToolBar*)this)->CalcDynamicLayout(0, LM_HORZ | LM_MRUWIDTH | LM_COMMIT);
else if (bHorz)
((CToolBar*)this)->CalcDynamicLayout(0, LM_HORZ | LM_HORZDOCK | LM_COMMIT);
else
((CToolBar*)this)->CalcDynamicLayout(0, LM_VERTDOCK | LM_COMMIT);
}
UINT CToolBar::GetButtonStyle(int nIndex) const
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
TBBUTTON button;
_GetButton(nIndex, &button);
return MAKELONG(button.fsStyle, button.fsState);
}
void CToolBar::SetButtonStyle(int nIndex, UINT nStyle)
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
TBBUTTON button;
_GetButton(nIndex, &button);
if (button.fsStyle != (BYTE)LOWORD(nStyle) || button.fsState != (BYTE)HIWORD(nStyle))
{
button.fsStyle = (BYTE)LOWORD(nStyle);
button.fsState = (BYTE)HIWORD(nStyle);
_SetButton(nIndex, &button);
m_bDelayedButtonLayout = TRUE;
}
}
#define CX_OVERLAP 0
CSize CToolBar::CalcSize(TBBUTTON* pData, int nCount)
{
ASSERT(pData != NULL && nCount > 0);
CPoint cur(0,0);
CSize sizeResult(0,0);
DWORD dwExtendedStyle = DefWindowProc(TB_GETEXTENDEDSTYLE, 0, 0);
for (int i = 0; i < nCount; i++)
{
//WINBUG: The IE4 version of COMCTL32.DLL calculates the separation
// on a TBSTYLE_WRAP button as 100% of the value in iBitmap compared
// to the other versions which calculate it at 2/3 of that value.
// This is actually a bug which should be fixed in IE 4.01, so we
// only do the 100% calculation specifically for IE4.
int cySep = pData[i].iBitmap;
ASSERT(_afxComCtlVersion != -1);
if (!(GetStyle() & TBSTYLE_FLAT) && _afxComCtlVersion != VERSION_IE4)
cySep = cySep * 2 / 3;
if (pData[i].fsState & TBSTATE_HIDDEN)
continue;
int cx = m_sizeButton.cx;
if (pData[i].fsStyle & TBSTYLE_SEP)
{
// a separator represents either a height or width
if (pData[i].fsState & TBSTATE_WRAP)
sizeResult.cy = max(cur.y + m_sizeButton.cy + cySep, sizeResult.cy);
else
sizeResult.cx = max(cur.x + pData[i].iBitmap, sizeResult.cx);
}
else
{
// check for dropdown style, but only if the buttons are being drawn
if ((pData[i].fsStyle & TBSTYLE_DROPDOWN) &&
(dwExtendedStyle & TBSTYLE_EX_DRAWDDARROWS))
{
// add size of drop down
ASSERT(_afxDropDownWidth != -1);
cx += _afxDropDownWidth;
}
sizeResult.cx = max(cur.x + cx, sizeResult.cx);
sizeResult.cy = max(cur.y + m_sizeButton.cy, sizeResult.cy);
}
if (pData[i].fsStyle & TBSTYLE_SEP)
cur.x += pData[i].iBitmap;
else
cur.x += cx - CX_OVERLAP;
if (pData[i].fsState & TBSTATE_WRAP)
{
cur.x = 0;
cur.y += m_sizeButton.cy;
if (pData[i].fsStyle & TBSTYLE_SEP)
cur.y += cySep;
}
}
return sizeResult;
}
int CToolBar::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;
if (pData[i].fsStyle & TBSTYLE_SEP)
{
dx = pData[i].iBitmap;
dxNext = dx;
}
else
{
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;
}
void CToolBar::SizeToolBar(TBBUTTON* pData, int nCount, int nLength, BOOL bVert)
{
ASSERT(pData != NULL && nCount > 0);
if (!bVert)
{
int nMin, nMax, nTarget, nCurrent, nMid;
// Wrap ToolBar as specified
nMax = nLength;
nTarget = WrapToolBar(pData, nCount, nMax);
// Wrap ToolBar vertically
nMin = 0;
nCurrent = WrapToolBar(pData, nCount, nMin);
if (nCurrent != nTarget)
{
while (nMin < nMax)
{
nMid = (nMin + nMax) / 2;
nCurrent = WrapToolBar(pData, nCount, nMid);
if (nCurrent == nTarget)
nMax = nMid;
else
{
if (nMin == nMid)
{
WrapToolBar(pData, nCount, nMax);
break;
}
nMin = nMid;
}
}
}
CSize size = CalcSize(pData, nCount);
WrapToolBar(pData, nCount, size.cx);
}
else
{
CSize sizeMax, sizeMin, sizeMid;
// Wrap ToolBar vertically
WrapToolBar(pData, nCount, 0);
sizeMin = CalcSize(pData, nCount);
// Wrap ToolBar horizontally
WrapToolBar(pData, nCount, 32767);
sizeMax = CalcSize(pData, nCount);
while (sizeMin.cx < sizeMax.cx)
{
sizeMid.cx = (sizeMin.cx + sizeMax.cx) / 2;
WrapToolBar(pData, nCount, sizeMid.cx);
sizeMid = CalcSize(pData, nCount);
if (nLength < sizeMid.cy)
{
if (sizeMin == sizeMid)
{
WrapToolBar(pData, nCount, sizeMax.cx);
return;
}
sizeMin = sizeMid;
}
else if (nLength > sizeMid.cy)
sizeMax = sizeMid;
else
return;
}
}
}
struct _AFX_CONTROLPOS
{
int nIndex, nID;
CRect rectOldPos;
};
CSize CToolBar::CalcLayout(DWORD dwMode, int nLength)
{
ASSERT_VALID(this);
ASSERT(::IsWindow(m_hWnd));
if (dwMode & LM_HORZDOCK)
ASSERT(dwMode & LM_HORZ);
int nCount;
TBBUTTON* pData = NULL;
CSize sizeResult(0,0);
//BLOCK: Load Buttons
{
nCount = DefWindowProc(TB_BUTTONCOUNT, 0, 0);
if (nCount != 0)
{
int i;
pData = new TBBUTTON[nCount];
for (i = 0; i < nCount; i++)
_GetButton(i, &pData[i]);
}
}
if (nCount > 0)
{
if (!(m_dwStyle & CBRS_SIZE_FIXED))
{
BOOL bDynamic = m_dwStyle & CBRS_SIZE_DYNAMIC;
if (bDynamic && (dwMode & LM_MRUWIDTH))
SizeToolBar(pData, nCount, m_nMRUWidth);
else if (bDynamic && (dwMode & LM_HORZDOCK))
SizeToolBar(pData, nCount, 32767);
else if (bDynamic && (dwMode & LM_VERTDOCK))
SizeToolBar(pData, nCount, 0);
else if (bDynamic && (nLength != -1))
{
CRect rect; rect.SetRectEmpty();
CalcInsideRect(rect, (dwMode & LM_HORZ));
BOOL bVert = (dwMode & LM_LENGTHY);
int nLen = nLength + (bVert ? rect.Height() : rect.Width());
SizeToolBar(pData, nCount, nLen, bVert);
}
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]);
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -