tags:

views:

257

answers:

2

Hi!

I made an MFC application, and now i want to turn off the window's close button during i do my copy operations. I did it successfull with this code:

BOOL bEnable = FALSE;    // To disable

UINT menuf = bEnable ? (MF_BYCOMMAND) : (MF_BYCOMMAND | MF_GRAYED | MF_DISABLED);

CMenu* pSM = GetSystemMenu(  , FALSE );
if ( pSM )
{
  pSM->EnableMenuItem( SC_CLOSE, menuf );
}

But now, at the end of my program in my thread ( UINT CopyThread( LPVOID pParam ) ) i want to reenable it, but i can't. I passed earlier to my thread the m_hWnd, and now i wan't to pass this to the GetSystemMenu function but i get a compiler error : error C2440: 'initializing' : cannot convert from 'HMENU' to 'CMenu *'. I'm sure that this is an easy question, but i'm a beginner, so please help, but i can't figure it out, what i'm doing worng!

Thanks in advance!

kampi

Update: I tried this way, which almost works. The Close "X" will be black again, but if i press it, my program doesn't exists. Am i doing something wrong, or this is because something else?

BOOL bEnable = TRUE;     // To enable
UINT menuf = bEnable ? (MF_BYCOMMAND) : (MF_BYCOMMAND | MF_GRAYED | MF_DISABLED);

HMENU pSM = ::GetSystemMenu( Test->hWnd, FALSE );
if ( pSM )
{
    ::EnableMenuItem(pSM, SC_CLOSE, menuf );
}
+2  A: 
  1. There is an easy way to disable 'close' menu in the system. Please add the bit of CS_NOCLOSE into the class style. You may change the class style by using SetClassLong.

  2. Why don't you just use Win32 API, not MFC function? For example, just use ::GetSystemMenu that returns HMENU. In general, you can create CMenu from the HMENU by CMenu::FromHandle, but in such simple case, it's much better to use directly Win32 API.

Please note that the mapping between MFC objects (e.g., CMenu, CWnd) and Win32 Handles (e.g., HMENU, HWND) is somewhat complex. The reason why I said it complex is there are two types of the mapping: temporal and permanent. If you make CMenu by calling CMenu::FromHandle, it is a temporary mapping; the mapping will be disconnected (i.e., CMenu object will be deleted) when the idle handler (OnIdle) is called next time. On the contrary, if you create a CWnd object and create an actual Window (note that MFC doesn't automatically create a real Window object by just creating CWnd), then there is a permanent mapping between CWnd and HWND.

minjang
Be aware the CS_NOCLOSE will affect _ALL_ windows of that class in the process. This is not usually a problem for your Application window, but may be a problem for popup windows.
John Knoeller
Thanks! That's right.
minjang
Hi! I updated my post. This works almost fine, but is press the button after re-enabling it, it doesn't quit :( Do you know why?
kampi
Sorry, it didn't worked, because i forgot to comment out some code. My mistake. Thanks for your help!
kampi
A: 

GetSystemMenu is the name of a Win32 api that returns HMENU, GetSystemMenu is also the name of an MFC method on the CWnd class, so when you are in a method of the CWnd class, you will use the MFC GetSystemMenu method which returns CMenu, but when you aren't you will use the Win32 API, which returns HMENU.

You can use ::GetSystemMenu to always use the Win32 API. Or you can add a public method to your class that derives from CWnd can call it to do the menu fixup.

John Knoeller