Home > ActionScript, Flex > Taking control of right-click in Adobe Flex

Taking control of right-click in Adobe Flex

Adobe was kind enough to give developers the ability to add options to the right-click menu in a Flex application with the use of ContextMenu objects.  However, if you want to customize the way the right-click menu displays, or perhaps do something entirely different when the user clicks the right mouse button, read on to find out how!

Lucky for me (and you) lots of people have been interested in this and there is already a project at code.google.com that takes care of the JavaScript side of things.  Go to http://code.google.com/p/custom-context-menu/ and download the zip file example.  The example is for a Flash application but we can apply the concepts to a Flex application.

Step 1 – Setup custom context menu code

Create a new Flex project in Flex Builder.  Copy rightclick.js and swfobject.js into the html-template folder of your project.  From here, I had to make several changes…

  • I modified the RightClick.init() function to accept an object and container value as input.  This allows me to pass in the name of the application as the object instead of having it be called the same thing every time.
  • I included rightclick.js and swfobject.js in the header of index.template.html.
  • I added a new div to the body called “flashcontent”.
  • I added an onload handler to the body tag to initialize RightClick
  • I replaced AC_FL_RunContent(…) with new SWFObject(…) making sure to maintain all template variables.

After making these changes, I verified that no right-click context menu appears in my application.

Step 2 – Listen for the rightClick event

Next I added a few lines to the main mxml file of my application to listen for the ExternalInterface event that will be dispatched when I right-click my appliction.

private function handleCreationComplete():void
{
    ExternalInterface.addCallback("rightClick", handleRightClick);
}

private function handleRightClick():void
{
    Alert.show("Right Click Success!");
}

Step 3 – Dispatch an event to the correct object

Getting the event to the main application is easy, but we actually want the appropriate child object to be notified when the right-click event occurs.  Since I am not using any double-click events in my application I decided I would treat every right-click event like a double-click event.  Users without a two button mouse (aka Mac users) can simply double-click to get the same menu while users with a two button mouse just have to right-click.  Here is how I make sure the event is dispatched to the appropriate object.

private function handleRightClick():void
{
    var objects:Array = systemManager.getObjectsUnderPoint(
        new Point(mouseX,mouseY));
    if (objects.length>0)
    {
        var object:Object = objects[objects.length-1];
        var relatedObject:InteractiveObject;
        if (object is InteractiveObject)
            relatedObject = object as InteractiveObject;
        else if (object.parent && object.parent is InteractiveObject)
            relatedObject = object.parent;
        var event:MouseEvent = new MouseEvent(
            MouseEvent.DOUBLE_CLICK,true,false,mouseX,mouseY,
            relatedObject);
        object.dispatchEvent(event);
    }
}

Try it out

Right-click on any of the buttons to see a custom popup appear with the button name. Select some items in the DataGrid and right-click to see them appear in a custom popup. Click anywhere else and you will notice the Adobe context menu never appears!  Download the source to start using it in your own applications.


Download the Source

Categories: ActionScript, Flex Tags:
  1. deyounni
    August 31st, 2009 at 19:48 | #1

    little help on the html template –
    did you just wrap everything that was in the body into a div?

    what does your onload look like? something like Rightclick.init()?

    did you simply reace the AF_RUN(…)with SWFObject(…) ?

    – nick on my iphone

  2. Christopher
    August 31st, 2009 at 21:58 | #2

    Click the “Download the Source” link above for the full project. In short, the body tag looks like:

    <body scroll=”no” id=”main” onload=”RightClick.init(‘${application}’,'flashcontent’);”>

  3. deyounni
    September 1st, 2009 at 00:23 | #3

    Missed the download source link the first time.

    Got it working on my machine.

    Any good ideas on making this modular / generic for multiple libraries? Something like a central dispatcher or registration for the right click? because if every component is using this right click, they are gonna have to be managed somehow.

    -Nick

  4. September 1st, 2009 at 05:18 | #4

    This code supports handling different actions for different objects as long as they are children of the application class, just like any other click event. Its up to you whether you implement event listeners in each display component or you build a controller to generalize the behavior. If you come up with a good solution be sure to link to it here so I can check it out.

  5. deyounni
    September 1st, 2009 at 11:58 | #5

    I see, The objects under the mouse are retrieved, and the top most get a double click dispatched from it.

    Maybe a new event, (RightClickEvent extends event), would be better. If you didn’t want to have to hook into the MouseEvent.DOUBLE_CLICK.

  1. No trackbacks yet.
You must be logged in to post a comment.