Board index » delphi » How to un-popup a popup menu

How to un-popup a popup menu

A normal menu behaves as follows: If I click the File menu, I get a dropdown
menu. Then, if I click the File menu again, the dropdown menu disappears.

Suppose I want a button to open a popup menu. No problem. But then I want a
second click of the button to close the popup. Implementing that
second-click behavior is a problem.

My first thought was to have a global boolean variable (PopupVisible). On
each button click, I check the variable, pop up the menu if the variable is
false, and then set the variable. That works if I only click the button. But
if the popup is visible and I click some other part of the form, the popup
disappears, but my variable still says that the popup is visible. So the
next time I click the button, it doesn't pop up the menu because it thinks
it's already visible.

So I need to reset the variable to false whenever any part of the form is
clicked. The problem is that the form doesn't know it's been clicked if I
click a component on the form. Just as the form has a KeyPreview property,
it needs a ClickPreview property, but there is no such property. Otherwise,
I have to add code to a click event for every component. That seems like a
bad approach because I might forget to do so for some component.

Surely there must be a better way to solve this problem. Any ideas?

 

Re:How to un-popup a popup menu


Quote
> Suppose I want a button to open a popup menu. No problem. But then I want a
> second click of the button to close the popup. Implementing that
> second-click behavior is a problem.
> My first thought was to have a global boolean variable (PopupVisible). On
> each button click, I check the variable, pop up the menu if the variable is
> false, and then set the variable. That works if I only click the button. But
> if the popup is visible and I click some other part of the form, the popup
> disappears, but my variable still says that the popup is visible. So the
> next time I click the button, it doesn't pop up the menu because it thinks
> it's already visible.

_snip_

Richard,

forget it, it will never work as you intend it to. When the popup menu comes
up Windows takes over the message handling and does not let go until the menu
closes one way or the other. Every click outside the menu will close it. So
the menu will *always* be closed when the OnClick event of your button fires!
Even if you go to the trouble to use TrackPopupmenu and duplicate a lot of
menu handling code in the Menus unit to get the message Windows sends to the
menus owner when the menu is closed it will arrive *before* the button is
clicked. So if you reset your global flag in response to the message the
button will still always see the flag as False. The only way to get around
that would be to use a timeout. The timeout period starts when the menu is
closed (to get aware of that you need the messy hack mentioned above), when
the button is clicked inside the timeout it does nothing, outside it pops up
the menu.

The simplest way to solve your problem is to have the menu pop up on top of
the button, you know...

Peter Below (TeamB)  100113.1...@compuserve.com)

Re:How to un-popup a popup menu


Thanks, Peter.

Quote
>>Forget it, it will never work as you intend it to<<

But Word 97 does it. I wonder if any non-Microsoft products do it.

Maybe I've described my problem too narrowly. What I want is a regular menu
(or something that looks and behaves like a regular menu) somewhere other
than at the top of the form. In my case, I want a different menu on each
tab sheet of a page control.

It doesn't appear that I can get a regular menu to appear anywhere other
than at the top of the form. So I put a toolbar on the tab sheet, and added
a flat toolbutton. It looks right -- just like a menu. Setting the
DropdownMenu property of the toolbutton results in the problem I described:
Each time you click the toolbutton, it opens the popup rather than closing
it if it's already open. (So I tried unsuccessfully to write my own click
event code, as described earlier.)

If these Delphi controls are actually using the API controls, Word 97
appears to be using the same controls, except that Word 97 puts the toolbar
on a coolbar. So how does Word 97 have menus (which behave like real menus)
that appear at places other than the top of the form?

Quote
>>Even if you go to the trouble to use TrackPopupmenu and duplicate a lot

of
menu handling code in the Menus unit to get the message Windows sends to
the
menus owner when the menu is closed it will arrive *before* the button is
clicked. So if you reset your global flag in response to the message the
button will still always see the flag as False.<<

What if, in response to that message, I checked the location of the click
to see whether the click was on the button? In any event, it sounds too
complicated for me to write. Maybe this would be a good project for an
experienced component writer.

Re:How to un-popup a popup menu


Richard,

having menus (or lookalikes) on individual tabs is a rather unusual design,
i would say. I would propably opt for changing the parent forms menu on the
fly as pages become active.

I have no idea how MS implemented the button menus in Word 97. But not
anything that looks like a menu and acts like a menu has to be a menu, you
know. MS has a long history of reinventing parts of Windows for the Office
apps. It would not be too hard, for instance, to fake a menu with an
ownerdrawn listbox or a TDrawGrid...

Peter Below (TeamB)  100113.1...@compuserve.com)

Re:How to un-popup a popup menu


Hi Richard,

I spent some time looking into your problem and i found a way to solve most
part of it. It seems that TToolButton with the DropDownmenu already does
everything you need because it will handle the showing of the menu and the
up- and downstate. However it will not clear the menu when you press the
button again.
I approached your question about the closing of the popupmenu as follows:
The popupmenu will close automatically if you click anywhere outside it.
The problem then is how do you know when it is closed (for example when you
click on a form). The way to detect this is because the parentcontrol (from
which the menu is started) will lose focus at that point. TSpeedbuttons gets
a message CM_MOUSELEAVE when this happens.
Because this can get complicated i created a new component for you which i
called TXMenuButton which encapsulates the necesary behaviour. It is
basically a modified TSpeedButton which looks a lot like a TToolButton.
It has one extra property called DropDownMenu which you must set to the
desired PopupMenu. Just install this component, drop a bunch of these
TXMenuButtons on your toolbar and connect them to the popupmenu's.
You will see that you can toggle your menu's etc. The only thing is that
when you point your mouse to an other button it does not automatically show
that menu (as in Word97) you have to click the button. I can not get this to
work because that other button does not get focus as long as the popupmenu
is active !! For the rest i think it should work as you expected.

If you have any questions let me know.

The .PAS file of the component is added as a file.
<<CHECK YOUR MAIL: I MAILED IT TO YOU>>

Good luck,

Ben van Mierlo
(b...@bart.nl)

Re:How to un-popup a popup menu


Your speed button works real well. It opens and closes the popup menu
correctly. But, as you mentioned, it's not quite exactly like a menu in that
you can't move the mouse between buttons and have each button's popup open
and close automatically. Nevertheless, it's still pretty useful.

Have you (or anyone else) ruled out the possibility of having a regular menu
appear some place other than at the top of the form? I started to glance
through my copy of Petzold's Win95 book, and it looks like maybe a menu's
parent window can be something other than a form. But it was too late at
night for me to read it carefully. Maybe someone can tell me "Don't bother"
before I spend a lot of time trying to figure it out.

Other Threads