|
Great example! This is exactly the stuff that I was looking for, but unfortunately I don't use MFC. I don't suppose you know how to get this work using the pure win32 SDK/API? Thanks.
|
|
|
|
|
Not sure if that can be done, or if it would be worth attempting. This code currently relies entirely on MFC, and if not using MFC you would probably be better off doing it from scratch.
|
|
|
|
|
of course it can be done. There's nothing magical about MFC...it is basically a wrapper around Win32 calls. Just look up the info in Visual Studio help for the MENUITEMINFO structure and InsertMenuItem function. It's pretty easy from there.
things could always be worse...
|
|
|
|
|
No, menu API functions can only be used for black&white bitmaps, it would look strange if color bitmap is used. Read documentation for MENUITEMINFO related functions...
|
|
|
|
|
Hi, Warren.
I would like to know how can I change the style of the checkmarks, which appear together de menu item. For example, how can I put them inside a rectangle.
Thank you.
|
|
|
|
|
I think that you can do this. Take a look at the online documentation (www.msdn.microsoft.com) for MENUITEMINFO. In particular take a look at the hbmpChecked member of the structure.
|
|
|
|
|
I like this BmpMenu, but after including
#include "BitmapMenu.h" I get many errors:
c:\..\vc98\include\new(35) : error C2061: syntax error : identifier 'THIS_FILE'
c:\..\vc98\include\new(35) : error C2091: function returns function
c:\..vc98\include\new(35) : error C2809: 'operator new' has no formal parameters
c:\..\vc98\include\new(37) : error C2556: 'void *(__cdecl *__cdecl operator new(void))(unsigned int,const struct std::nothrow_t &)' : overloaded function differs only by return type from 'void *(__cdecl *__cdecl op
erator new(void))(unsigned int)'
c:\..\vc98\include\new(35) : see declaration of 'new'
..
..
c:\..\vc98\include\memory(20) : error C2954: template definitions cannot nest
I'm using VC++ 6.0
Maybe someone knows that to do?
|
|
|
|
|
I don't know what the problem is on initial look. Like I said to others, try to compile with the demo project first, then you have a working version and you can migrate to your code.
It seems to be a template problem. Actually there is no reason the BitmapMenu class needs to be templated. Another way to implement this would be to use the CMenu::Attach function in OnInitMenuPopup. This would remove the templates and make the code slightly more modular. Probably a better method.
|
|
|
|
|
HI, first thanx to you, I have a poject to present to my teacher about the Bitmap menu, i did all steps that you said but i get 6 errors which says :
'messageMap' : cannot access protected member declared in class 'CMDIFrameWnd'
Can you please tell me what should i do?
Sohi
|
|
|
|
|
Hi Sohi,
Well, I am sorry I can't help debug your program. But I know that the code does compile and run on Windows 98/2000/XP and should also work on Windows Me (but haven't talked to anybody that has done it yet). So if you are using one of those OS, it should work.
I would download, compile, and run the demo. Once you have verified that you can run the demo, migrate from the demo to your project.
Warren
|
|
|
|
|
Hi, sohi.
I had the same problem, using MDI. I solve that replacing T_FrameWnd by CMDIFrameWnd in BitmapMenu.h. Try it.
Caranthol.
|
|
|
|
|
Very nice code! I have converted it to a plain win32 API version. A problem:
When the toolbar can be customized, some icons on toolbar may be hided. The code cannot assign bitmaps to menu items whose correspondance ID is hidden on current toolbar...
|
|
|
|
|
Interesting. Did you solve this problem? My applications do not allow customization, and I never tested this.
I think one easy way to solve this problem would be to create a tool bar that does not have any hidden icons and pass it to AddToolBar(). This tool bar could be hidden, so the user would never see it. This is a bit of a hack, but could be done very easily. Would this work?
|
|
|
|
|
This is wuwuli.
I finally sole the problem by a non-MFC way, in the codes, CreateToolbarEx() is used instead of LoadToolbar().
Image list is created directly from bitmap (IDB_TOOLAR) associate with toobar, then customizing of the toolar will not bother again.
//tbButton - button list of toolbar.
//IDB_TOOLAR - bitmap id in resource.
//#define IMAGEWIDTH 18
int imageID = -1;
HIMAGELIST imageList;
for (int i=0; i<sizeof(tbButton)/sizeof(TBBUTTON); i++)
{
if ((UINT)tbButton[i].idCommand == lpDrawItemStruct->itemID)
imageID = tbButton[i].iBitmap;
}
if (imageID == -1) return 0;
imageList = ImageList_LoadImage(g_hinstance, MAKEINTRESOURCE(IDB_TOOLBAR), IMAGEWIDTH, 0, CLR_DEFAULT, IMAGE_BITMAP, 0);
Well, another problem still remain: The icons of system menu are all disappeared. (under win98, win2k works well)
Thanks agian for your nice code, which is best way to draw a bitmap menu if one doesn't want to customize menu too much.
|
|
|
|
|
I think that it is a good idea to not owner-draw the system menu. If you look at most applications that owner-draw their menus, they do not owner-draw the system menu. That gives the system menu a consistent look across applications.
If you are having problems with the drawing of the system menu, you can get the default behavior by adding a single line of code to this project:
At the top of the OnInitMenuPopup function (after calling the base class) add this line:
// Do not owner-draw the system menu.
if (bSysMenu) return;
|
|
|
|
|
Is there any wauy to show menu items with different colors and /or fonts?
I need to change menu items color to another color (like WTL)menus, actually I don't know where (in your nice code)to write my OnDrawItem function.
will u help me?
|
|
|
|
|
Unfortunately further customization of the menus using this method would be difficult. The Microsoft menus are not easy to customize, and when you want to do more than what was done in this article, you are better off going with a complete owner-drawn solution.
Owner-drawing the menus is not too difficult, but you are going to be writting a minimum of twice as much code as was shown in this article.
|
|
|
|
|
Hi Warren,
Thanks for the contribution to CP. I've noticed a few problems. First it isn't using the menu colors I have setup in Control Panel. And second when I move over a menu item which is disabled and has a bitmap the selection goes over the bitmap when it shouldn't. This is just with your demo app. I am running WinXP but I doubt whether that's relevant.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
Neville,
> it isn't using the menu colors I have setup in Control Panel
I tested it using a variety of appearance schemes and menu colors, and it works fine on my system (Win 98). Can you give me some more specifics about what is happening? Since I have only tested it under Win 98, it is possible that this problem is related to using it under XP. However, that seems strange since I am using standard methods of getting the colors such as: GetSysColor(COLOR_BTNSHADOW).
> when I move over a menu item which is disabled and has a bitmap
> the selection goes over the bitmap when it shouldn't
Yes, this is by TTMO design (Time To Move On ). I spent quite a bit of time trying to get a different behavior, but finally got sick of working on it. Actually I don't even like the default MFC behavior, which is that disabled menu items without bitmaps get highlighted (when the mouse is on top of it). This is not how a disabled button acts. It seems to me that the correct behavior is that the entire menu item (bitmap and text) does not get highlighted when it is disabled. However, I think the only way to get that behavior would be to make the disabled items owner drawn.
I wrote some code that would highlight the disabled menu text, but not the disabled menu bitmap. It was working well, but I discovered that it would not work under all appearance schemes so I removed it. I don't really understand what is going on, but I will describe it and maybe someone can enlighten me:
When a disabled menu item is not highlighted, the bitmap area acts like a monochrome display and bitmaps that are drawn will appear in only one color (and you get that highlighted shadow for free). However, when the disabled menu item is highlighted , the bitmap area acts like a color display. If that was all there was to it that would be fine, however after writing code to deal with this I found that under a few appearance schemes the bitmap area acts like the monochrome display even when highlighted. One of these appearance schemes is "Rose". Since I could not figure out how to detect which type of display was currently being used, I could not draw the bitmap correctly in all instances.
I looked at things like current brushes, default bitmaps, etc. but could never make sense of this. If anyone knows what is going on, it would probably be pretty easy for me to update the code, since I have a version that produces an unhighlighted disabled bitmap under most appearance schemes.
Warren
|
|
|
|
|
Warren Gardner wrote:
> it isn't using the menu colors I have setup in Control Panel
I tested it using a variety of appearance schemes and menu colors, and it works fine on my system (Win 98). Can you give me some more specifics about what is happening? Since I have only tested it under Win 98, it is possible that this problem is related to using it under XP. However, that seems strange since I am using standard methods of getting the colors such as: GetSysColor(COLOR_BTNSHADOW).
Hi Warren, I feel a little foolish, it must have been a late night. I was comparing your example app with VC++ which just so happens doesn't use the Control Panel settings. Trust MS to do their own thing. So I was wrong on this one.
Re. the disabled menu items. I think it would be quite disconcerting if the mouse jumped over them or they weren't selected. Also the MS approach allows the user to see status bar help on disabled menu items which is a good idea.
As to any advice on the problem you raised, I'm afraid I don't have any other than have you looked at the other code you refer to in your article.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
It's very simple to use. I tested it on Win2000 and NT4.
On this last system, it can't work because of the dynamic calls to GetMenuInfoWin50 and SetMenuInfoWin50. They are not available.
Do you have an idea to replace ?
|
|
|
|
|
Yes, GetMenuInfo and SetMenuInfo are available in Windows 98/Me/2000/XP, but not in Windows 95/NT. I said in the original article that this would not work under Windows 95, but I should have said 95/NT.
What happens under NT? It would be nice if you got a functioning program without bitmaps , but I suspect what you got was a program that crashed .
|
|
|
|
|
You think right, it crashes !
|
|
|
|
|
How to set this menu to dialog based application?
|
|
|
|
|
I will use the MSDN example project dlgcbr32 to demonstrate this. Dlgcbr32 demonstrates how to add control bars to a dialog based application. Build dlgcbr32 and then follow these steps (the first 5 steps are essentially the same steps given in the original article):
1. Add these files to your project:
BitmapMenu.cpp, BitmapMenu.h, and winuser2.h
2. In Mdlsmain.h add this line:
#include "BitmapMenu.h"
3. In Mdlsmain.h inherit your modeless dialog from BitmapMenu:
class CModelessMain : public BitmapMenu<CModelessDialog>
4. In Mdlsmain.cpp add two message handlers (the third message handler ON_WM_INITMENUPOPUP() is already there):
ON_WM_MEASUREITEM()
ON_WM_DRAWITEM()
5. In Mdlsmain.cpp at the end of the CModelessMain::OnInitDialog() function add the tool bar:
AddToolBar(&m_toolBar);
6. At the beginning of BitmapMenu.cpp add this line:
#include "Modeless.h"
7. At the end of BitmapMenu.cpp add this line:
template BitmapMenu<CModelessDialog>;
8. In Mdlsmain.cpp at the beginning of the function CModelessMain::OnInitMenuPopup() add this line:
BitmapMenu<CModelessDialog>::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
9. At the top of BitmapMenu.h add this line:
#include <afxcmn.h>
|
|
|
|