I am trying to upgrade my MFC MDI application to use the new MFC Feature Pack.
I converted the CToolbar to CMFCToolBar. Now I am trying to disable one item in the toolbar under certain conditions. I listened to the ON_UPDATE_COMMAND_UI message of the item's ID and disabled the item by writing the following:
pCmdUI->Enable(FALSE);
This works perfectly only if the ON_UPDATE_COMMAND_UI message was handled in the CView object but not if handled in the CMFCToolbar derived class.
If there a way to disable an item from the toolbar class itself?
The Toolbar is not part of the command routing in MFC. So it will never get the command and update command UI messages. You can see the command routing in detail here: MFC Command Routing
You could overwrite the OnCmdMsg() method in one of the objects which gets the command messages (as you can see in the link above) and pass the message on to the Toolbar.
Related
I have a CDialogEx Class called Properties in which I handle the ON_COMMAND message. Now, ON_COMMAND should get called when I click the menu item ID_EDIT_PROPERTIES (as a submenu from main menu). The event handler wizard wrote that code for me, but when I start the Application the menu item remains grayed out. I've tried to manually activate it by calling EnableMenuItem when ON_UPDATE_COMMAND_UI happens, but to no avail.
Any help would be greatly appreciated.
You just need to understand how menu items enabling/disabling is handled:
If there is neither ON_COMMAND nor ON_UPDATE_COMMAND_UI handler the item is disabled.
If there exists no ON_UPDATE_COMMAND_UI handler but there is an ON_COMMAND one in the currently active document or view (or even the "mainframe"), the item is enabled.
If there exists a ON_UPDATE_COMMAND_UI handler, en-/disabling the item is determined by the handler (pCmdUI->Enable(bEnableState)).
Also keep in mind that:
You may not call EnableMenuItem() yourself, instead call pCmdUI->Enable(bEnableState) in an ON_UPDATE_COMMAND_UI handler. This affects not only the menu item, but any other "command"-type item (with the same ID), eg main menu, context menu, toolbar or rebar button.
Where to put the handler, is a matter of application design and depends on the data you are processing or representing. It can be put in the mainframe class (if it depends on some "global" data or setting), in the document class (if it depends on or changes some data or setting in the document - possibly affecting all views), or in the view class(-es) (depending on or affecting the current view only).
In your case, if I understand correctly, the item is disabled because the handler is in the CDialogEx-derived class, but no instance of this class has been created yet, ie there exists no ON_COMMAND handler for your ID_EDIT_PROPERTIES command.
Per m_bAutoMenuEnable, When this data member is enabled (which is the default), menu items that do not have ON_UPDATE_COMMAND_UI or ON_COMMAND handlers will be automatically disabled when the user pulls down a menu.
I admit that I don't know ii it is different for CDialogEx, But for CDialog I found that the UPDATE_COMMAND_UI didn't ever work unless I handled the WM_KICKIDLE event.
In your OnKickIdle event handler make a call to:
CWnd::UpdateDialogControls
There is a short tutorial on it here.
Forgive me if CDialogEx supercedes this information and I will remove the answer.
My program/environment...VS2010, C++, MFC100, CWinAppEx, CMDIFrameWndEx. MFC feature pack.
I am creating and handling a CPreviewView derivative. My method treats this preview view as a normal view that the user can keep up and active. Where as the default PreviewView paints over the current view and 'takes over' the child frame.
One thing I can't figure out is how to gain control over the ON_UPDATE_COMMAND_UI message maps that should be directed to all CDocuments. When a CPreviewView is created it somehow disables all the command handlers to CDocuments. The command handlers to CViews are still up and working.
All Documents open in my MDI app don't receive their ON_UPDATE_COMMAND_UI messages. I can move these message handlers out to the View, or Frame but there are too many to do this efficiently.
Does anyone know where in the CPreviewView class turns off document handlers?
First of all, MFC is not a "locked" framework. Its complete source resides on your own PC in the following folder: "your Visual Studio folder"\VC\atlmfc\src\mfc\ (on my PC it is: c:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\atlmfc\src\mfc) The source for CPreviewView is in viewprev.cpp file. I just opened the file and in the DoPrintPreview they are calling this:
pParent->OnSetPreviewMode(TRUE, pState); // Take over Frame Window
According to MSDN this method:
The default implementation disables all standard toolbars and hides the main menu and the main client window. This turns MDI frame windows into temporary SDI frame windows.
I have opened the file called winfrm.cpp and checked that this method is doing, and it does disable all the menu. Obviously, no Update messages will be sent to documents while preview mode is on.
The MSDN article at the hyperlink above says that you need to override the OnSetPreviewMode method for your frame to:
customize the hiding and showing of control bars and other frame window parts during print preview. Call the base class implementation from within the overridden version.
This should not be a problem.
I have a document within MFC C++ application. I need to delete one the buttons from the particular CMFCToolbar within a code (not resources) completely, even preventing a user to restore the button via toolbar customization dialog. At this moment I use RemoveButton method of CMFCToolbar but it only makes the button invisible and it can be restored via toolbar customization dialog that is not an option for me at this time. I will be very glad if you suggest something that can help me there.
There are two internal lists in CMFCToolBar that are used to reset the Buttons upon customization.
They are named m_OrigButtons and m_OrigResetButtons.
You may need to derive your own class and delete the buttons with the specific IDs from there.
But better: Never to include such a button on the first time when the toolbar is created!
I'm using an MFC application with a toolbar.
I need to use a button of this toolbar in some class.
But, i don't find how to map the toolbar button events to methods of my class.
I saw in the property menu that i can map an event to a method. but there the name the the button is not in the events list.
The button is already used in other classes.
So how to map a toolbar button in my class ?
The only classes that receive toolbar messages are view windows, the mainframe, the document and the CWinApp. Toolbar/Menu messages are not routed to other classes. Your question would be clearer if you explain what kind of class you are trying to add the toolbar message handler into.
Another problem is that the Visual Studio wizard assumes that there is a menu command with the same ID as each toolbar button. So it only lists menu IDs, not toolbar IDs that have no matching menu command. But you can easily map a toolbar button to a class method without the wizard's help by putting a line like this in the class message map:
ON_COMMAND(ID_NEW_TOOLBUTTON, OnNewToolbutton)
But it will only work in the above mentioned classes that receive toolbar messages.
I've created a simple Dialog box with a few controls (edit, text, etc) and saved
it to the resource folder in GME/GME.rc/Dialog
I added an auto-gen'd event handler which created a new class (Class.cpp
for the purposes of this example) Note: the Class::Class(CWnd *pParent) :
CDialogEx(Class::IDD, pParent) constructor is empty, I'm not sure if that's
relevant but I don't think it is..
There's a MESSAGE_MAP COMMAND(menu_item_id, &class::member_function())
invocation within the Class.cpp was auto-generated. It's wrapped in the
standard BEGIN_MESSAGE_MAP macro stuff.
However: when the menu item is clicked, the item remains gray. The
properties for "enabled=true" and "gray=false" are both properly
configured. So, I assume this is error is due to the message handler isnt
registered.
Any help would be appreciated.
Without code, it's pretty darn hard to help. Are you sure you put the message handler for the menu id in either a CView, CFrame, CDocument, or CWinApp derived class? If you put the menu handler in your dialog class, it's not going to do you much good.
Dialogs do not contain the code to run through the list of ON_UPDATE_COMMAND_UI handlers that MFC uses to enable menu items. Ordinarily this is handled by CFrameWnd for example. Try calling UpdateDialogControls in your OnInitDialog function.
I see that your code is also missing the ON_UPDATE_COMMAND_UI macro for the menu item, even though the handler it would reference was created for you.
You add menu item handlers to the window that has the menu, which is usually the CMainFrame. Copy the message map and handler to the CMainFrame and see if that helps. I'm not sure what you're trying to do here - I assume you want to display 'Class' (maybe better to edit your post to call this 'ExampleDialog' or something...) when the menu item is clicked, right? Or did you somehow add a menu to your CDialogEx-derived class? If the last, I guess this is what Mark is referring to - 'how are you displaying the menu'? How are you manually adding a menu to your dialog?