- Home
- Tutorials
- Flash
- Intermediate
- Context Menus in Flash MX 2004

Page 1 of 1
Neil Webb
Neil Webb is a Flash Platform Developer currently living and working in England. He joined the site when it was just a baby - look at it now! Neil has previously worked for Cambridge University, FIFA and Hutchinson Whampoa among others.
Author: Neil Webb, neil AT nwebb DOT co DOT uk, http://www.nwebb.co.uk
Difficulty Level: Intermediate
Requirements: Flash MX 2004
Assumed Knowledge: Familiarity with basic actionscript (v1)
File(s) to Download: contextmenufiles.zip
Online Example: All examples are embedded within these tutorial pages
Flash MX 2004 introduces the ContextMenu class
We're going to start this tutorial by having a play around with the example below. You will need the Flash 7 plugin in order for this file to work properly. Right-click the blue square and/or the pink square, then choose any one of the new options from the right-click menus (you can have multiple options running simultaneously if you wish). A brief explanation of each option's functionality has been written below the two squares.
As we've just seen, it's now possible to assign custom context menus to our Flash movies. Back in the 'dark ages' (prior Flash MX) right-clicking on a flash movie would bring up a rather unwieldy pop-up menu that looked a little like this:
...and by default this is what we get with Flash MX and Flash MX 2004 too. Flash MX gave us the ability to shorten this menu somewhat by disabling a few of the options, but FMX2 ushers in a new level of control with the ContextMenu class. The Flash dictionary has this to say about the new class:
"The ContextMenu class provides runtime control over the items in the Flash Player context menu, which appears when a user right-clicks (Windows) or Control-clicks (Macintosh) the Flash Player. You can use the methods and properties of the ContextMenu class to add custom menu items, control the display of the built-in context menu items (for example, Zoom In and Print), or create copies of menus"
What may not be instantly apparent from the above description is that we're not just talking about a menu for the main movie. Every instance of a MovieClip, Button and TextField on the main timelinecan now have its very own context menu too. The reason I referred to "main timeline" in itialics is because it isn't possible to assign an instance of the ContextMenu class to any MovieClip, Button or TextField instance that does not [at least effectively] reside on the main timeline. This means that TextFields and Buttons nested inside a MovieClip on the root can be targeted and given their own menu, but a MovieClip nested inside another MovieClip on the root timeline cannot. The following code should help make it a bit clearer:
firstMovieClip.someButton.menu = someContextMenu; //works
firstMovieClip.someTextField.menu = someContextMenu; //works
firstMovieClip.secondMovieClip.menu = someContextMenu; //doesn't work
Another thing to be aware of is that if we assign a custom menu to a MovieClip that contains [child] MovieClips, TextFields or Buttons then those children automatically inherit the menu of the parent MovieClip (unless those Buttons or TextFields are assigned menus of their own). This is a familiar cascading behaviour that we might expect, but what is interesting is how Flash deals with the hitArea for the parent clip. Each of the children now acts as a separate hit area for the parent clip, but click in an area inbetween these children and the root menu will appear instead. Again, this is easier to clarify with an example...
If you right-click on one of the letters below you will see a custom menu with the brand new option "Dance Baby!!!" Go on, right-click and choose the new option.
Okay, so the letter M should be merrily dancing away at this point. This is all well and good, but how do we stop it from dancing? We will discuss a proper method to do this shortly, but for now just refresh this webpage page in the browser (press F5). Go ahead and refresh it now, because we need the letter "M" to be stationary for this next part...
Both letters in the above swf are contained within a MovieClip called mcLetters. When you right-clicked on either letter, Flash displayed the context Menu that had been assigned to mcLetter. With both letters now stationary you can see that clicking inbetween(or outside) of the letters means that the default flash menu is displayed instead of the custom one. By clicking inbetween the "M" and the "X" we can assume that we are actually clicking on mcLetters but the custom menu for mcLettersis not displayed because only the contents of the clip are acting as its hitAreas. If this would be a problem for your application in terms of functionality, it can easily be solved by creating a background graphic for the mcLetters MovieClip, and giving the background an alpha of 0.
Before we take a look at the code there is at least one more thing that we need to be aware of. Custom context menus will only work for swfs that are embedded in HTML (or tested in the Flash authoring environment). They will not work for standalone files (exe and swf without the accompanying HTML file).
We've covered a lot of ground so far and still haven't seen any real code yet. Here is the minimal amount of code needed to produce our "dance baby!!!" example as seen above:
var lettersCM = new ContextMenu();
lettersCM.hideBuiltInItems();
var dance = new ContextMenuItem("Dance Baby!!!", doDance);
lettersCM.customItems.push(dance);
function doDance() {
mcLetters.dancer.gotoAndPlay(2);
}
mcLetters.menu = lettersCM;
All instances of the ContextMenu begin life with a copy of an array called customItems, in which we store our menu links. Using the Array.push() method of the Array object we now need to push our newly created menu item into the customItems array. Following that we create the "doDance" function which, when called simply instructs the "M" movieclip to play onwards from frame 2, and finally we associate our ContextMenu instance with our movie clip, using the keyword menu. Viola, the MovieClip "mcLetters" now has a new menu!
Something to note about this code before we move on; In my code I used a standard function. You may or may not be aware that there are two types of functions - standard and literal:
//standard function
function funcName(){
trace("I always get processed before other code");
}
//literal function
someVarName = function(){
trace("I get processed as I'm encountered");
}
We have the ability to do quite a bit more than we have done so far in our example, and we will start to take a look at these extra options now. In both the examples so far I chose to hide all of the built in menu items using the hideBuiltInItems() method of our ContextMenu object, but we actually have more control than that, and can choose to hide/display built-in items on an individual basis. I could just have removed the ability to 'print' by replacing lettersCM.hideBuiltInItems() with the line lettersCM.builtInItems.print = false;
Also, our function doDance was actually being sent two arguments, although we didn't use either of them. The first argument is a reference to the object that was under the mouse when it was clicked, and the second is a reference to the ContextMenu item. Let's re-write our function to make use of these:
function doDance(obj, item) {
trace(obj); //traces _level0.mcLetters
trace(item.caption); //traces Dance Baby!!!
}
Now just to confuse you, I mentioned above that the ContextMenuItem has an onSelect event Handler, but so does ContextMenu! It is the latter which we will be using in the next example.
ContextMenu.onSelect() is very useful to us because it is invoked before the menu is actually displayed. When you right-click, onSelect is invoked, and just milliseconds later the menu appears. To the naked eye it looks as if the menu appears immediately. This means that we can make important decisions about what the menu displays based on the current state of our movie or other criteria. For example, along with the ContextMenuItem.enabled property which we mentioned above, we could do something like this:
var myContextMenu = new ContextMenu();
var item1 = new ContextMenuItem("about this button", aboutBtnFunc);
myContextMenu.customItems.push(item1);
//cmObj is a reference to the ContextMenu object
myContextMenu.onSelect = function(obj, cmObj){
if(obj instanceof MovieClip){
item1.enabled = false;
}
}
someMovieClip.menu = myContextMenu;
function aboutBtnFunc(obj){trace("you press all the right buttons!")}
Okay, so do you remember our letter "M", dancing non-stop like some amphetamine-fuelled loonatic ... what was missing was a way to make him stop using the context menu, and we now almost have enough information to do that. It must be a 'he', because when was the last time you saw a girl dance that badly? Mind you, I'm not such a bad mover myself.
We could have put both options on the menu simultaneously, but that wouldn't be very professional, so instead we'll swap the options around. When he's dancing we'll swap the "Dance Baby!!!" option to say "Stop!!!". Look at the example below to see what I mean:
The last thing needed in order to achieve this is knowing how to make our links visible or invisible. The most appropriate way for us here is to do so when we instantiate a new instance of the ContextMenuItem class. We have already seen how to pass in the minimum amount of arguments needed, caption (ie link name) and callbackFunction. Here are the rest:
//code has been line-wrapped for formatting purposes
new ContextMenuItem
(caption,callbackFunc,[separatorBefore,[enabled,[visible]]])
So, without further ado, here is a screenshot of the code needed to make it all work ("Hurray" I hear you cheer). The fla is available for download (and also contains the "blue & pink squares" example that we saw way back at the beginning of this tutorial.
Note: Some code may be line-wrapped for tutorial formatting purposes. This does not affect performance of the swf.:
That's it for yet another tute. The code has been commented and shouldn't pose any problems for you given your newfound knowledge. I recommend that you look at the code for the blue & pink squares fla (along with the explanations in the Actionscript dictionary for reference), as there are things in it that have not been possible to cover in this tutorial. Bye for now.
If you have any suggestions or comments about this or any of my tutorials you can email me at and I will do my best to answer them. Please note that due to the volume of Flash-related emails I get, I now prioritize emails related directly to the tutorials themselves. You may find answers to your questions already posted on Flash forums such as actionscript.org This, and other tutorials can be found on nwebb.co.uk
Spread The Word
Related Articles
1 Response to "Context Menus in Flash MX 2004" 
|
said this on 04 May 2007 3:21:26 AM CDT
This helps with custom cursors in flash.
When you rightclick in flash, the cursor reappears. So, to make sure it hides correctly after the context menu is gone, do a check to see if the menu was actually shown: (only snippets shown, cursor is the name of the custom cursor, customCM is the context menu, the code was done on the main timeline) [CODE] var rightClicked = false; customCM.onSelect = function(obj, cmObj) { rightClicked = true; } //this is to check if the mouse buttons are pressed _root.onEnterFrame = function() { if (Key.isDown(2)) //show mouse when rightclick menu is visible { Mouse.show();//so the actual cursor comes back //function in the custom cursor for animation etc. //true means RMB was clicked (so menu appears) cursor.rightClick(true); } if (Key.isDown(1)) //hide mouse when menu disappears { Mouse.hide(); if(rightClicked) //only does this if the context menu was shown. { //closing animation, etc, when context menu closed cursor.rightClick(false); cursor._x = _xmouse; cursor._y = _ymouse; rightClicked = false; } } } [/CODE] The cursor.rightClick(inMenu:Boolean) is just a function that animates the cursor for opening/closing the context menu. I placed the custom cursor to the left of the current _xmouse pos and swapped it to a different cursor icon, so it looked like the menu appeared from the custom cursor. |



Author/Admin)