#winapi #mfc #cmfctoolbar
#winapi #мфц #cmfctoolbar #mfc
Вопрос:
Создал CMFCDropDownToolBar
в CMainFrame::OnCreate
:
// Loading toolbar with a single icon/entry.
if (!m_wndMyDropdownToolBar.Create(this,
WS_CHILD|CBRS_TOP|CBRS_TOOLTIPS|CBRS_FLYBY|CBRS_HIDE_INPLACE|CBRS_SIZE_DYNAMIC|
CBRS_GRIPPER | CBRS_BORDER_3D,
ID_ACTION_BUTTON) ||
!m_wndMyDropdownToolBar.LoadToolBar (IDR_TOOLBAR_DROPDOWNSELECT))
{
TRACE0("Failed to create build toolbarn");
return FALSE; // fail to create
}
// build list - use existing icon
for (UINT i=0; i<2; i ) {
CString s;
s.Format(_T("%i: Whatever %in"), i, i);
m_wndMyDropdownToolBar.InsertButton(CMFCToolBarButton(ID_COMMAND_START i, 0, s));
};
Затем остальные:
afx_msg LRESULT CMainFrame::OnToolbarReset(WPARAM idtoolbar, LPARAM)
{
if (idtoolbar==IDR_MAINFRAME) {
ASSERT(m_wndMyDropdownToolBar.GetSafeHwnd() != NULL);
//-----------------------------------
// Replace dropdown button:
//-----------------------------------
m_wndToolBar.ReplaceButton(ID_ACTION_BUTTON_DUMMY,
CMFCDropDownToolbarButton(_T("Text that doesn't show anywhere"), amp;m_wndMyDropdownToolBar));
}
return 0;
}
BOOL CMainFrame::GetToolbarButtonToolTipText(CMFCToolBarButton* pButton, CStringamp; strTTText)
{
if (pButton->m_nID>=ID_COMMAND_START amp;amp; pButton->m_nID<=ID_COMMAND_END) {
// use text
strTTText=pButton->m_strText;
return TRUE;
}
return FALSE;
}
Все работает нормально, поскольку в выпадающем списке отображаются кнопки, при наведении курсора отображается всплывающая подсказка, но когда вы выбираете одну из кнопок, добавленных вручную с помощью InsertButton()
вызова, кнопка на главной панели инструментов пуста и всплывающих подсказок нет. Если я затем вернусь и выберу первую кнопку (часть загруженного ресурса), она покажет правильный значок и подсказку.
Что я делаю неправильно?
Спасибо!!
Ответ №1:
Проблема в том, что CMFCDropDownToolbarButton::SetDefaultCommand(UINT uiCmd)
ошибка. Если не bUserButton
тип, то предполагается, что индекс к m_ImagesLocked
является позицией вместо того, чтобы принимать кнопки iIndex
. Вы не можете использовать bUserButton
и поддерживать bLargeButtons
, поскольку пользовательские кнопки должны быть одинакового размера. Также кнопка, которая находится на главной панели инструментов, принимает первые элементы m_strText
(обычно пустая строка, поскольку загружается с панели инструментов), поэтому обновления всплывающей подсказки через CMainFrame::GetToolbarButtonToolTipText()
выше, также не работают (она должна выводить текст кнопок, но не выполняет). Поэтому, вероятно, лучшее, что можно сделать для тестирования, это взять afxdropdowntoolbar.cpp
и дублировать его в проекте, а затем исправить с новым именем класса. Небольшое раздувание кода, если только SetDefaultCommand()
было виртуальным, могло бы легко исправить это.
Также обратите внимание, что при использовании LoadBitmap
/ LoadBitmapEx
вы должны установить bLocked
значение TRUE (как и при использовании InsertButton()
)
Пусть все работает так, как должно быть с самого начала, если вам это нужно, вот основные изменения:
Тьфу, нужно переопределить защищенные CMFCToolBarImages ::CopyTemp() поэтому вместо того, чтобы переделывать почти всю поддержку панели инструментов MFC, я добавил этот хак! Я не добавляю никаких элементов данных, поэтому должен поддерживать совместимость с 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, CStringamp; strTTText) const;
// HACK protected CMFCToolBarImages!!
void CopyTempAll(CMyDropDownToolBar *desttoolbar) const
{
((const CMyToolBarImages*) amp;m_ImagesLocked)->MyCopyTemp((CMyToolBarImages*) amp;desttoolbar->m_ImagesLocked);
((const CMyToolBarImages*) amp;m_ColdImagesLocked)->MyCopyTemp((CMyToolBarImages*) amp;desttoolbar->m_ColdImagesLocked);
((const CMyToolBarImages*) amp;m_DisabledImagesLocked)->MyCopyTemp((CMyToolBarImages*) amp;desttoolbar->m_DisabledImagesLocked);
((const CMyToolBarImages*) amp;m_LargeImagesLocked)->MyCopyTemp((CMyToolBarImages*) amp;desttoolbar->m_LargeImagesLocked);
((const CMyToolBarImages*) amp;m_LargeColdImagesLocked)->MyCopyTemp((CMyToolBarImages*) amp;desttoolbar->m_LargeColdImagesLocked);
((const CMyToolBarImages*) amp;m_LargeDisabledImagesLocked)->MyCopyTemp((CMyToolBarImages*) amp;desttoolbar->m_LargeDisabledImagesLocked);
}
};
Вызовите CMainFrame для всплывающей подсказки:
BOOL CMyDropDownToolBar::OnUserToolTip(CMFCToolBarButton* pButton, CStringamp; 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;
}
Для фактического первого исправления, необходимого для запуска всего этого:
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;
}
.
.
.
}
Чтобы подсказки инструментов выглядели в соответствии с жирным шрифтом и нормально, используйте 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, CStringamp; rMessage) const;
};
// For customizing the default messages on the status bar and second line of tooltip
void CMyDropDownFrame::GetMessageString(UINT nID, CStringamp; 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;
}
}
}
}
}
Также необходимо изменить CMyDropDownFrame::onCreate(), чтобы иметь дело с участником protect:
int CMyDropDownFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
.
.
.
// "Clone" the original toolbar:
m_pWndOriginToolbar->CopyTempAll(amp;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);
*/
.
.
.
};
Комментарии:
1. Привет @user3161924, спасибо, что поделились решением, и вы также можете принять свой собственный ответ .