Subdialog



  • On 17/11/2016 at 02:18, xxxxxxxx wrote:

    User Information:
    Cinema 4D Version:   16 
    Platform:   Windows  ;   
    Language(s) :     C++  ;

    ---------
    I have a command plugin that opens a second sub-dialog.
    The first time this works, but the second time, the dialog will not create the layout.
    This issue was already posted in Oct 2011

    But I can not get it to work, even with the answers Robert provided.
    Could someone provide an example?

    Here my not working code (mostly copied from the old post).

    H file.
    #define ID_DIALOG 123456789
      
    class RenameDialogTest : public GeDialog
    {
    private:
        String name;
    public:
        virtual Bool CreateLayout(void);
        virtual Bool InitValues(void);
        virtual Bool Command(Int32 id, const BaseContainer& msg);
      
        Bool SetName(String name);
        String GetName();
    };
      
    class MainDialog : public GeDialog
    {
    private:
        RenameDialogTest dlgSub;
      
    public:
        virtual Bool CreateLayout(void);
        virtual Bool InitValues(void);
        virtual Bool CoreMessage(Int32 id, const BaseContainer& msg);
        virtual Bool Command(Int32 id, const BaseContainer& msg);
      
    };
      
    class Dialog : public CommandData
    {
    private:
        MainDialog dlg;
    public:
        virtual Bool Execute(BaseDocument *doc);
        virtual Bool RestoreLayout(void *secret);
    };
      
      
    CPP file.
      
    //Headers from c4d
    #include "c4d.h"
      
    //Headers from Plugin
    #include "test subdialog.h"
      
    //////////////////////////////////////////////////////////////////////////////
    //                                                                            
    //    RenameDialog - GeDialog
    //                                                                            
    //////////////////////////////////////////////////////////////////////////////
      
    // GeDialog.CreateLayout
    //*---------------------------------------------------------------------------*
    Bool RenameDialogTest::CreateLayout(void)
    //*---------------------------------------------------------------------------*
    {
        AddEditText(500, BFH_LEFT, 150, 0);
      
        AddButton(1000, BFH_LEFT, 0, 0, "OK");
        AddButton(1001, BFH_LEFT, 0, 0, "Cancel");
      
        return TRUE;
    }
      
    // GeDialog.InitValues
    //*---------------------------------------------------------------------------*
    Bool RenameDialogTest::InitValues(void)
    //*---------------------------------------------------------------------------*
    {
        SetString(500, name);
        return TRUE;
    }
      
    // GeDialog.Command
    //*---------------------------------------------------------------------------*
    Bool RenameDialogTest::Command(Int32 id, const BaseContainer& msg)
    //*---------------------------------------------------------------------------*
    {
        switch(id)
        {
            case 1000:
                {
                    GetString(500,name);
                    SpecialEventAdd(101010101);
                    Close();
                }
      
            case 1001: 
                {
                    Close();
                }
        }
            
        return TRUE;
    }
      
    //*---------------------------------------------------------------------------*
    Bool RenameDialogTest::SetName(String name)
    //*---------------------------------------------------------------------------*
    {
        this->name = name;
      
        return TRUE;
    }
      
    //*---------------------------------------------------------------------------*
    String RenameDialogTest::GetName()
    //*---------------------------------------------------------------------------*
    {
        return name;
    }
      
    //////////////////////////////////////////////////////////////////////////////
    //                                                                            
    //    MainDialog - GeDialog
    //                                                                            
    //////////////////////////////////////////////////////////////////////////////
      
      
    // GeDialog.InitValues
    Bool MainDialog::InitValues(void)
    {
    	return TRUE;
    }
      
    // GeDialog.CreateLayout
    //*---------------------------------------------------------------------------*
    Bool MainDialog::CreateLayout(void)
    //*---------------------------------------------------------------------------*
    {
        SetTitle("Test");
        AddButton(1000,0,0,0,"Start");
        return TRUE;
    }
    //*---------------------------------------------------------------------------*
      
    // GeDialog.CoreMessage
    //*---------------------------------------------------------------------------*
    Bool MainDialog::CoreMessage(Int32 id, const BaseContainer& msg)
    //*---------------------------------------------------------------------------*
    {
        //GePrint(IntToString(id));
        if(id==101010101)
        {
            GePrint(dlgSub.GetName());
        }
      
        return TRUE;
    }
      
    // GeDialog.Command
    //*---------------------------------------------------------------------------*
    Bool MainDialog::Command(Int32 id, const BaseContainer& msg)
    //*---------------------------------------------------------------------------*
    {
        if(id==1000)
        {
            dlgSub.SetName("test string");
            dlgSub.Open(DLG_TYPE_MODAL,ID_DIALOG);
        }
      
        return TRUE;
    }
                                                                
    //////////////////////////////////////////////////////////////////////////////
    //
    //    Dialog - CommandData
    //                                                                            
    //////////////////////////////////////////////////////////////////////////////
      
    // CommandData.Execute
    //*---------------------------------------------------------------------------*
    Bool Dialog::Execute(BaseDocument* doc)
    //*---------------------------------------------------------------------------*
    {    
        return dlg.Open(DLG_TYPE_MODAL,ID_DIALOG);
    }
      
    // CommandData.RestoreLayout
    //*---------------------------------------------------------------------------*
    Bool Dialog::RestoreLayout(void* secret)
    //*---------------------------------------------------------------------------*
    {
        return dlg.RestoreLayout(ID_DIALOG,0,secret);
    }
      
    Bool RegisterDialog(void)
    {
        return RegisterCommandPlugin(ID_DIALOG,"Dialog",0,NULL,String(),NewObjClear(Dialog));
    }
    


  • On 17/11/2016 at 08:56, xxxxxxxx wrote:

    Hi Pim,
    I agree that there really should be an example of this in the SDK.

    Here is a complete example of a GeDialog plugin that spawns another dockable GeDialog.
    This plugin does not use any .h or resource files. Everything is self contained in the .cpp file.
    So to use this. You don't need to create anything except the .cpp file and the main.cpp file.

    Add these to your main.cpp file:

    Bool RegisterMyDialog_CMD();  
      
    Bool PluginStart(void)  
    {  
      if(!RegisterMyDialog_CMD()) return FALSE;  
      return TRUE;  
    }
    

    The .cpp file:

    //This plugin is an example of using a dialog with a SubDialog that can each be docked into the C4D UI  
    //Then saved to a custom layout  
      
    // be sure to use a unique ID obtained from www.plugincafe.com  
    #define PLUGIN_ID 10000061  
    #define SUBDLG_ID 10000062  
      
    #include "c4d.h"  
    #include "gui.h"  
    //#include "c4d_symbols.h"   <----Not used in this example. No .h files are used  
      
    enum  
    {  
      MY_STATIC_TEXT = 10000,  
      MY_CKBOX,  
      INLINE_CKBOX,  
      MY_BUTTON1,  
      MY_BUTTON2  
    };  
      
    enum  
    {  
      MY_TEXT_GROUP = 20000,  
      MY_BUTTON_GROUP  
    };  
      
      
    //The sub dialog  
    class MySubDialog : public GeDialog  
    {  
      public:  
          MySubDialog(void);  
          virtual Bool CreateLayout(void);  
          virtual Bool InitValues(void);  
          virtual Bool Command(LONG id,const BaseContainer &msg);  
          virtual LONG Message(const BaseContainer &msg,BaseContainer &result);  
          virtual Bool CoreMessage  (LONG id,const BaseContainer &msg);  
    };  
      
    MySubDialog::MySubDialog(void)  
    {}  
      
    Bool MySubDialog::CreateLayout(void)  
    {  
      SetTitle("Sub Dialog");  
      
      GroupBegin(MY_TEXT_GROUP, BFH_SCALEFIT,2,0,"",0);  
      {  
          AddStaticText(MY_STATIC_TEXT,BFH_CENTER,200,15,"",0);  
          AddCheckbox(MY_CKBOX, BFH_CENTER, 20, 20, "MyBox");  
      }  
      GroupEnd();  
      
      GroupBeginInMenuLine();   //Adds the checkbox to the menu area of the dialog window  
      AddCheckbox(INLINE_CKBOX,0,0,0, String("Reset"));  
      GroupEnd();  
        
      return TRUE;  
    }  
      
    Bool MySubDialog::InitValues(void)  
    {  
      // first call the parent instance  
      if (!GeDialog::InitValues()) return FALSE;          
      
      SetString(MY_STATIC_TEXT, "Sub Dialog");  
      this->SetBool(MY_CKBOX, FALSE);  
      this->SetBool(INLINE_CKBOX, FALSE);  
        
      return TRUE;  
    }  
      
    Bool MySubDialog::Command(LONG id,const BaseContainer &msg)  
    {          
      switch (id)  
      {  
          case INLINE_CKBOX:              
              InitValues();      // Executes the InitValues() function to reset the values              
              break;  
      
          case MY_CKBOX:              
              GePrint("Enabled");  
              break;  
      }      
      
      return TRUE;  
    }  
      
    Bool MySubDialog::CoreMessage(LONG id,const BaseContainer &msg)  
    {  
      return GeDialog::CoreMessage(id,msg);  
    }  
      
    LONG MySubDialog::Message(const BaseContainer &msg,BaseContainer &result)  
    {  
      return GeDialog::Message(msg,result);  
    }  
      
      
      
    //The master dialog that is used to open the MySubDialog dialog  
    class MyDialog : public GeDialog  
    {  
      MySubDialog subDlg;  
      INSTANCEOF(MyDialog, GeDialog);  
      
      public:  
          MyDialog(void);  
          virtual Bool CreateLayout(void);  
          virtual Bool InitValues(void);  
          virtual Bool Command(LONG id,const BaseContainer &msg);  
          virtual LONG Message(const BaseContainer &msg,BaseContainer &result);  
          virtual Bool CoreMessage  (LONG id,const BaseContainer &msg);  
          virtual LONG MyDialog::RestoreLayout(LONG pluginid, LONG subid, void *secret);  
    };  
      
    MyDialog::MyDialog(void)  
    {}  
      
    Bool MyDialog::CreateLayout(void)  
    {  
      SetTitle("Main Dialog");  
      
      GroupBegin(MY_TEXT_GROUP, BFH_SCALEFIT,2,0,"",0);  
      {  
          AddStaticText(MY_STATIC_TEXT,BFH_CENTER,80,15,"",0);  
      }  
      GroupEnd();  
      
      GroupBegin(MY_BUTTON_GROUP, BFH_SCALEFIT,2,0,"",0);  
      {  
          AddButton(MY_BUTTON1,BFH_LEFT,100,15,"Open SubDlg");  
          AddButton(MY_BUTTON2,BFH_LEFT,100,15,"Change SubDlg");  
      }  
      GroupEnd();  
        
      return TRUE;  
    }  
      
    Bool MyDialog::InitValues(void)  
    {  
      // first call the parent instance  
      if (!GeDialog::InitValues()) return FALSE;  
            
      SetBool(1001,FALSE);  
      SetString(MY_STATIC_TEXT, "Hello");  
        
      return TRUE;  
    }  
      
    Bool MyDialog::Command(LONG id,const BaseContainer &msg)  
    {          
      switch (id)  
      {  
          case MY_BUTTON1:  
              subDlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID);  
              break;  
      
          case MY_BUTTON2:  
              subDlg.SetBool(MY_CKBOX, TRUE);  
              break;  
      
      }      
      
      return TRUE;  
    }  
      
    Bool MyDialog::CoreMessage(LONG id,const BaseContainer &msg)  
    {  
      return GeDialog::CoreMessage(id,msg);  
    }  
      
    LONG MyDialog::Message(const BaseContainer &msg,BaseContainer &result)  
    {  
      return GeDialog::Message(msg,result);  
    }  
      
    //Restore the subdialog and the main dialog in the layout  
    LONG MyDialog::RestoreLayout(LONG pluginid, LONG subid, void *secret)  
    {  
      LONG newsubid = ((RestoreLayoutSecret* )secret)->subid;  
      if( newsubid == SUBDLG_ID ) return subDlg.RestoreLayout(PLUGIN_ID, pluginid, secret);  
      
      //return MyDialog::RestoreLayout(PLUGIN_ID, 0, secret);  //Used if INSTANCEOF(MyDialog, GeDialog); is not delared in the class  
      return SUPER::RestoreLayout(PLUGIN_ID, 0, secret);  
    }  
      
      
      
    class MyDialog_CMD : public CommandData   //MyDialog_CMD is the class name that needs to be listed in the main.cpp to register it properly   
    {  
      private:  
          MyDialog dlg;  
      
      public:  
          virtual Bool Execute(BaseDocument *doc);  
          virtual LONG GetState(BaseDocument *doc);  
          virtual Bool RestoreLayout(void *secret);  
    };  
      
    LONG MyDialog_CMD::GetState(BaseDocument *doc)  
    {  
      return CMD_ENABLED;  
    }  
      
    Bool MyDialog_CMD::Execute(BaseDocument *doc)  
    {  
      return dlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID, -1, -1, 300, 150);      
    }  
      
    Bool MyDialog_CMD::RestoreLayout(void *secret)  
    {  
      return dlg.RestoreLayout(PLUGIN_ID, 0, secret);  
    }  
      
    Bool RegisterMyDialog_CMD(void)  
    {  
      String help = "Dockable Subdialog Example"; //The help text displayed at the bottom of the C4D UI  
      return RegisterCommandPlugin(PLUGIN_ID, "Dockable Subdialog",0, nullptr, help, gNew MyDialog_CMD);  
    }
    

    -ScottA



  • On 18/11/2016 at 01:16, xxxxxxxx wrote:

    Hello,

    in your code you use the same Id ( ID_DIALOG ) for both dialogs. That won't work.

    If you just want to display a dialog that lets you edit a String you can use the build-in function RenameDialog().

    best wishes,
    Sebastian



  • On 18/11/2016 at 02:13, xxxxxxxx wrote:

    @ScottA, Thanks a lot for the working example.
    I will study it in detail and use it in my own plugin.
    Thanks again.

    @Sebastian, using different Id's did not solve the issue.
    However, I agree the Id's must be different!

    -Pim



  • On 18/11/2016 at 06:40, xxxxxxxx wrote:

    Using ScottA's example I now see what is going wrong, but I cannot explain it.

    The example is working correctly when using only 1 sub dialog.
    It goes wrong when I open the sub dialog a second time.

    What I do:
    In the main dialog:command I open a Modal sub dialog.
    When it is closed, I do some code and open the same Modal sub dialog.
    In the sub dialog command I get the input and Close() the sub dialog.

    This apparently this is not correct.
    When I use Close(), the next sub dialog is empty.
    When I remove the Close() and close the sub dialog by closing the sub dialog window, everything is correct!

    Also the manual states that Close() a Modal dialog is not needed.
    However, I like to close the modal sub dialog after the users confirms his input with a button and not by closing the sub dialog window.

    Bool MyDialog::Command(Int32 id,const BaseContainer &msg)
    {        
        switch (id)
        {
           case MY_BUTTON1:
                subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID);
                ...
                ...
                subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID);
                break;
        }    
        return TRUE;
    }
      
    In the sub dialog:
    Bool SubDialog::Command(Int32 id, const BaseContainer& msg)
    {
            if (id == MY_BUTTONOSMOK) {
                  //Close();	               //here it goes wrong!!!
                 return TRUE;
            }
            
        //# all other ID's            
        return TRUE;     
    } // end Command  
      
    
    


  • On 18/11/2016 at 07:59, xxxxxxxx wrote:

    It works fine for me in R13.
    Try it like this: this->Close();

    The only problem I've had with Close() is that it didn't work on macs.
    I don't know if Maxon ever fixed it.

    -ScottA



  • On 18/11/2016 at 08:45, xxxxxxxx wrote:

    Hi ScottA,

    Did you try it with 2 sub dialogs after each other?
    So opening one, close it process it and then open the same one again.
    For me that is the issue.

    I tried this->Close(), but that did not help.

    -Pim

    PS I am using R16



  • On 18/11/2016 at 09:13, xxxxxxxx wrote:

    2 sub dialogs? Are you opening more than one sub dialog?
    I'm using the code I posted to test it. Which has one main dialog and one sub dialog(another GeDialog).
    I added a close button to the sub dialog.
    When I close the sub dialog with it's close button. And re-open it again using the main dialog. The sub dialog is not empty. It's all still there and working as expected.

    -ScottA



  • On 18/11/2016 at 09:34, xxxxxxxx wrote:

    I use the same sub dialog twice.
    So, in the main dialog I open the sub dialog, do some processing and open the sub dialog once again. Both times in the command of the main dialog.

    Hope this explains.
    Pim



  • On 18/11/2016 at 10:02, xxxxxxxx wrote:

    I don't understand why you are opening the same sub dialog when it's already open?
    Or do you mean that you close the sub dialog, and then re-open it a second time?

    Either way.
    If I open the sub dialog. And then try to open it again(even though it's already open). It still works as expected for me. The sub dialog never goes blank(shows no gizmos).

    Here is my plugin that you can test out.
    No matter which buttons I use on either dialog. The sub dialog always works and never goes blank.
    It should work in R16: http://www2.zippyshare.com/v/XVulPng9/file.html

    -ScottA



  • On 18/11/2016 at 11:24, xxxxxxxx wrote:

    Yes, i close it and open it a second time.
    (New input from the user).
    Thanks for the plugin.

    Pim



  • On 19/11/2016 at 11:52, xxxxxxxx wrote:

    Hi ScottA,

    Here your original file with my additions to show the issue.
    To make it working in R16:
    - changed LONG to Int32
    - changed gNew MyDialog_CMD to NewObjClear(MyDialog_CMD)
    - added #include "c4d.h" in .h file

    - changed the sub dialog mode from DLG_TYPE_ASYNC to DLG_TYPE_MODAL
    - add a second call to open the sub dialog for a second time:

            case MY_BUTTON1:
                subDlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID);
                subDlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID);
                break;
    

    So far it is still working.
    After closing the first (modal) sub dialog, the second one is displayed correctly.

    Now I want to close the Modal sub dialog, when the user entered his input.
    So I add a Close() in the command of the sub dialog

           case MY_CKBOX:            
                GePrint("Enabled");
                Close();
                break;
    

    Now, after  the user entered his input, the first modal sub dialog is closed, but the second one opens up empty!

    Here the full code.

    The .h file
    #define ID_DIALOG 123456789
      
    #include "c4d.h"
      
    class RenameDialogTest : public GeDialog
    {
    private:
        String name;
    public:
        virtual Bool CreateLayout(void);
        virtual Bool InitValues(void);
        virtual Bool Command(Int32 id, const BaseContainer& msg);
      
        Bool SetName(String name);
        String GetName();
    };
     
    class MainDialog : public GeDialog
    {
    private:
        RenameDialogTest dlgSub;
      
    public:
        virtual Bool CreateLayout(void);
        virtual Bool InitValues(void);
        virtual Bool CoreMessage(Int32 id, const BaseContainer& msg);
        virtual Bool Command(Int32 id, const BaseContainer& msg);
      
    };
      
    class Dialog : public CommandData
    {
    private:
        MainDialog dlg;
    public:
        virtual Bool Execute(BaseDocument *doc);
        virtual Bool RestoreLayout(void *secret);
    };
      
    The cpp file:
    //This plugin is an example of using a dialog with a SubDialog that can each be docked into the C4D UI
    //Then saved to a custom layout
      
    // be sure to use a unique ID obtained from www.plugincafe.com
    #define PLUGIN_ID 10000061
    #define SUBDLG_ID 10000062
      
    #include "c4d.h"
    #include "gui.h"
    //#include "c4d_symbols.h"   <----Not used in this example. No .h files are used
      
    enum
    {
        MY_STATIC_TEXT = 10000,
        MY_CKBOX,
        INLINE_CKBOX,
        MY_BUTTON1,
        MY_BUTTON2
    };
      
    enum
    {
        MY_TEXT_GROUP = 20000,
        MY_BUTTON_GROUP
    };
      
      
    //The sub dialog
    class MySubDialog : public GeDialog
    {
        public:
            MySubDialog(void);
            virtual Bool CreateLayout(void);
            virtual Bool InitValues(void);
            virtual Bool Command(Int32 id,const BaseContainer &msg);
            virtual Int32 Message(const BaseContainer &msg,BaseContainer &result);
            virtual Bool CoreMessage  (Int32 id,const BaseContainer &msg);
    };
      
    MySubDialog::MySubDialog(void)
    {}
      
    Bool MySubDialog::CreateLayout(void)
    {
        SetTitle("Sub Dialog");
      
        GroupBegin(MY_TEXT_GROUP, BFH_SCALEFIT,2,0,"",0);
        {
            AddStaticText(MY_STATIC_TEXT,BFH_CENTER,200,15,"",0);
            AddCheckbox(MY_CKBOX, BFH_CENTER, 20, 20, "MyBox");
        }
        GroupEnd();
      
        GroupBeginInMenuLine();   //Adds the checkbox to the menu area of the dialog window
        AddCheckbox(INLINE_CKBOX,0,0,0, String("Reset"));
        GroupEnd();
        
        return TRUE;
    }
      
    Bool MySubDialog::InitValues(void)
    {
        // first call the parent instance
        if (!GeDialog::InitValues()) return FALSE;        
      
        SetString(MY_STATIC_TEXT, "Sub Dialog");
        this->SetBool(MY_CKBOX, FALSE);
        this->SetBool(INLINE_CKBOX, FALSE);
        
        return TRUE;
    }
      
    Bool MySubDialog::Command(Int32 id,const BaseContainer &msg)
    {        
        switch (id)
        {
            case INLINE_CKBOX:            
                InitValues();      // Executes the InitValues() function to reset the values            
                break;
      
            case MY_CKBOX:            
                GePrint("Enabled");
                Close();				//Added Pim
                break;
        }    
      
        return TRUE;
    }
      
    Bool MySubDialog::CoreMessage(Int32 id,const BaseContainer &msg)
    {
        return GeDialog::CoreMessage(id,msg);
    }
      
    Int32 MySubDialog::Message(const BaseContainer &msg,BaseContainer &result)
    {
        return GeDialog::Message(msg,result);
    }
      
      
      
    //The master dialog that is used to open the MySubDialog dialog
    class MyDialog : public GeDialog
    {
        MySubDialog subDlg;
        INSTANCEOF(MyDialog, GeDialog);
      
        public:
            MyDialog(void);
            virtual Bool CreateLayout(void);
            virtual Bool InitValues(void);
            virtual Bool Command(Int32 id,const BaseContainer &msg);
            virtual Int32 Message(const BaseContainer &msg,BaseContainer &result);
            virtual Bool CoreMessage  (Int32 id,const BaseContainer &msg);
            virtual Int32 MyDialog::RestoreLayout(Int32 pluginid, Int32 subid, void *secret);
    };
      
    MyDialog::MyDialog(void)
    {}
      
    Bool MyDialog::CreateLayout(void)
    {
        SetTitle("Main Dialog");
      
        GroupBegin(MY_TEXT_GROUP, BFH_SCALEFIT,2,0,"",0);
        {
            AddStaticText(MY_STATIC_TEXT,BFH_CENTER,80,15,"",0);
        }
        GroupEnd();
      
        GroupBegin(MY_BUTTON_GROUP, BFH_SCALEFIT,2,0,"",0);
        {
            AddButton(MY_BUTTON1,BFH_LEFT,100,15,"Open SubDlg");
            AddButton(MY_BUTTON2,BFH_LEFT,100,15,"Change SubDlg");
        }
        GroupEnd();
        
        return TRUE;
    }
      
    Bool MyDialog::InitValues(void)
    {
        // first call the parent instance
        if (!GeDialog::InitValues()) return FALSE;
            
        SetBool(1001,FALSE);
        SetString(MY_STATIC_TEXT, "Hello");
        
        return TRUE;
    }
      
    Bool MyDialog::Command(Int32 id,const BaseContainer &msg)
    {        
        switch (id)
        {
            case MY_BUTTON1:
                subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID);   //change Pim
                subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID,-1,-1, 200,100, SUBDLG_ID);   // Added Pim
                break;
      
            case MY_BUTTON2:
                subDlg.SetBool(MY_CKBOX, TRUE);
                break; 
      
        }    
      
        return TRUE;
    }
      
    Bool MyDialog::CoreMessage(Int32 id,const BaseContainer &msg)
    {
        return GeDialog::CoreMessage(id,msg);
    }
      
    Int32 MyDialog::Message(const BaseContainer &msg,BaseContainer &result)
    {
        return GeDialog::Message(msg,result);
    }
      
    //Restore the subdialog and the main dialog in the layout
    Int32 MyDialog::RestoreLayout(Int32 pluginid, Int32 subid, void *secret)
    {
        Int32 newsubid = ((RestoreLayoutSecret* )secret)->subid;
        if( newsubid == SUBDLG_ID ) return subDlg.RestoreLayout(PLUGIN_ID, pluginid, secret);
      
        //return MyDialog::RestoreLayout(PLUGIN_ID, 0, secret);  //Used if INSTANCEOF(MyDialog, GeDialog); is not delared in the class
        return SUPER::RestoreLayout(PLUGIN_ID, 0, secret);
    }
      
      
      
    class MyDialog_CMD : public CommandData   //MyDialog_CMD is the class name that needs to be listed in the main.cpp to register it properly 
    {
        private:
            MyDialog dlg;
      
        public:
            virtual Bool Execute(BaseDocument *doc);
            virtual Int32 GetState(BaseDocument *doc);
            virtual Bool RestoreLayout(void *secret);
    };
      
    Int32 MyDialog_CMD::GetState(BaseDocument *doc)
    {
        return CMD_ENABLED;
    }
      
    Bool MyDialog_CMD::Execute(BaseDocument *doc)
    {
        return dlg.Open(DLG_TYPE_ASYNC, PLUGIN_ID, -1, -1, 300, 150);    
    }
      
    Bool MyDialog_CMD::RestoreLayout(void *secret)
    {
        return dlg.RestoreLayout(PLUGIN_ID, 0, secret);
    }
      
    Bool RegisterMyDialog_CMD(void)
    {
        String help = "Dockable Subdialog Example"; //The help text displayed at the bottom of the C4D UI
        return RegisterCommandPlugin(PLUGIN_ID, "Dockable Subdialog",0, nullptr, help, NewObjClear(MyDialog_CMD));
    }
    

    The above code example is a bit silly, but the idea is that the user should enter his data using the same sub dialog twice.

    Hope you can help me.
    If not, the user has to close the sub dialog by closing its window, before he can continue.
    In Python it is working!

    -Pim



  • On 19/11/2016 at 11:55, xxxxxxxx wrote:

    Originally posted by xxxxxxxx

    It should work in R16: http://www2.zippyshare.com/v/XVulPng9/file.html

    I could not download this file. 
    It kept asking me to download other files, before I was allowed to download your file.

    -Pim



  • On 19/11/2016 at 12:59, xxxxxxxx wrote:

    You're opening two sub dialogs that have the same ID# using MY_BUTTON1. That's a big no, no.
    If you want to open 2 sub dialogs. You will need to create a class for each one of them, and give each one a unique ID# to avoid any clashing errors.
    I don't know why it works in Python. But it really shouldn't.

    Can you post your R16 plugin with the source code anywhere?
    I think it will be simpler to debug things having your actual plugin in hand.

    -ScottA



  • On 19/11/2016 at 16:01, xxxxxxxx wrote:

    I am opening the same sub dialog. The dialogs that are opened after each other, are the same.

    Here a link to a zip file with the R16 .h and .cpp file.
    It is the same code as posted earlier.

    Note: I develop in R16, so it is supported under R16, R17 and R18.

    -Pim



  • On 19/11/2016 at 19:47, xxxxxxxx wrote:

    OK. I think I get it.
    What you are doing seems a bit strange to me. But you must have your reasons for wanting to do it.

    Your sub dialog is a class. And just like any class. The way you use them is to make instances of the class. Then use those instances throughout your code.
    So if you want to open the same sub dialog twice. You need to create two instances of it in your master dialog.
    Right now you only have one instance and you're trying to use it twice, which is illegal.

    In your master dialog's class define a new sub dialog class instance

    class MyDialog : public GeDialog  
    {  
      MySubDialog subDlg;  
      MySubDialog subDlg2;  //<---Add this to your code  
      INSTANCEOF(MyDialog, GeDialog);  
      
    //...the rest of the class code
    

    Then open your new sub dialog instance

    Bool MyDialog::Command(LONG id, const BaseContainer &msg)  
    {  
      switch (id)  
      {  
      case MY_BUTTON1:  
          subDlg.Open(DLG_TYPE_MODAL, PLUGIN_ID, -1, -1, 200, 100, SUBDLG_ID);  
          subDlg2.Open(DLG_TYPE_MODAL, PLUGIN_ID, -1, -1, 200, 100, SUBDLG_ID);//<---Like this  
          break;  
      
      case MY_BUTTON2:  
          subDlg.SetBool(MY_CKBOX, TRUE);  
          break;  
      }  
      return TRUE;  
    }
    

    That should prevent the second dialog from becoming empty when the first one is closed.
    *But be warned. I don't think this is a good idea. I don't think these dialogs are meant to be used this way. I don't think they were designed to be created with multiple instances. The support guys can guide you better on that. It just seems wrong to me.
    IMO. The better way to do this is to create another sub dialog class with it's own ID#. Then open them both the same way in your button code.

    -ScottA



  • On 20/11/2016 at 01:00, xxxxxxxx wrote:

    Ok, I like your solution and I agree that the issue might be as you state:
    "Right now you only have one instance and you're trying to use it twice, which is illegal."

    Until the support guys come with another solution, I will do as you suggest. Thanks.

    Note: your solution works!

    To explain my approach.
    I have a plugin in which the user has to input an address and based on that input another address.
    So sometimes one address and sometimes two addresses.
    For both addresses I am using the sub dialog (seems logical to me).

    - show sub dialog
    - user enters address
    - store address.city in firstAddress
    - close sub dialog

    - if firstAddress.city = Amsterdam
       - show sub dialog (again)
       - user enters second address
       - store address.city in secondtAddress
       - close sub dialog


Log in to reply