A timed context menu


This is sort of in the same spirit as our previous exercise in writing a timed message box, but this is much easier. Here, we use the handy-dandy WM_CANCELMODE message to get us out of menu mode.

void CALLBACK
MenuTooLateProc(HWND hwnd, UINT uiMsg, UINT idEvent, DWORD dwTime)
{
  SendMessage(hwnd, WM_CANCELMODE, 0, 0);
}

BOOL
TimedTrackPopupMenuEx(HMENU hMenu, UINT uFlags, int x, int y,
    HWND hwnd, LPTPMPARAMS pTpm, DWORD dwTimeout)
{
    UINT idTimer = SetTimer(NULL, IDT_TOOLATE, dwTimeout, MenuTooLateProc);
    BOOL fResult = TrackPopupMenuEx(hMenu, uFlags, x, y, hwnd, pTpm);
    if (idTimer) KillTimer(NULL, idTimer);
    return fResult;
}

Before displaying the menu, we set a timer. (And we use a thread timer because we don't own the hwnd window and therefore don't know what timer IDs are safe to use.) If the timer fires, we send ourselves a WM_CANCELMODE message to cancel menu mode. This causes the system to act as if the user had dismissed the menu without selecting anything, either by hitting ESC or clicking outside the menu. The call to the TrackPopupMenuEx function returns once the user has selected something (or the timeout has elapsed), at which point we clean up by destroying our timer before returning.

Comments (25)
  1. Gwendolene says:

    Is there any way I (as a webmaster) can change what context-menu items appear on right-clicks in Internet Explorer? I know about various Javascript tricks to ban right-clicks…

  2. mb says:

    Is there a reason to hide a menu when a timeout expires? I think the user could be confused by a disappearing menu.

  3. hmm says:

    "we send ourselves a WM_CANCELMODE message"

    SetTimer(NULL) though? Should it read SetTimer(hwnd)?

  4. Bjoern Graf says:

    I’m with mb here: I cannot think of a single reason when to use an expiring menu; And the user might just be in the state of deciding what option to select when the program decides to cancel the menu…

    @ hmm: thread vs. window timer, see the last paragraph.

  5. ac says:

    > And we use a thread timer <<

    So where does the HWND used in MenuTooLateProc come from?

  6. Raymond Chen says:

    My mistake. The window passed to TimedTrackPopupMenuEx needs to be passed to the SendMessage in MenuTooLateProc. Serves me right for writing code without actually running it. Now I need a scratch window…

  7. mb: It’s an example of how to correctly use the Win32 API. The technique could be useful to do similar things. I love seeing these types of examples from Raymond.

  8. Tim Robinson says:

    How about an Office-style that initially opens with some of the items hidden, then shows the rest if the user pauses for a few seconds?

  9. J. Edward Sanchez says:

    Tim Robinson: I don’t think it’s possible to alter a Windows menu while it’s being displayed. You’d have to do it using a fake menu; that’s what Office does.

    Or you could dismiss the initial menu with WM_CANCELMODE, and then pop up the full menu — but that would be ugly.

  10. Shog9 says:

    Gwendolene – don’t ever do this. Please.

  11. Wilhelm Svenselius says:

    Gwendolene: I think I speak for most users (and I’m a web builder myself) when I say, STAY THE HELL AWAY from the web browser’s built-in facilities. You will only annoy people, and we will find ways to work around your site.

    By the way, whatever Javascript tricks you know of to ban right-clicks, sorry to break it to you but they can all be worked around. Trying to block right-clicks is as futile as it is stupid.

  12. Yep says:

    Agree with Wilhelm. Frankly Gwendolene, I just shut off javascript, reload the page and steal whatever I want. There’s nothing you can to stop me, so stop wasting everyone’s time.

  13. Jon Potter says:

    As soon as an image is on my screen it’s been downloaded – all the javascript tricks in the world aren’t going to stop me simply pressing Print Screen to grab it to the clipboard.

  14. Image Thief says:

    Don’t bother with print screen. Just go to your browser’s cache and copy the image from there. Or View | Source, get the URL, and download it directly.

    Sorry for feeding the off-topic-ness, but man I hate those dumb sites that disable right clicks. If any of them actually had stuff worth stealing, I’d do so just to spite them.

  15. Norman Diamond says:

    3/7/2005 11:23 AM J. Edward Sanchez

    > I don’t think it’s possible to alter a

    > Windows menu while it’s being displayed.

    > You’d have to do it using a fake menu;

    > that’s what Office does.

    Doesn’t the Start menu do the same thing in some cases? I seem to recall that disabling personalized (or whatever it’s called now) menus in the classic-style Start button and IE is one of the first things that I do after a fresh install of W2K or WXP. Of course I do the same in Office but that comes later.

  16. Gwendolene says:

    Yes, it’s easy to get around right-clicks, if you’re motivated enough to be reading a tech blog.

    The average user won’t be able to though. And to marketers, decreasing liquidity of content (even at the expense of annoying a small number of users) is a good thing.

    Stop thinking like a developer. Loads of less savvy users actually find stuff like this cool.

    I happen to think that I should dictate the user’s experience on my site, not some evangelist browser developers.

  17. J. Edward Sanchez says:

    Doesn’t the Start menu do the same thing in some cases?

    Yes.

  18. Gwendolene: try clicking on the Menu key in your keyboard. That will display the context menu for a web page.

    At least it has worked on every site I’ve seen trying to block the right mousebutton click.

    — LuisR

  19. Gwendolene said:

    "I happen to think that I should dictate the user’s experience on my site, not some evangelist browser developers."

    Sorry Gwendolene, but this is an appalling statement. The user should always be in control. Let’s say you dictate 8pt fonts – but the person reading the page has difficulty reading text that small – what kind of "experience" are they getting then?

    I know plenty of users who right-click and choose Back (doesn’t move the mouse as much), and their "experience" is ruined by sites that use hoaky methods to disable the menu.

    Even more people use items form the content menu such as Google search and Copy, and Print, all of them have to jump through additional hoops to do something.

    You should be glad that the user has invited you onto their computer and not dictate anything to them.

    If there is some content you truly want to protect, then e-mail me via my blog and let’s discuss other ways to protect "liquidity of content" without hacks that annoy a lot more users than you think.

  20. Moi says:

    Are we competing to find the most geeky ways of getting around right-click disabling JavaScript? I reckon telneting to the webserver and issuing the http commands by hand has to win.

    Can we get back to the normal programming now?

  21. Chris Becke says:

    People who use client side scripting to reduce, rather than increase features do not get my respect.

    As a human being who has to develop stuff that has to be delivered to web sited myself I loath you. I loath you because client script being used to reduce functionality is driving enough people to turn it off that my ability to deliver a compelling user experience is being reduced.

  22. JamesW says:

    Off Topic

    My favourite way of liberating content is to drag the image to the desktop (this works in Firefox and Safari) no need for uber haX0r techniques. If there are lots of images then ‘curl’ is very good – basically an automated version of Moi’s suggestion.

    On Topic(ish)

    @ Tim Robinson

    ‘How about an Office-style that initially opens with some of the items hidden, then shows the rest if the user pauses for a few seconds?’

    AAAAArrrggghhh! That’s even worse than disabling right clicks in web browsers. How I HATE the hiding of things in Office and I hope there is a special circle in hell for whoever dreamt that idea up.

    It is a usability nightmare. When I’m looking for an option I can’t just quickly scan the likely menus – I have to waiiiiiiiit a litttttle whiiiiile until the hidden stuff appears. Adding to the pain is the shuffling of menu items to order them by recent usage: it’s a menu, lay things out logically and keep stuff in the same place so I can find it again later. It is not a *$£&*£$ pop chart – I don’t want a top 10 list of recently used buttons. I know it’s an option that can be turned off but to do so I have to go through the misery outlined above. Oh, and what’s with Tools->Options… and Tools->Customise… in Word? Yay, give the user twice as many places to hunt for options.</RANT>

  23. Norman Diamond says:

    3/8/2005 4:13 AM JamesW

    > How I HATE the hiding of things in Office

    > and I hope there is a special circle in hell

    Aw come on, it only takes a few mouse strokes, just one time after installing Office, and it’s gone. Please reserve the special circle in hell for people who make it impossible for users to fix the broken things they release.

    > Oh, and what’s with Tools->Options… and

    > Tools->Customise… in Word? Yay, give the

    > user twice as many places to hunt for

    > options.</RANT>

    Agreed. But have you looked at Tools->Options? If this setting were buried in there, the user would have 100 times as many places to hunt for it. Even two very similar options, one to display accented uppercase characters (for some versions of French) and one to not automatically convert backslashes to yen signs (for some choices of fonts in documents intended for foreign readership), require hunting in different tabs.</OT>

  24. Moi says:

    JamesW – you’ve tried holding down the shift key and selecting menus in Excel, right…?

  25. JamesW says:

    @Moi

    No – what’s meant to happen? I’ve just tried with Excel 2000 and didn’t notice anything. I did notice that if you Alt-click a menu then Excel hangs…

Comments are closed.

Skip to main content