Karrtik Iyer
asked on
C++ | MFC | CMFCToolbar | Set tool button image as EMF file
Hi Experts,
I would like to know how can I set an EMF file on a disk as image to the CMFCToolBarButton's image.
We have the images of the tool bar buttons given as emf file which we are not supposed to convert to BMP and use it.
Instead we are suppose to directly use the EMF file to set as Tool bar button's image.
Please help and advise.
Thanks,
Karrtik
I would like to know how can I set an EMF file on a disk as image to the CMFCToolBarButton's image.
We have the images of the tool bar buttons given as emf file which we are not supposed to convert to BMP and use it.
Instead we are suppose to directly use the EMF file to set as Tool bar button's image.
Please help and advise.
Thanks,
Karrtik
ASKER
Hi Sara,
I already tried this approach. I could derive my custom class from CMFCToolBarButton, however with this approach, two issues occur.
1> The InsertButton call on CMFCToolBar fails with instance of my custom class derived from CMFCToolBarButton. The create object call inside Insert function fails for my custom class.
CMFCToolBarButtonEx mybutton( MY_ID, -1, _T("My Tool") );
m_nToolBar.InsertButton(my button );
2> Also CMFCToolBarButton does not allow message map to defined for the derived class. The below code fails to compile:
BEGIN_MESSAGE_MAP(CMFCTool BarButtonE x, CMFCToolBarButton)
END_MESSAGE_MAP()
Thanks,
Karrtik
I already tried this approach. I could derive my custom class from CMFCToolBarButton, however with this approach, two issues occur.
1> The InsertButton call on CMFCToolBar fails with instance of my custom class derived from CMFCToolBarButton. The create object call inside Insert function fails for my custom class.
CMFCToolBarButtonEx mybutton( MY_ID, -1, _T("My Tool") );
m_nToolBar.InsertButton(my
2> Also CMFCToolBarButton does not allow message map to defined for the derived class. The below code fails to compile:
BEGIN_MESSAGE_MAP(CMFCTool
END_MESSAGE_MAP()
Thanks,
Karrtik
ASKER
I forgot to update in my question that I could override the DrawButton function of CMFCToolBar and do a playMetaFile using DC object. However I was not sure about the limitation of this DrawButton approach. I would like to know if because of using this DrawButton option, will it cause any default behavior provided by CMFCToolBarButton to get overridden except the image being redrawn, also are there any chances of memory or performance issues?
Sample code:
BOOL CMFCToolBarEx::DrawButton(
CDC* pDC,
CMFCToolBarButton* pButton,
CMFCToolBarImages* pImages,
BOOL bHighlighted,
BOOL bDrawDisabledImages
){
if(pButton->m_nID == MY_ID){
HENHMETAFILE hMetaFile = NULL;
hMetaFile = ::GetEnhMetaFile(L"C:\\sca n_dash_ale rt_d.emf") ;
BOOL retval = pDC->PlayMetaFile(hMetaFil e,pButton- >Rect());
return retval;
}
else
return CMFCToolBar::DrawButton(pD C,pButton, pImages,bH ighlighted ,bDrawDisa bledImages );
}
Sample code:
BOOL CMFCToolBarEx::DrawButton(
CDC* pDC,
CMFCToolBarButton* pButton,
CMFCToolBarImages* pImages,
BOOL bHighlighted,
BOOL bDrawDisabledImages
){
if(pButton->m_nID == MY_ID){
HENHMETAFILE hMetaFile = NULL;
hMetaFile = ::GetEnhMetaFile(L"C:\\sca
BOOL retval = pDC->PlayMetaFile(hMetaFil
return retval;
}
else
return CMFCToolBar::DrawButton(pD
}
(1) i would assume that InsertButton is not a virtual function (i will verify that tomorrow). so you better would provide an empty or dummy bitmap and only use the OnDraw to get what you want.
(2) between BEGIN_MESSAGE_MAP and END_MESSAGE_MAP you would define an variable sized array by means of macros like ON_MESSAGE(...), .... i would assume that an empty array lets the compiler complain. beside of that, you should try to go without a message map cause this is designed for customizing of classes which belong to the mfc framework and less for tool helpers.
Sara
(2) between BEGIN_MESSAGE_MAP and END_MESSAGE_MAP you would define an variable sized array by means of macros like ON_MESSAGE(...), .... i would assume that an empty array lets the compiler complain. beside of that, you should try to go without a message map cause this is designed for customizing of classes which belong to the mfc framework and less for tool helpers.
Sara
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Hi Sara,
InsertButton calls fails at the below location (afxtoolbar.cpp): The button pointer returned is NULL.
CMFCToolBarButton* pButton = (CMFCToolBarButton*) pClass->CreateObject();
ENSURE(pButton != NULL);
And here is the declaration for InsertButton (it is virtual) from afxtoolbar.h:
virtual int InsertButton(const CMFCToolBarButton& button, INT_PTR iInsertAt = -1);
Thanks,
Karrtik
InsertButton calls fails at the below location (afxtoolbar.cpp): The button pointer returned is NULL.
CMFCToolBarButton* pButton = (CMFCToolBarButton*) pClass->CreateObject();
ENSURE(pButton != NULL);
And here is the declaration for InsertButton (it is virtual) from afxtoolbar.h:
virtual int InsertButton(const CMFCToolBarButton& button, INT_PTR iInsertAt = -1);
Thanks,
Karrtik
you need to overload the CreateObject function which is some kind of "virtual" constructor or "factory" code to creating derived objects rather than base class objects.
Sara
Sara
the pClass is of type CRuntimeClass* what is a means to create objects from and get runtime info of CObject derived classes.
to make this feature available for your class you have to use the DECLARE_DYNCREATE macro in the header and the IMPLEMENT_DYNCREATE macro in the cpp file of your derived class.
Sara
to make this feature available for your class you have to use the DECLARE_DYNCREATE macro in the header and the IMPLEMENT_DYNCREATE macro in the cpp file of your derived class.
Sara
About my previous comment: I forgot to mention the attached code uses Gdiplus, so you (if you don't use it yet) will have to initialize it. You can take a look at http://www.codeproject.com/Articles/1112/Starting-with-GDI to see how this can be done in a MFC app.
ZOPPO
ZOPPO
ASKER
Thanks Zoppo, I am trying your code.
Thanks Sara.
I got that working by overriding DrawButton of the CMFCToolbar, does not necessarily have to override the CMFCToolBarButton::OnDraw, I guess.
The question would be say either on OnDraw or DrawButton I playing the EMF file works, however I am unable to get the text below the button working/appearing once I do the PlayMetaFile. How do I get to display the text below the EMF file using this approach?
See code below.
void CMFCToolBarButtonEx::OnDra w(
CDC* pDC,
const CRect& rect,
CMFCToolBarImages* pImages,
BOOL bHorz,
BOOL bCustomizeMode,
BOOL bHighlight,
BOOL bDrawBorder,
BOOL bGrayDisabledButtons
)
{
HENHMETAFILE hMetaFile = NULL;
hMetaFile = ::GetEnhMetaFile(L"C:\\sca n_dash_ale rt_d.emf") ;
CRect myrect = rect;
myrect.DeflateRect(rect.Wi dth()/4,re ct.Height( )/4);
BOOL retval = pDC->PlayMetaFile(hMetaFil e,myrect);
if(retval == TRUE)
{
int i = i + 1;
}
this->m_strText = L"Scan Alert"; //This does not work
}
Thanks Sara.
I got that working by overriding DrawButton of the CMFCToolbar, does not necessarily have to override the CMFCToolBarButton::OnDraw,
The question would be say either on OnDraw or DrawButton I playing the EMF file works, however I am unable to get the text below the button working/appearing once I do the PlayMetaFile. How do I get to display the text below the EMF file using this approach?
See code below.
void CMFCToolBarButtonEx::OnDra
CDC* pDC,
const CRect& rect,
CMFCToolBarImages* pImages,
BOOL bHorz,
BOOL bCustomizeMode,
BOOL bHighlight,
BOOL bDrawBorder,
BOOL bGrayDisabledButtons
)
{
HENHMETAFILE hMetaFile = NULL;
hMetaFile = ::GetEnhMetaFile(L"C:\\sca
CRect myrect = rect;
myrect.DeflateRect(rect.Wi
BOOL retval = pDC->PlayMetaFile(hMetaFil
if(retval == TRUE)
{
int i = i + 1;
}
this->m_strText = L"Scan Alert"; //This does not work
}
ASKER
I guess I shall have to use the CDC and draw my own custom text and custom location. May be because of customised on draw the text set for button doesn't work in the default way as shown in my last post.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
the class has virtual member function OnDraw, so you could derive from it and use an overloaded OnDraw to draw .emf files instead of one bitmap file containing all toolbar button images.
I would assume it is simpler to convert to bitmap but you may make up your own decision.
Sara