CCMenuItem default fires its block on touchup. I'd like to change this to touchdown. Anyway to perform this without modifying CCMenu class (which would break other parts). Can this be done in a category?
Wonder why the events are not implemented same way as UIKit (free event selection).
You can subclass CCMenuItem and make this behaviour possible by overriding selected, unselected and activate, depending on your needs.
You can then use your new class in CCMenu so that you can lay it out automatically and the rest of your app will continue to function.
You can still use a CCMenuItem outside of a CCMenu and toggle touches yourself. Use the selected, unselected and activate methods. No need to modify the CCMenu.
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.
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!
A CCMenuItemImage will call the selector after the touch that was pressing it releases it.
However, is it not possible to make it call the selector as soon as the touch presses it? This is to create a faster effect in the menu.
subclass CCMenuItemImage and process the event
-(void) selected{
// do you thing : for example you could have a target:selector pair of
// properties added in your implementation.
[super selected];
}
i use that to detect a long touch and pop a contextual tooltip window (for example).
Is there a way to create a event to the QGraphicsView created without creating another class and inheriting the QGraphicsView?
I want to know if there's a way to do something like that:
ui->gView->AddEvent(click, functionName);
Thanks.
If you want to handle mouse click event for the view, install an event filter to the view and watch for MouseButtonPress event.
Below is what I came up with. Wonder if there's easier way to do it.
Suppose I want only menu layer to be touchable while it's up.
I put invisible layer that will swallow touches.
bool tNoTouchLayer::init()
{
if(!CCLayer::init()) {
return false;
}
setIsTouchEnabled(true);
return true;
}
void tNoTouchLayer::registerWithTouchDispatcher()
{
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}
bool tNoTouchLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
return true;
}
Now I can add the noTouchLayer before adding menu layer, and all touches would be stolen by noTouchLayer.
Lastly, i did find more info on this:
http://code.google.com/p/cocos2d-iphone/issues/detail?id=1033
the reason that menu items are stealing touches is because menu items have their touch priority set to the highest (lowest char value) possible...
you can change kCCMenutouchPriority to be 0 instead.
That's how you do it as far as I can tell. Note however that your code will not disable any menues added to the scene. To do that you have to remove the menu from the touch dispatcher when adding the popup and add it back again when removing the popup.
To remove a menu from the touch dispatcher you can do the following:
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(menu);
and to add it back you can do this:
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(menu, kCCMenuHandlerPriority, true);
where menu is your CCMenu node.
As a tip, I created a class like the one above but I also added the popup menu to it, creating one touch blocking menu in one node. :)
this isn't exactly the answer you are looking for, but here's something up for thought:
if you're trying to do this for a pop-up, would it be possible to try to pop up a subclass of UIAlertView (one that looks the way you want it to)?
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-uialertview-custom-graphics/
Here's another approach:
keep state of the app and which layer is "on top".
in each of your menu listeners, have them all do a check to see if the state of your current layer should allow for that menu button to be pressed.
also, you can override "addchild" to see if it's a MenuItem, and if it is a MenuItem, then have it check to see if it should be enabled. if not, return immediately instead of executing the rest of the code
If I understand your question correctly, I guess you try to do something like "pause screen" to pop up and disable all other layers.
Well, you said in your comment that you won't like to enable touch event in other areas but not your pop-up's area. Basically, I would think we should think in term of layer for easier understanding, and easier to implement.
Let's see if we have "main layer" which holds other game objects to show as its childs (assume that they also are running animation). Now you touch a button and want to pop up "pause layer". You have to do the following in order to disable all touch event from others layer + objects.
Pause layers' schedule and actions [via pauseSchedulerAndActions()]
Pause all of its game objects inside the layer (ie. enemies) [via pauseSchedulerAndActions()]
Disable CCMenu object (if any), this will ignore touch event on CCMenu related object ie.CCMenuItemImage [via setEnabled(false)]
Disable touch event for layer itself [via setTouchEnabled(false)]
The first 2 points are about stop running any schedule method, and animation.
The latter 2 points are about stop accepting touch event. You can see that CCMenu* related class maintains its own touch event separately from CCLayer, thus we need to do additional effort by set to both CCMenu* object and the layer itself.
I tried this and it works well for me. Also it's better as we don't have to involve setting dispatcher directly in my opinion.