tbar95.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,707 行 · 第 1/4 页
CPP
1,707 行
button.fsState |= TBSTATE_ENABLED;
if ( tool->IsToggled() )
button.fsState |= TBSTATE_CHECKED;
switch ( tool->GetKind() )
{
case wxITEM_RADIO:
button.fsStyle = TBSTYLE_CHECKGROUP;
if ( !lastWasRadio )
{
// the first item in the radio group is checked by
// default to be consistent with wxGTK and the menu
// radio items
button.fsState |= TBSTATE_CHECKED;
if (tool->Toggle(true))
{
DoToggleTool(tool, true);
}
}
else if (tool->IsToggled())
{
wxToolBarToolsList::compatibility_iterator nodePrev = node->GetPrevious();
int prevIndex = i - 1;
while ( nodePrev )
{
TBBUTTON& prevButton = buttons[prevIndex];
wxToolBarToolBase *tool = nodePrev->GetData();
if ( !tool->IsButton() || tool->GetKind() != wxITEM_RADIO )
break;
if ( tool->Toggle(false) )
{
DoToggleTool(tool, false);
}
prevButton.fsState = TBSTATE_ENABLED;
nodePrev = nodePrev->GetPrevious();
prevIndex--;
}
}
isRadio = true;
break;
case wxITEM_CHECK:
button.fsStyle = TBSTYLE_CHECK;
break;
default:
wxFAIL_MSG( _T("unexpected toolbar button kind") );
// fall through
case wxITEM_NORMAL:
button.fsStyle = TBSTYLE_BUTTON;
}
bitmapId++;
break;
}
lastWasRadio = isRadio;
i++;
}
if ( !::SendMessage(GetHwnd(), TB_ADDBUTTONS, (WPARAM)i, (LPARAM)buttons) )
{
wxLogLastError(wxT("TB_ADDBUTTONS"));
}
delete [] buttons;
// Deal with the controls finally
// ------------------------------
// adjust the controls size to fit nicely in the toolbar
int y = 0;
size_t index = 0;
for ( node = m_tools.GetFirst(); node; node = node->GetNext(), index++ )
{
wxToolBarToolBase *tool = node->GetData();
// we calculate the running y coord for vertical toolbars so we need to
// get the items size for all items but for the horizontal ones we
// don't need to deal with the non controls
bool isControl = tool->IsControl();
if ( !isControl && !isVertical )
continue;
// note that we use TB_GETITEMRECT and not TB_GETRECT because the
// latter only appeared in v4.70 of comctl32.dll
RECT r;
if ( !::SendMessage(GetHwnd(), TB_GETITEMRECT,
index, (LPARAM)(LPRECT)&r) )
{
wxLogLastError(wxT("TB_GETITEMRECT"));
}
if ( !isControl )
{
// can only be control if isVertical
y += r.bottom - r.top;
continue;
}
wxControl *control = tool->GetControl();
wxSize size = control->GetSize();
// the position of the leftmost controls corner
int left = wxDefaultCoord;
// TB_SETBUTTONINFO message is only supported by comctl32.dll 4.71+
#ifdef TB_SETBUTTONINFO
// available in headers, now check whether it is available now
// (during run-time)
if ( wxApp::GetComCtl32Version() >= 471 )
{
// set the (underlying) separators width to be that of the
// control
TBBUTTONINFO tbbi;
tbbi.cbSize = sizeof(tbbi);
tbbi.dwMask = TBIF_SIZE;
tbbi.cx = (WORD)size.x;
if ( !::SendMessage(GetHwnd(), TB_SETBUTTONINFO,
tool->GetId(), (LPARAM)&tbbi) )
{
// the id is probably invalid?
wxLogLastError(wxT("TB_SETBUTTONINFO"));
}
}
else
#endif // comctl32.dll 4.71
// TB_SETBUTTONINFO unavailable
{
// try adding several separators to fit the controls width
int widthSep = r.right - r.left;
left = r.left;
TBBUTTON tbb;
wxZeroMemory(tbb);
tbb.idCommand = 0;
tbb.fsState = TBSTATE_ENABLED;
tbb.fsStyle = TBSTYLE_SEP;
size_t nSeparators = size.x / widthSep;
for ( size_t nSep = 0; nSep < nSeparators; nSep++ )
{
if ( !::SendMessage(GetHwnd(), TB_INSERTBUTTON,
index, (LPARAM)&tbb) )
{
wxLogLastError(wxT("TB_INSERTBUTTON"));
}
index++;
}
// remember the number of separators we used - we'd have to
// delete all of them later
((wxToolBarTool *)tool)->SetSeparatorsCount(nSeparators);
// adjust the controls width to exactly cover the separators
control->SetSize((nSeparators + 1)*widthSep, wxDefaultCoord);
}
// position the control itself correctly vertically
int height = r.bottom - r.top;
int diff = height - size.y;
if ( diff < 0 )
{
// the control is too high, resize to fit
control->SetSize(wxDefaultCoord, height - 2);
diff = 2;
}
int top;
if ( isVertical )
{
left = 0;
top = y;
y += height + 2*GetMargins().y;
}
else // horizontal toolbar
{
if ( left == wxDefaultCoord )
left = r.left;
top = r.top;
}
control->Move(left, top + (diff + 1) / 2);
}
// the max index is the "real" number of buttons - i.e. counting even the
// separators which we added just for aligning the controls
m_nButtons = index;
if ( !isVertical )
{
if ( m_maxRows == 0 )
{
// if not set yet, only one row
SetRows(1);
}
}
else if ( m_nButtons > 0 ) // vertical non empty toolbar
{
if ( m_maxRows == 0 )
{
// if not set yet, have one column
SetRows(m_nButtons);
}
}
InvalidateBestSize();
UpdateSize();
return true;
}
// ----------------------------------------------------------------------------
// message handlers
// ----------------------------------------------------------------------------
bool wxToolBar::MSWCommand(WXUINT WXUNUSED(cmd), WXWORD id)
{
wxToolBarToolBase *tool = FindById((int)id);
if ( !tool )
return false;
bool toggled = false; // just to suppress warnings
if ( tool->CanBeToggled() )
{
LRESULT state = ::SendMessage(GetHwnd(), TB_GETSTATE, id, 0);
toggled = (state & TBSTATE_CHECKED) != 0;
// ignore the event when a radio button is released, as this doesn't
// seem to happen at all, and is handled otherwise
if ( tool->GetKind() == wxITEM_RADIO && !toggled )
return true;
tool->Toggle(toggled);
UnToggleRadioGroup(tool);
}
// OnLeftClick() can veto the button state change - for buttons which
// may be toggled only, of couse
if ( !OnLeftClick((int)id, toggled) && tool->CanBeToggled() )
{
// revert back
tool->Toggle(!toggled);
::SendMessage(GetHwnd(), TB_CHECKBUTTON, id, MAKELONG(!toggled, 0));
}
return true;
}
bool wxToolBar::MSWOnNotify(int WXUNUSED(idCtrl),
WXLPARAM lParam,
WXLPARAM *WXUNUSED(result))
{
#if wxUSE_TOOLTIPS
// First check if this applies to us
NMHDR *hdr = (NMHDR *)lParam;
// the tooltips control created by the toolbar is sometimes Unicode, even
// in an ANSI application - this seems to be a bug in comctl32.dll v5
UINT code = hdr->code;
if ( (code != (UINT) TTN_NEEDTEXTA) && (code != (UINT) TTN_NEEDTEXTW) )
return false;
HWND toolTipWnd = (HWND)::SendMessage((HWND)GetHWND(), TB_GETTOOLTIPS, 0, 0);
if ( toolTipWnd != hdr->hwndFrom )
return false;
LPTOOLTIPTEXT ttText = (LPTOOLTIPTEXT)lParam;
int id = (int)ttText->hdr.idFrom;
wxToolBarToolBase *tool = FindById(id);
if ( !tool )
return false;
return HandleTooltipNotify(code, lParam, tool->GetShortHelp());
#else
wxUnusedVar(lParam);
return false;
#endif
}
// ----------------------------------------------------------------------------
// toolbar geometry
// ----------------------------------------------------------------------------
void wxToolBar::SetToolBitmapSize(const wxSize& size)
{
wxToolBarBase::SetToolBitmapSize(size);
::SendMessage(GetHwnd(), TB_SETBITMAPSIZE, 0, MAKELONG(size.x, size.y));
}
void wxToolBar::SetRows(int nRows)
{
if ( nRows == m_maxRows )
{
// avoid resizing the frame uselessly
return;
}
// TRUE in wParam means to create at least as many rows, FALSE -
// at most as many
RECT rect;
::SendMessage(GetHwnd(), TB_SETROWS,
MAKEWPARAM(nRows, !(GetWindowStyle() & wxTB_VERTICAL)),
(LPARAM) &rect);
m_maxRows = nRows;
UpdateSize();
}
// The button size is bigger than the bitmap size
wxSize wxToolBar::GetToolSize() const
{
// TB_GETBUTTONSIZE is supported from version 4.70
#if defined(_WIN32_IE) && (_WIN32_IE >= 0x300 ) \
&& !( defined(__GNUWIN32__) && !wxCHECK_W32API_VERSION( 1, 0 ) ) \
&& !defined (__DIGITALMARS__)
if ( wxApp::GetComCtl32Version() >= 470 )
{
DWORD dw = ::SendMessage(GetHwnd(), TB_GETBUTTONSIZE, 0, 0);
return wxSize(LOWORD(dw), HIWORD(dw));
}
else
#endif // comctl32.dll 4.70+
{
// defaults
return wxSize(m_defaultWidth + 8, m_defaultHeight + 7);
}
}
static
wxToolBarToolBase *GetItemSkippingDummySpacers(const wxToolBarToolsList& tools,
size_t index )
{
wxToolBarToolsList::compatibility_iterator current = tools.GetFirst();
for ( ; current ; current = current->GetNext() )
{
if ( index == 0 )
return current->GetData();
wxToolBarTool *tool = (wxToolBarTool *)current->GetData();
size_t separators = tool->GetSeparatorsCount();
// if it is a normal button, sepcount == 0, so skip 1 item (the button)
// otherwise, skip as many items as the separator count, plus the
// control itself
index -= separators ? separators + 1 : 1;
}
return 0;
}
wxToolBarToolBase *wxToolBar::FindToolForPosition(wxCoord x, wxCoord y) const
{
POINT pt;
pt.x = x;
pt.y = y;
int index = (int)::SendMessage(GetHwnd(), TB_HITTEST, 0, (LPARAM)&pt);
// MBN: when the point ( x, y ) is close to the toolbar border
// TB_HITTEST returns m_nButtons ( not -1 )
if ( index < 0 || (size_t)index >= m_nButtons )
{
// it's a separator or there is no tool at all there
return (wxToolBarToolBase *)NULL;
}
// when TB_SETBUTTONINFO is available (both during compile- and run-time),
// we don't use the dummy separators hack
#ifdef TB_SETBUTTONINFO
if ( wxApp::GetComCtl32Version() >= 471 )
{
return m_tools.Item((size_t)index)->GetData();
}
else
#endif // TB_SETBUTTONINFO
{
return GetItemSkippingDummySpacers( m_tools, (size_t) index );
}
}
void wxToolBar::UpdateSize()
{
wxPoint pos = GetPosition();
::SendMessage(GetHwnd(), TB_AUTOSIZE, 0, 0);
if (pos != GetPosition())
Move(pos);
// In case Realize is called after the initial display (IOW the programmer
// may have rebuilt the toolbar) give the frame the option of resizing the
// toolbar to full width again, but only if the parent is a frame and the
// toolbar is managed by the frame. Otherwise assume that some other
// layout mechanism is controlling the toolbar size and leave it alone.
wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
if ( frame && frame->GetToolBar() == this )
{
frame->SendSizeEvent();
}
}
// ----------------------------------------------------------------------------
// toolbar styles
// ---------------------------------------------------------------------------
void wxToolBar::SetWindowStyleFlag(long style)
{
// the style bits whose changes force us to recreate the toolbar
static const long MASK_NEEDS_RECREATE = wxTB_TEXT | wxTB_NOICONS;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?