How to Communicate between SubDialog and main GeDialog



  • Hello,
    I am trying to send messages from a SubDialog to a parent GeDialog. I am using a variation of this example implementation from NiklasR.

    import c4d
    
    PLUGIN_ID = 1000004 # Test ID
    ACTION_ID = 123456
    
    class MainDialog(c4d.gui.GeDialog):
        @property
        def sub_dialog(self):
            if not hasattr(self, '_sub_dialog'):
                self._sub_dialog = SubDialog()
            return self._sub_dialog
    
        def CreateLayout(self):
            self.SetTitle('Main Dialog')
            self.AddButton(1000, 0, name="Open Sub-Dialog")
            return True
    
        def Message(self, msg, result):
            if msg.GetId() == ACTION_ID:
                print msg
            return c4d.gui.GeDialog.Message(self, msg, result)
    
        def Command(self, param, bc):
            print bc
            if param == 1000:
                self.sub_dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=1)
            return True
    
        def Restore(self, pluginid, secref):
            if secref['subid'] == 1:
                return self.sub_dialog.Restore(pluginid, secref)
            else:
                return super(MainDialog, self).Restore(pluginid, secref)
    
    class SubDialog(c4d.gui.GeDialog):
        def CreateLayout(self):
            self.SetTitle('Sub-Dialog')
            self.AddButton(1000, 0, name="Send Message")
            return True
    
        def Command(self, id, msg):
            if id == 1001:
                bc = c4d.BaseContainer()
                bc.SetId(c4d.BFM_ACTION)
                bc.SetInt32(c4d.BFM_ACTION_ID, ACTION_ID)
                self.SendParentMessage(bc)
            return True
    
    class Command(c4d.plugins.CommandData):
    
        def Register(self):
            return c4d.plugins.RegisterCommandPlugin(
                    PLUGIN_ID, "Sub-Dialog Message", 0, None, "", self)
    
        @property
        def dialog(self):
            if not hasattr(self, '_dialog'):
                self._dialog = MainDialog()
            return self._dialog
    
        def Execute(self, doc):
            return self.dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID)
    
        def RestoreLayout(self, secref):
            return self.dialog.Restore(PLUGIN_ID, secref)
    
    if __name__ == '__main__':
        Command().Register()
    
    
    

    I've tried using SendParentMessage but, for whatever reason, my parent dialog isn't receiving the message.

    In my parent GeDialog I've tried using the Command and Message methods, but neither receives the message from the SubDialog.

    Can anyone help? Thank you!



  • Did you try my example which exactly demonstrate the use of a SubDialog?
    SubDialog is about having a dialog embedded into another one.

    If you want to make communicate two independent GeDialog you have to use CoreMessage because there is no hierarchy between them they are both independent windows.



  • Hi @blastframe the main issue I guess is because of your SubDialog inherit from GeDial and not SubDialog.
    Here a quick example

    import c4d
    
    GADGET_ID_SUBDIALOG = 10000
    MSG_ID_SUBDIALOG_LAYOUT_CREATED = 1000001
    
    
    class SubDialogExample(c4d.gui.SubDialog):
    
        def CreateLayout(self):
            """
            This Method is called automatically when Cinema 4D Create the Layout (display) of the SubDialog.
            """
    
            # Creates a Static Text
            self.AddStaticText(1000, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0, "First Sub Dialog", c4d.BORDER_THIN_IN)
            msgContainer = c4d.BaseContainer(MSG_ID_SUBDIALOG_LAYOUT_CREATED)
            self.SendParentMessage(msgContainer)
    
            return True
    
    
    class ExampleDialog(c4d.gui.GeDialog):
    
        # The SubDialog need to be stored somewhere, we will need this instance to be attached to the current Layout
        subDialog = SubDialogExample()
    
        def CreateLayout(self):
            """
            This Method is called automatically when Cinema 4D Create the Layout (display) of the Dialog.
            """
    
            # Adds a Gadget that will host a SubDialog
            self.AddSubDialog(GADGET_ID_SUBDIALOG, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 100, 100)
    
            # Attaches the stored SubDialog to the Gadget previously created
            self.AttachSubDialog(self.subDialog, GADGET_ID_SUBDIALOG)
    
            return True
    
        
        def Message(self, msg, result):
            """
            This Method is called automatically when the GeDialog receives a Message.
            :param msg: The message container.
            :param result: A container to place results in.
            """
    
            # Messages is sent from the GeUserArea in line 65
            if msg.GetId() == MSG_ID_SUBDIALOG_LAYOUT_CREATED:
                print("The GeUserArea, has been draw.")
                return True
    
            return super(ExampleDialog, self).Message(msg, result)
    
    
    def main():
        # Creates a new instance of the GeDialog
        dlg = ExampleDialog()
    
        # Opens the GeDialog, since it's open it as Modal, it block Cinema 4D
        dlg.Open(c4d.DLG_TYPE_MODAL_RESIZEABLE, defaultw=300, defaulth=50)
    
    
    if __name__ == "__main__":
        main()
    

    Cheers,
    Maxime.



  • @m_adam Hi Maxime, thank you for the reply.

    I wasn't able to get it to work. I would like the Subdialog to be its own window, not attached to the Main Dialog. Is this possible? In the documentation for SendParentMessage it says the method is available for GeDialog but is it only for usage with GeUserArea? I don't think I understand the purpose of the Subdialog when used as a gadget. I see in the documentation for Subdialog that it inherits from GeDialog so shouldn't it be able to open as such? Thank you.

    import c4d
    
    PLUGIN_ID = 1000004 # Test ID
    ACTION_ID = 123456
    GADGET_ID_SUBDIALOG = 10000
    
    class SubDialog(c4d.gui.SubDialog):
        def CreateLayout(self):
            self.SetTitle('Sub-Dialog')
            self.AddButton(1001, 0, name="Send Message")
            return True
    
        def Command(self, id, msg):
            if id == 1001:
                bc = c4d.BaseContainer()
                bc.SetId(c4d.BFM_ACTION)
                bc.SetInt32(c4d.BFM_ACTION_ID, ACTION_ID)
                self.SendParentMessage(bc)
            return True
    
    class MainDialog(c4d.gui.GeDialog):
        subDialog = SubDialog()
    
        def CreateLayout(self):
            self.SetTitle('Main Dialog')
            self.AddButton(1000, 0, name="Open Sub-Dialog")
            # Adds a Gadget that will host a SubDialog
            #self.AddSubDialog(GADGET_ID_SUBDIALOG, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 100, 100)
    
            # Attaches the stored SubDialog to the Gadget previously created
            #self.AttachSubDialog(self.subDialog, GADGET_ID_SUBDIALOG)
            return True
    
        def Message(self, msg, result):
            if msg.GetId() == ACTION_ID:
                print "YES"
                return True
            return c4d.gui.GeDialog.Message(self, msg, result)
    
        def Command(self, param, bc):
            print bc
            if param == 1000:
                self.subDialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID, subid=1)
            return True
    
        def Restore(self, pluginid, secref):
            if secref['subid'] == 1:
                return self.subDialog.Restore(pluginid, secref)
            else:
                return super(MainDialog, self).Restore(pluginid, secref)
    
    class Command(c4d.plugins.CommandData):
    
        def Register(self):
            return c4d.plugins.RegisterCommandPlugin(
                    PLUGIN_ID, "Sub-Dialog Message", 0, None, "", self)
    
        @property
        def dialog(self):
            if not hasattr(self, '_dialog'):
                self._dialog = MainDialog()
            return self._dialog
    
        def Execute(self, doc):
            return self.dialog.Open(c4d.DLG_TYPE_ASYNC, PLUGIN_ID)
    
        def RestoreLayout(self, secref):
            return self.dialog.Restore(PLUGIN_ID, secref)
    
    if __name__ == '__main__':
        Command().Register()
    


  • Did you try my example which exactly demonstrate the use of a SubDialog?
    SubDialog is about having a dialog embedded into another one.

    If you want to make communicate two independent GeDialog you have to use CoreMessage because there is no hierarchy between them they are both independent windows.



  • @m_adam Hi Maxime, I did try your example and I saw it working as a gadget but, you're right, I want to communicate between two GeDialogs. I followed your advice on using CoreMessage and found success with SpecialEventAdd. Thank you!


Log in to reply