I have three buttons in a CMFCToolbar
that is contained in a CDialogEx
, that I have set their styles to TBBS_CHECKGROUP
This allows each button to be toggled from checked to unchecked states, however I'd like to treat these three buttons as a group and ONLY allow one button to be checked at a time.
I cannot find any way to achieve this.
Only one of the buttons below should be checked at a time. How can I ensure that the other buttons automaticaly are unchecked?
In my code:
DWORD dwCtrlStyle = TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CBRS_SIZE_DYNAMIC;
DWORD dwStyle = AFX_DEFAULT_TOOLBAR_STYLE;
if (m_ToolBar.CreateEx(this, dwCtrlStyle,
dwStyle, CRect(1, 1, 1, 1), IDR_TOOLBAR1_PNG))
{
dwStyle = CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC;
m_ToolBar.SetPaneStyle(m_ToolBar.GetPaneStyle() | dwStyle);
}
CMFCToolBarInfo info;
m_ToolBar.SetSizes(CSize(32, 32), CSize(32, 32));
BOOL ret2 = m_ToolBar.LoadBitmap(IDR_TOOLBAR1_PNG); // << THIS WORKS
CMFCToolBarButton but1(0, 0, L"HELLO", TRUE, 0);
CMFCToolBarButton but2(1, 1, L"HELLO", TRUE, 0);
CMFCToolBarButton but3(2, 2, L"HELLO", TRUE, 0);
but1.SetStyle(but1.m_nStyle | TBBS_CHECKGROUP);
but2.SetStyle(but2.m_nStyle | TBBS_CHECKGROUP);
but3.SetStyle(but3.m_nStyle | TBBS_CHECKGROUP);
m_ToolBar.InsertButton(but1, 0);
m_ToolBar.InsertButton(but2, 0);
m_ToolBar.InsertButton(but3, 0);
m_ToolBar.SetToolBarBtnText(0, _T("By"));
m_ToolBar.SetToolBarBtnText(1, _T("Your"));
m_ToolBar.SetToolBarBtnText(2, _T("Command"));
m_ToolBar.InsertSeparator(2);
m_ToolBar.SetWindowPos(0, 0, 0, 400, 36, 0, 0);
UPDATE:
I've been able to get a partial workaround by adding ON_UPDATE_COMMAND_UI_RANGE
and using the following code (Although this allows me to ensure the other buttons are always unchecked, I'm still unable to change the state of the current button being clicked to keep it checked:
void CMFCApplication1Dlg::OnUpdateViewFilterData(CCmdUI* pCmdUI)
{
for (int i = 0; i < 3; ++i)
{
UINT nID;
UINT info;
int img;
m_ToolBar.GetButtonInfo(i, nID, info,img);
int check = 2;
if (nID != pCmdUI->m_nID)
{
UINT newStyle = m_ToolBar.GetButtonStyle(i) & ~(TBBS_CHECKED | TBBS_INDETERMINATE);
if (check == 1)
newStyle |= TBBS_CHECKED;
else if (check == 2)
newStyle |= TBBS_INDETERMINATE;
m_ToolBar.SetButtonStyle(i, newStyle | TBBS_CHECKBOX);
}
if (nID == pCmdUI->m_nID)
{
// If the button that is clicked keep it selected
//pCmdUI->SetCheck(1) // << Does not work
}
}
}
OK after much trial and error and a lot of coffee I have now established why CMFCToolbar
fails to work correctly when in a CDialogEx
.
I had noticed that even though I had implemented ON_UPDATE_COMMAND_UI
for each of the buttons, any attempt to use pCmdUI->SetCheck()
or pCmdUI->Enable()
would always just silently fail.
It turns out that for these commands to work correctly in a CDialogEx
the important missing piece of the puzzle is to ensure you set m_ToolBar.SetRouteCommandsViaFrame(FALSE);
And then finally to ensure that the update command is called at the very beginning to set the initial check box states just add the following:
ON_MESSAGE_VOID(WM_KICKIDLE, OnKickIdle)
void CMFCApplication1Dlg::OnKickIdle()
{
if (IsWindowVisible())
{
CFrameWnd* pParent = (CFrameWnd*)this;
if (pParent)
m_ToolBar.OnUpdateCmdUI(pParent, (BOOL)FALSE);
}
}