Drop down menu for any TControl

前端 未结 2 869
庸人自扰
庸人自扰 2020-12-18 04:02

Continue of this topic:

Drop down menu for TButton

I have wrote a generic code for DropDown memu with any TControl, but for som

2条回答
  •  忘掉有多难
    2020-12-18 05:01

    Requirements

    If I understand you correctly, then the requirements are:

    1. At the first left mouse button click on a Control, a PopupMenu should be shown beneath the Control.
    2. At the second left mouse button click an that same Control, the shown PopupMenu should be closed.

    Realize that, disregarding the implementation of requirement 1 for the moment, requirement 2 happens automatically: when you click outside a PopupMenu, the PopupMenu will close. This concludes to that the implementation of the first should not interfere with the second.

    Possible solutions:

    • Count the clicks on the Control: at the first click, show the PopupMenu and at the second click, do nothing. But this will not work, because the PopupMenu may be closed already by clicks elsewhere and then a second click should actually be the first click.
    • At the first click, show the PopupMenu. At the second click, determine whether the PopupMenu is still shown. If so, then do nothing. Otherwise, assume a first click. This also will not work, because when a second click is processed, the PopupMenu will be already closed.
    • At the first click, show the PopupMenu. At the second click, determine whether the PopupMenu is closed sometime during the last couple of milliseconds. If so, then the disappearance is due to this very second click and do nothing. This is the solution you are currently using by utilizing the fact that TPopupMenu.Popup will not return until the PopupMenu is closed.

    The current implementation

    1. During the OnClick event of a Control:
      • The OnMouseDown event of the control is assigned to a custom handler,
      • The PopupMenu is Shown.
    2. On the second click on the Control:
      • The time when then PopupMenu was closed is saved (this is still during execution of the previous OnClick event),
      • The custom OnMouseDown event handler is called,
      • If the saved time was within the last 100 milliseconds, the mouse capture is released and all execution is aborted.

    Note: a possibly already OnMouseDown event setting is not saved and gone!

    Why this works for a Button

    A TCustomButton handles click events by responding to a by Windows send CN_COMMAND message. That is a specific Windows BUTTON sytem class control characteristic. By canceling the mouse capture mode, this message is not send. Thus the Control's OnClick event is not fired on the second click.

    Why this doesn't work for a Panel

    A TPanel handles click events by adding the csClickEvents style to its ControlStyle property. This is a specific VCL characteristic. By aborting execution, subsequent code due to the WM_LBUTTONDOWN message is stopped. However, the OnClick event of a TPanel is fired somewhere down its WM_LBUTTONUP message handler, thus the OnClick event is still fired.

    Solution for both

    Use davea's answer on your other question wherein he simply does nothing if the saved time of the PopupMenu's closing was within the last 100 milliseconds.

提交回复
热议问题