Context menu in Dialog

This is a simple context menu test. Because of using WinApi calls to determine the mouse pointer position and the mouse button used, it works only on Windows platform.

As far as I understand those working on other platforms can easily use Python scripts to determine both the mouse pointer position and the mouse button.

DialogContextMenu.odt (20.5 KB)

would be nice if you could list your happy contributions somewhere like in an additional section of General Macros - The Document Foundation Wiki :wink:

Here is another version without direct WinApi calls.
DialogContextMenu_WithPythonScript.odt (16.8 KB)

This uses a Python script (mouse_api.py) to determine both the mouse pointer position and the mouse button used. mouse_api.zip
On Windows: Copy the file mouse_api.py to C:\Program Files\LibreOffice\share\Scripts\python

In case you don’t want to download the script…

import platform

def get_mouse_info():
    system = platform.system()

    if system == "Windows":
        import ctypes

        class POINT(ctypes.Structure):
            _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]

        pt = POINT()
        ctypes.windll.user32.GetCursorPos(ctypes.byref(pt))

        left = ctypes.windll.user32.GetAsyncKeyState(1) & 0x8000 != 0
        right = ctypes.windll.user32.GetAsyncKeyState(2) & 0x8000 != 0

        return pt.x, pt.y, left, right

    elif system == "Linux":
        try:
            import evdev
            devices = [evdev.InputDevice(path) for path in evdev.list_devices()]
            mouse = None

            for dev in devices:
                if 'mouse' in dev.name.lower() or 'pointer' in dev.name.lower():
                    mouse = dev
                    break

            if not mouse:
                raise RuntimeError("Mouse device not found")

            x = y = None
            left = right = False

            for event in mouse.read():
                if event.type == evdev.ecodes.EV_REL:
                    if event.code == evdev.ecodes.REL_X:
                        x = event.value
                    elif event.code == evdev.ecodes.REL_Y:
                        y = event.value
                elif event.type == evdev.ecodes.EV_KEY:
                    if event.code == evdev.ecodes.BTN_LEFT:
                        left = event.value == 1
                    elif event.code == evdev.ecodes.BTN_RIGHT:
                        right = event.value == 1

            return x or 0, y or 0, left, right

        except Exception:
            # Fallback: just location without buttons
            from pynput.mouse import Controller
            mouse = Controller()
            x, y = mouse.position
            return x, y, False, False

    elif system == "Darwin":
        from pynput.mouse import Controller
        mouse = Controller()
        x, y = mouse.position
        return x, y, False, False

    else:
        raise NotImplementedError("Operating system not supported")

Hello, @Pertsa !

If you specify the function header in your example as follows:

Sub ShowContextMenu(oEvent)

then you can analyze the MouseEvent event.
Specifically, the Buttons property indicates which mouse button was pressed, and the X and Y properties indicate the coordinates of the mouse pointer.

2 Likes

The ScriptForge library proposes many solutions to manage menus in different contexts:

All of them manage the mouse (@sokol92, indeed, with the MouseEvent), accept cascading menus, icons, checkboxes, …

1 Like

sokol92

Thanks a lot!

DialogContextMenuInBureBasic.odt (20.2 KB)