Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    Multi-menu menu, how to

    Cinema 4D SDK
    sdk c++
    2
    5
    1.1k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • WickedPW
      WickedP
      last edited by

      Hi folks,

      How does one go about making a multi-menu menu, like the shortcuts in the viewport:

      f3985add-0867-47e2-b512-562cb54039aa-image.png

      Can I do this in my own dialog/UA?

      WP.

      wickedp.com

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @WickedP
        last edited by ferdinand

        Hello @WickedP,

        Thank you for reaching out to us. In short - radial menus or any form of "multi-menus" are not part of the public API. There is c4d.gui.ShowPopupDialog but it is blocking, so trying to open two or more menus at once will not work.

        So, you would have to use multiple GeDialog instances at once to do this. And for that you will need a handler for them, something like I did in the quick sketch below. The problem with this is, that you cannot have a dialog of type DLG_TYPE_ASYNC_POPUPEDIT, i.e., a borderless dialog, with a menu. Which then means that you also must (re)-implement menus.

        I personally would not go down that rabbit hole, there is a lot of work and only little reward. Just use a dialog with one menu or ShowPopupDialog.

        Cheers,
        Ferdinand

        FYI: ShowPopupDialog is ShowPopupMenu in C++.

        Code:

        """Realizes a dialog handler which handles multiple dialogs, primarily with the feature that closing
        one dialog entails closing all of them.
        
        Must be run in the script manager.
        """
        
        import c4d
        
        
        class DialogHandler:
            """Realizes the dialog handler object.
            """
            def __init__(self, count=4) -> None:
                self._collection: dict[MyDialog, bool] = {MyDialog(self): True for i in range(count)}
        
            def Open(self):
                for i, dlg in enumerate(self._collection):
                    dlg.Open(c4d.DLG_TYPE_ASYNC, xpos=400+i*100, ypos=400, defaultw=100, defaulth=24)
        
            def OnClose(self, sender: "MyDialog") -> None:
                self._collection[sender] = False
                for dlg, isOpen in self._collection.items():
                    if isOpen:
                        dlg.Close()
        
        class MyDialog(c4d.gui.GeDialog):
            """Realizes the handled dialog.
            """
            def __init__(self, handler: DialogHandler) -> None:
                self._handler: DialogHandler = handler
        
            def CreateLayout(self) -> bool:
                self.MenuSubBegin("Test")
                self.MenuAddString(1000, f"Foo&i{c4d.Ocube}&")
                self.MenuAddString(1001, f"Bar&i{c4d.Osphere}&")
                self.MenuSubEnd()
                return True
        
            def InitValues(self) -> bool:
                return True
        
            def Command(self, id: int, msg: c4d.BaseContainer) -> bool:
                self.Close()
                return True
            
            def AskClose(self) -> bool:
                self._handler.OnClose(self)
                return False
        
        
        handler: DialogHandler = DialogHandler(count=4)
        if __name__ == "__main__":
            handler. Open()
        

        MAXON SDK Specialist
        developers.maxon.net

        WickedPW 1 Reply Last reply Reply Quote 0
        • WickedPW
          WickedP @ferdinand
          last edited by

          Thanks @ferdinand,

          I've made a mock-up of a multi-menu system using dialogs as you suggested. Work-in-progress question:

          When I close my menu system (destroy the dialogs), how can I set another dialog/window as the main focus again? Currently, if I open up my dialogs, and say, go and type something in Notepad, then come back to CInema and close the menus/dialogs, Windows switches back to Notepad as the main focus window. How can I avoid this?

          WP.

          wickedp.com

          ferdinandF 1 Reply Last reply Reply Quote 0
          • ferdinandF
            ferdinand @WickedP
            last edited by ferdinand

            Hello @WickedP,

            hm, good question, you can grab the HWND of a dialog with GeDialog::GetWindowHandle, but there is neither a way to determine the focused CDialog (not a typo, the underlying type of GeDialog) nor set the focused dialog. With ::GetWindowHandle and tracking the active window handle via OS functions, you probably could fiddle things into place. But just as GUI stuff, I personally also would avoid OS backend stuff at all costs.

            But my main question would be: When you use DLG_TYPE_ASYNC_POPUPEDIT will such dialogs actually 'steal' the focus from another dialog/window? My gut feeling would be no, but I did not try.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

            WickedPW 1 Reply Last reply Reply Quote 0
            • WickedPW
              WickedP @ferdinand
              last edited by WickedP

              Thanks @ferdinand,

              Agree. I've avoided using OS-specific calls up until now. But for this one I've had to make an exception. Not an ideal solution, but it seems to work:

              e9057cac-086c-4810-bb9c-c198ecdc2427-image.png

              To get around the lost window focus issue, I'm using the first dialog's Timer() to poll and check if any dialog in the menu has window focus. If none do, e.g., a user has clicked away, the system self-destructs. If a menu selection is made, it sends a Message() back to the calling object with details, and then self-destructs.

              It's all a bit of a hack. But it works. 🤷

              WP.

              Update: I'll mark this thread as solved. If I have any further questions I'll pop back in.

              wickedp.com

              1 Reply Last reply Reply Quote 1
              • ferdinandF ferdinand referenced this topic on
              • First post
                Last post