Click to See Complete Forum and Search --> : CheckMenuItem doesn`t check menu item!!!


Cesario Simões
June 10th, 1999, 03:18 PM
I`m trying check/uncheck a menu item (in the pop-up, of course) but it doesn`t work!
I`m using this code:
void CAgendaDlg::OnMenuItemToCheckOrUncheck()
{
UINT nMenuState;

nMenuState = m_menuPrincipal->GetMenuState( ID_LEMBRARSENHACONTA, FALSE );
if ( nMenuState == 0xFFFFFFFF )
{//erro: não tem este item:
AfxMessageBox ( "Não tem este item no menu.",MB_OK );
}
else
{
if (nMenuState && MF_CHECKED )//MF_CHECKED==8
{
//nMenuState = m_menuPrincipal->CheckMenuItem( ID_LEMBRARSENHACONTA, MF_CHECKED );
//nMenuState = m_menuPrincipal->CheckMenuItem( 5, MF_BYPOSITION | MF_CHECKED );
nMenuState = CheckMenuItem( ID_LEMBRARSENHACONTA, MF_CHECKED );
}
else
{
nMenuState = m_menuPrincipal->CheckMenuItem( ID_LEMBRARSENHACONTA, MF_UNCHECKED );
//nMenuState = m_menuPrincipal->CheckMenuItem( 5, MF_BYPOSITION | MF_UNCHECKED );
nMenuState = CheckMenuItem( ID_LEMBRARSENHACONTA, MF_UNCHECKED );
}
if ( nMenuState == 0xFFFFFFFF )
{//erro: não tem este item:
AfxMessageBox ( "Não tem este item no menu (2).",MB_OK );
}
UpdateData(FALSE);
}
}
Please, help me!

Cesario Simões, Jr.

Cesario Simões
June 10th, 1999, 03:47 PM
I`m using a dialog with menu... This function work in it?

I`m creating the menu using:

m_menuPrincipal = new CMenu;
m_menuPrincipal->LoadMenu(IDR_MENU2);//SetMenu
SetMenu ( m_menuPrincipal );

I have tryed other method: Overriding the message:
void CAgendaDlg::OnUpdateLembrarsenhaconta(CCmdUI* pCmdUI)
{
UINT nMenuState;

nMenuState = m_menuPrincipal->GetMenuState( ID_LEMBRARSENHACONTA, FALSE );
if ( nMenuState == 0xFFFFFFFF )
{//erro: não tem este item:
AfxMessageBox ( "Não tem este item no menu.",MB_OK );
}
else
{
if (nMenuState && MF_CHECKED )//MF_CHECKED==8
{
pCmdUI->SetCheck( 0 );
}
else
{
pCmdUI->SetCheck( 1 );
}
}
}

But it doesn`t work too!


Cesario Simões, Jr.

Coder
June 10th, 1999, 04:05 PM
It looks like an error in your code.

if (nMenuState && MF_CHECKED )//MF_CHECKED==8

This will always be true if nMenuState is not 0. I think you meant:
if( 0 != (nMenuState & MF_CHECKED) ) {
//etc.



The single ampersand performs a bitwise AND, the '&&' is a logical AND.

Cesario Simões
June 11th, 1999, 06:51 AM
I want exactly a logical AND: If it`s TRUE the bit, I want to check the pop-up menu item. But I have another information: My application is dialog-based: it`s a dialog with menu... The function "CheckMenuItem" works in a dialog menu?

Cesario Simões, Jr.

Dave Lorde
June 11th, 1999, 07:58 AM
> I want exactly a logical AND: If it`s TRUE the bit

I think you'll find Coder is right. If you want to test whether the MF_CHECKED bit is set in nMenuState, you should use *bitwise* AND (&) not logical AND (&&).

The logical AND expression will be true if both arguments are non-zero, and nMenuState can be non-zero even if the MF_CHECKED bit is not set. The bitwise AND (&) tests that at least one corresponding bit is set in both arguments, which is what you said you wanted.

Dave

Cesario Simões
June 11th, 1999, 08:39 AM
OK! Isn`t the question... I have changed the code (changing from "&&" to "&") but it`s still not working properly! The pop-up menu item remains unchecked...

Related with the "&&" and "&" stuff:
I wrote this little piece of code and, testing and debuging, the results are:
UINT nMenuState, nTeste1 = 0, nTeste2 = 2, nTeste3 = 3;
BOOL bResult;
bResult = (nTeste1 & nTeste2 );//0&2=0 00000000b & 00000010b = 0
bResult = (nTeste1 && nTeste2 );//0&&2=0 00000000b && 00000010b = 0
bResult = (nTeste2 & nTeste3 );//2&3=2 00000010b & 00000011b = 00000010b
bResult = (nTeste2 && nTeste3 );//2&&3=1(TRUE)00000010b && 00000011b = 00000001b
bResult = (nTeste1 & nTeste2 );//0&2=0 00000000b & 00000010b = 00000000b
bResult = (nTeste1 && nTeste2 );//0&&2=0 00000000b && 00000010b = 00000000b
( BOOL is realy an int )

Doubt? Try it!
:-)

Cesario Simões, Jr.

Dave Lorde
June 11th, 1999, 09:07 AM
What's so surprising? The results are just what I would expect from those operators. It's pretty basic stuff.

To rephrase what I said before: '&&' returns true if both arguments are true (non-zero), and false otherwise. '&' returns the bits set that are common to both arguments.

Dave

Jason Teagle
June 11th, 1999, 09:13 AM
Regarding the '&' vs. '&&' - your results are, of course, correct; but you are getting confused by them.

If you have a value, x, which may or may not have one or more bits set in it, and you want to find out if it has the MF_CHECKED attribute, the correct, FULL test is:

if ( (x & MF_CHECKED) == MF_CHECKED)...

This performs a bitwise comparison, and returns the set of bits which are non-zero in both values (i.e., it masks out all the bits we are not interested in, and leaves the rest). Because we want to see if MF_CHECKED is present, we must compare the result with MF_CHECKED to make sure those bits were present. Thus, if MF_CHECKED was 9 (1001b):

(2 & MF_CHECKED == MF_CHECKED) is FALSE, since 2 (0010b) does NOT contain both the bits in MF_CHECKED.

(13 & MF_CHECKED == MF_CHECKED) is TRUE, since 13 (1101b) contains both the bits in MF_CHECKED.

If the value you want to compare with (MF_CHECKED in this case) only contains one non-zero bit (which is the whole point of mutually-exclusive masks), then the test can be shortened to

if (x & MF_CHECKED)...

since the result of the bitwise comparison will be either equivalent to MF_CHECKED if the one bit is present, or 0.

What this is really saying is

if ( (x & MF_CHECKED) != FALSE)... (FALSE = 0)

What the following is saying:

if (x && MF_CHECKED)...

is equivalent to

if (x != FALSE && MF_CHECKED != FALSE)...

Summary: '&&' and '||' should ONLY be used to create an 'if' when you want two or more conditions to cause the 'if' code to be executed ('if (my_hair_is_green AND my_eyes_are_blue)' ). If you want to perform a test to see if a value includes a mask, use '&'.

Although your results seem to show that you are right, I'm afraid it's just a coincidence.

Cesario Simões
June 11th, 1999, 09:47 AM
OK, you all are correct and I give thanks: your explanation avoid all doubts related with operators '&' and '&&'. But the original question remains unsolved: 'Why the pop menu item isn`t checked?'

Cesario Simões, Jr.

cooper_nc
June 13th, 1999, 06:07 AM
I have the same problem also. I made a new menu item, but for some reason
I can't figure out how to tell it to check and uncheck itself.

Ernie

Jason Teagle
June 14th, 1999, 03:14 AM
Now that I have looked at your code, I can see the problem. Consider the menu:

m_pMenu --> Popup 1 Popup 2 Popup 3
Item 1-1 Item 2-1 Item 3-1
Item 1-2 Item 2-2 Item 3-2
Item 1-3 Item 3-3
Separator
Item 1-4






What you appear to be attempting to do is to check, for example, the Item 1-4 item. What you must remember is that in the above example, m_pMenu points to a menu which contains three items: Popup 1, Popup 2 and Popup 3. As far as m_pMenu is concerned, there is nothing else in its menu. Therefore, attempting to check position 4 or ID_MNU_ITEM_1_4 on m_pMenu has no effect - because m_pMenu does not contain that index or command ID.

Item 1-4 is actually in Popup 1's menu, which is a submenu (but as far as the system is concerned, a menu in its own right). THAT menu DOES have a position 4 and the above ID.

Therefore, you must call m_pMenu->GetSubMenu(0) to retrieve a pointer to Popup 1's menu (position index 0), and THEN check the menu item from there.

Does this help?

cooper_nc
June 14th, 1999, 05:29 AM
I am having the exact problem... I can get the program to tell me whether the
menu is checked or unchecked, but I cannot get it to change it. There has to be a real simple solution... but in hours I cannot find it.

Here is my current code... maybe I am using the wrong function.

Thanks... and if I figure it out... I'll let you all know.

Ernie


void CMainFrame::OnOptionsDisplaymaintitle()
{
CMenu m1;
CMenu *m2;
CString s;
UINT menuState;
UINT x;

m1.LoadMenu(IDR_MAINFRAME);

m2 = m1.GetSubMenu(4);

menuState = m2->GetMenuState(ID_OPTIONS_DISPLAYMAINTITLE,MF_BYCOMMAND);

x=m2->GetMenuItemID(0);
s.Format("%d=%d Mstate=%d (%d %d)",x, ID_OPTIONS_DISPLAYMAINTITLE,
menuState, MF_CHECKED, MF_UNCHECKED);
//OUTPUT IS 32775=32775 Mstate=8 (8 0)
AfxMessageBox(s);

if (menuState == 0xFFFFFFFF){
AfxMessageBox("menu help!");
}

if (0 != (menuState & MF_CHECKED) )
{
AfxMessageBox("CHECKED");
x=m2->CheckMenuItem(0,MF_BYPOSITION);
}
else if (0 == menuState)
{
AfxMessageBox("UNCHECKED");
x=m2->CheckMenuItem(0,MF_BYPOSITION);
}
}

cooper_nc
June 14th, 1999, 05:54 AM
I was looking on this forum at other posts about menu's and one spawned me to finally figure it out. Here is the code that I now have that does actually work!


void CMainFrame::OnOptionsDisplaymaintitle()
{
CMenu *pAddinMenu, *pTopMenu;
UINT menuState;

pTopMenu = AfxGetMainWnd()->GetMenu();
pAddinMenu = pTopMenu->GetSubMenu(4);

ASSERT(pAddinMenu != NULL);

menuState = pAddinMenu->GetMenuState(ID_OPTIONS_DISPLAYMAINTITLE,MF_BYCOMMAND);

if (menuState == 0xFFFFFFFF){
AfxMessageBox("menu help!");
}
if (0 != (menuState & MF_CHECKED) )
{
pAddinMenu->CheckMenuItem(ID_OPTIONS_DISPLAYMAINTITLE,MF_UNCHECKED);
}
else if (0 == menuState)
{
pAddinMenu->CheckMenuItem(ID_OPTIONS_DISPLAYMAINTITLE,MF_CHECKED);
}
}

Jason Teagle
June 14th, 1999, 05:54 AM
When you are calling CheckMenuItem(), you are not ORing in the MF_CHECKED bit in the section:

else if (0 == menuState)
{
AfxMessageBox("UNCHECKED");
x=m2->CheckMenuItem(0,MF_BYPOSITION);
}

You must use MF_BYPOSITION|MF_CHECKED to get the check mark in there. Also, it is not advisable to mix using MF_BYCOMMAND and MF_BYPOSITION - stick to one or the other.

Apart from that, everything looks OK.

Cesario Simões
June 14th, 1999, 12:40 PM
It`s curious: When I check the menu item manualy (via resource editor) and I watch the answer of nMenuState = m_menuPrincipal->GetMenuState( ID_OPES_LEMBRARSENHACONTA, FALSE ); I can see the correct answer! The item is checked (nMenuState is 8). And when this item is manualy unchecked again, I can see nMenuState = 0...
But implementing your sugestion, the result is the same. And the item in menu always stay unchecked...

Cesario Simões, Jr.

Cesario Simões
June 14th, 1999, 04:12 PM
Yess!
It`s working now!
Thak you, very much!

Cesario Simões, Jr.

Jason Teagle
June 15th, 1999, 02:57 AM
Please look at the post of mine, in this thread, dated 6/14/99 1:14am (no, I wasn't up at that time in the morning!) - in that post I DID point out that you needed to grab the submenu to use CheckMenuItem()!

Jason Teagle
June 15th, 1999, 02:58 AM
Please look at the post of mine, in this thread, dated 6/14/99 1:14am (no, I wasn't up at that time in the morning!) - in that post I DID point out that you needed to grab the submenu to use CheckMenuItem()!

Cesario Simões
June 15th, 1999, 06:27 AM
I apologize! Really, you had posted before. Your post are rated correctly (please, take a look...). You have contributed to solve the problem. I recognize it. Incidently then the code start to work, I post the message in response to Mr. Cooper, who also send a good piece of code.
Thank you Mr. Teagle! If sometime you want to visit the South of Brazil and the wonderfull Sta. Catarina Island, I want to guide you here showing the 42 beaches, the lagoons and the water-falls... :-)
Goodbye and thanks again.
Cesario

Cesario Simões, Jr.

cooper_nc
June 15th, 1999, 03:04 PM
Speaking for myself, I had several problems I needed to overcome. If I could have found some code similar to what I posted, I would have saved myself hours. I finally figured it out after reading from several posts, trial and error, and pressing F1 a lot. Thanks for you help. Your information was right but it wasn't a complete solution to Mr Simoes or my problem, at least not enough to title a message "Told you so..."

Ernie Cooper

Jason Teagle
June 16th, 1999, 02:01 AM
I have to disagree. There is nothing more in your 'It works' post than has been posted by myself during this thread. The root of yours and Mr. Simoes' problem was that you were trying to call CheckMenuItem() on the top menu level, whereas the actual item required was in a submenu. I would hope that my previous post had explained that well enough.

I was not looking for any credit, as I come here to try to help people - I just wanted to point out that I had already given an answer which would have solved your problem. Please do not try to dismiss my efforts.

However, if you feel aggrieved, my apologies.