The problem is that CMFCDropDownToolbarButton::SetDefaultCommand(UINT uiCmd)
is flawed. If not a bUserButton
type then it assumes the index to the m_ImagesLocked
is by position instead of taking the buttons iIndex
. You can't use bUserButton
and support bLargeButtons
since the user buttons have to be the same size. Also the button that sits on the main toolbar takes on the first items m_strText
(normally empty string since loaded with toolbar) so the tooltip updates via CMainFrame::GetToolbarButtonToolTipText()
above don't work either (it should pull in the buttons text but doesn't). So probably test best thing to do is take afxdropdowntoolbar.cpp
and duplicate it in the project then fix it with a new class name. A little code bloat, if only SetDefaultCommand()
was virtual, could fix it easily.
Also note, if using LoadBitmap
/ LoadBitmapEx
, you should set bLocked
to TRUE (as well as when using InsertButton()
)
Have it all working the way it should have to start with, if you need this, here's the core changes:
Ugh, needed to override the protected CMFCToolBarImages::CopyTemp() so instead of having to redo almost all of the MFC toolbar support I added this hack! I doesn't add any data members so should maintain compatiblity with CMFCToolBar.
class CMyToolBarImages : public CMFCToolBarImages
{
public:
void MyCopyTemp(CMyToolBarImages *imagesDest) const
{
imagesDest->Clear();
imagesDest->m_bIsTemporary = TRUE;
imagesDest->m_sizeImage = m_sizeImage;
imagesDest->m_sizeImageDest = m_sizeImageDest;
imagesDest->m_hbmImageWell = m_hbmImageWell;
imagesDest->m_bUserImagesList = m_bUserImagesList;
imagesDest->m_iCount = m_iCount;
imagesDest->m_bReadOnly = TRUE;
imagesDest->m_nBitsPerPixel = m_nBitsPerPixel;
}
};
class CMyDropDownToolBar : public CMFCToolBar
{
.
.
.
virtual BOOL OnUserToolTip(CMFCToolBarButton* pButton, CString& strTTText) const;
// HACK protected CMFCToolBarImages!!
void CopyTempAll(CMyDropDownToolBar *desttoolbar) const
{
((const CMyToolBarImages*) &m_ImagesLocked)->MyCopyTemp((CMyToolBarImages*) &desttoolbar->m_ImagesLocked);
((const CMyToolBarImages*) &m_ColdImagesLocked)->MyCopyTemp((CMyToolBarImages*) &desttoolbar->m_ColdImagesLocked);
((const CMyToolBarImages*) &m_DisabledImagesLocked)->MyCopyTemp((CMyToolBarImages*) &desttoolbar->m_DisabledImagesLocked);
((const CMyToolBarImages*) &m_LargeImagesLocked)->MyCopyTemp((CMyToolBarImages*) &desttoolbar->m_LargeImagesLocked);
((const CMyToolBarImages*) &m_LargeColdImagesLocked)->MyCopyTemp((CMyToolBarImages*) &desttoolbar->m_LargeColdImagesLocked);
((const CMyToolBarImages*) &m_LargeDisabledImagesLocked)->MyCopyTemp((CMyToolBarImages*) &desttoolbar->m_LargeDisabledImagesLocked);
}
};
Have it call CMainFrame for tooltip:
BOOL CMyDropDownToolBar::OnUserToolTip(CMFCToolBarButton* pButton, CString& strTTText) const
{
ASSERT_VALID(pButton);
CFrameWnd* pTopFrame = AFXGetParentFrame(this);
if (pTopFrame == NULL)
{
return FALSE;
}
CMyDropDownFrame* pDropFrame = DYNAMIC_DOWNCAST(CMyDropDownFrame, pTopFrame);
if (pDropFrame != NULL)
{
pTopFrame = AFXGetParentFrame(pDropFrame);
if (pTopFrame == NULL)
{
return FALSE;
}
}
CMDIFrameWndEx* pMainFrame = DYNAMIC_DOWNCAST(CMDIFrameWndEx, pTopFrame);
if (pMainFrame != NULL)
{
return pMainFrame->GetToolbarButtonToolTipText(pButton, strTTText);
}
else // Maybe, SDI frame...
{
CFrameWndEx* pFrame = DYNAMIC_DOWNCAST(CFrameWndEx, pTopFrame);
if (pFrame != NULL)
{
return pFrame->GetToolbarButtonToolTipText(pButton, strTTText);
}
else // Maybe, MDIChild frame
{
CMDIChildWndEx* pMDIChild = DYNAMIC_DOWNCAST(CMDIChildWndEx, pTopFrame);
if (pMDIChild != NULL)
{
return pMDIChild->GetToolbarButtonToolTipText(pButton, strTTText);
}
else // Maybe, OLE frame...
{
COleIPFrameWndEx* pOleFrame = DYNAMIC_DOWNCAST(COleIPFrameWndEx, pFrame);
if (pOleFrame != NULL)
{
return pOleFrame->GetToolbarButtonToolTipText(pButton, strTTText);
}
}
}
}
return FALSE;
}
For the actual first fix needed that started this whole thing:
void CMyDropDownToolbarButton::SetDefaultCommand(UINT uiCmd)
{
.
.
.
if (pButton->m_nID == uiCmd)
{
m_bLocalUserButton = pButton->m_bUserButton;
if (m_bLocalUserButton)
{
m_iSelectedImage = pButton->GetImage();
}
else
{
// FIXED HERE:
m_iSelectedImage=pButton->GetImage();
if (m_iSelectedImage==-1) {
m_iSelectedImage=iImage;
}
}
// FIXED HERE:
m_strText=pButton->m_strText;
break;
}
.
.
.
}
To get the tool tips to look consistent with bold and normal, had it use CMainFrame::GetMessageString:
class CMyDropDownFrame : public CMiniFrameWnd
{
.
.
.
// For customizing the default messages on the status bar and second line of tooltip
virtual void GetMessageString(UINT nID, CString& rMessage) const;
};
// For customizing the default messages on the status bar and second line of tooltip
void CMyDropDownFrame::GetMessageString(UINT nID, CString& rMessage) const
{
CFrameWnd* pTopFrame = AFXGetParentFrame(this);
if (pTopFrame == NULL)
{
return;
}
CMFCDropDownFrame* pDropFrame = DYNAMIC_DOWNCAST(CMFCDropDownFrame, pTopFrame);
if (pDropFrame != NULL)
{
pTopFrame = AFXGetParentFrame(pDropFrame);
if (pTopFrame == NULL)
{
return;
}
}
CMDIFrameWndEx* pMainFrame = DYNAMIC_DOWNCAST(CMDIFrameWndEx, pTopFrame);
if (pMainFrame != NULL)
{
pMainFrame->GetMessageString(nID, rMessage);
return;
}
else // Maybe, SDI frame...
{
CFrameWndEx* pFrame = DYNAMIC_DOWNCAST(CFrameWndEx, pTopFrame);
if (pFrame != NULL)
{
pFrame->GetMessageString(nID, rMessage);
return;
}
else // Maybe, MDIChild frame
{
CMDIChildWndEx* pMDIChild = DYNAMIC_DOWNCAST(CMDIChildWndEx, pTopFrame);
if (pMDIChild != NULL)
{
pMDIChild->GetMessageString(nID, rMessage);
return;
}
else // Maybe, OLE frame...
{
COleIPFrameWndEx* pOleFrame = DYNAMIC_DOWNCAST(COleIPFrameWndEx, pFrame);
if (pOleFrame != NULL)
{
pOleFrame->GetMessageString(nID, rMessage);
return;
}
}
}
}
}
Also needed to change CMyDropDownFrame::OnCreate() to deal with protect member:
int CMyDropDownFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
.
.
.
// "Clone" the original toolbar:
m_pWndOriginToolbar->CopyTempAll(&m_wndToolBar);
/*
m_pWndOriginToolbar->m_ImagesLocked.CopyTemp(m_wndToolBar.m_ImagesLocked);
m_pWndOriginToolbar->m_ColdImagesLocked.CopyTemp(m_wndToolBar.m_ColdImagesLocked);
m_pWndOriginToolbar->m_DisabledImagesLocked.CopyTemp(m_wndToolBar.m_DisabledImagesLocked);
m_pWndOriginToolbar->m_LargeImagesLocked.CopyTemp(m_wndToolBar.m_LargeImagesLocked);
m_pWndOriginToolbar->m_LargeColdImagesLocked.CopyTemp(m_wndToolBar.m_LargeColdImagesLocked);
m_pWndOriginToolbar->m_LargeDisabledImagesLocked.CopyTemp(m_wndToolBar.m_LargeDisabledImagesLocked);
*/
.
.
.
};