Intuitive, right? Incidentally, this resource is defined in the .rc2 file and the ATL_IDW_MENU_BAR identifier is used as a default parameter of the CreateSimpleCEMenuBar method of the CFrameWindowImplBase class template. So what do you have to do in order to change the menu bar? Gasp!
ATL_IDW_MENU_BAR SHMENUBAR DISCARDABLE
BEGIN
IDR_MAINFRAME,
2,
I_IMAGENONE, ID_ACTION, TBSTATE_ENABLED, TBSTYLE_AUTOSIZE,
ID_ACTION, 0, NOMENU,
I_IMAGENONE, ID_MENU, TBSTATE_ENABLED, TBSTYLE_DROPDOWN TBSTYLE_AUTOSIZE,
ID_MENU, 0, 0,
END
There is a better way, fortunately. A way that you can encapsulate and that makes the whole process a bit more transparent.
You create a Windows Mobile menu bar by calling the SHCreateMenuBar API typically from your main window's WM_CREATE handler. As you can see the function takes a single parameter, a pointer to a SHMENUBARINFO structure where you define the menu bar. There are two ways to create a menu bar: you either specify a menu bar resource ID or you provide your own HMENU by specifying the SHCMBF_HMENU flag. This is in fact a much more palatable alternative because you can declaratively create your menu bar in a single location of your application's code. Using my beloved WTL, here's how the code would look like on the main frame's OnCreate handler:
The m_mainMenu variable is a CMenu, of course. The advantage of this approach is that you create the main menu bar in a very explicit way and if you later want to change it you know where to find the code, and stop guessing what that crappy SHMENUBAR resource declaration means...
if(m_mainMenu.CreateMenu())
{
m_mainMenu.AppendMenu(MF_BYCOMMAND MF_ENABLED MF_STRING,
ID_BACK, _T("Back"));
m_mainMenu.AppendMenu(MF_BYCOMMAND MF_ENABLED MF_STRING,
ID_MENU, _T("Menu"));
SHMENUBARINFO mbi = { 0 };
mbi.cbSize = sizeof(mbi);
mbi.hwndParent = m_hWnd;
mbi.dwFlags = SHCMBF_HMENU;
mbi.nToolBarId = (UINT)(HMENU)m_mainMenu;
mbi.hInstRes = ModuleHelper::GetResourceInstance();
mbi.nBmpId = 0;
mbi.cBmpImages = 0;
mbi.hwndMB = NULL;
BOOL bRet = ::SHCreateMenuBar(&mbi);
if(bRet != FALSE)
{
m_hWndCECommandBar = mbi.hwndMB;
SizeToMenuBar();
}
}
CodeProject
2 comments:
hey... that's nice blog... it remembers me of my school days.. thanks.... hope u'll keep doin it...!!!!
cell phone number reverse search
Hi,
It's been a long time I didn't check your website and I can see that you are still active about Windows Mobile.
I have some comments about MenuBar and Windows Mobile and I have solved lots of issue by using a mix of static creation and dynamic update.
Let me explain :
In a real world application with internationalization support and multiple views it's generally simpler to create a MB for each view.
But in my case I always create only 2 types of menubar :
One with a single button and another one with two and when a view is loaded I am using a small class I wrote to change labels, add menu items ...
Something like :
CCommandBarEx cmdbar;
cmdbar.GetButton( 1, CCommandBarEx::BY_INDEX ).SetWindowText()
0 is the left button and 1 the right one.
This class is just a wrapper playing with TB_GETBUTTONINFO and TB_SETBUTTONINFO.
You can even disable a button by setting an invalid cmd id.
If I don't forget I will publish it.
Post a Comment