Solved It seems that the scroll group has a bug in the R26 version. When the doc is refreshed, it will automatically change its position?

def CreateLayout(self):
        ...
        scrollflags = c4d.SCROLLGROUP_VERT | c4d.SCROLLGROUP_HORIZ | c4d.SCROLLGROUP_AUTOHORIZ|c4d.SCROLLGROUP_AUTOVERT
        if self.ScrollGroupBegin(self.ID_Scroll_Group, c4d.BFH_SCALEFIT| c4d.BFV_SCALEFIT, scrollflags, initw=0, inith=0):
            if self.GroupBegin(self.ID_ProjectSubDlg_Group, c4d.BFH_SCALEFIT| c4d.BFV_SCALEFIT, 1, 0,""):
                    #
                    #
                    #
                    pass  # sub_item_dlgs
                    #
                    #
                    #

            self.GroupEnd()
        self.GroupEnd()
        ...
        return True

    def init_sub_items(self):
        self.sub_item_dlgs = []
        self.LayoutFlushGroup(self.ID_ProjectSubDlg_Group)
        if self.GroupBegin(self.ID_ProjectSubDlg_Group, c4d.BFH_SCALEFIT| c4d.BFV_SCALEFIT, 1, 0,""):
            item_list = sorted(self.structure["items"], key=lambda x: self.structure["items"][x]["order"])
            index = 1
            for item_name in item_list:
                item_data = self.structure["items"][item_name]
                if item_data["type"] != self.get_type():
                    continue
                sub_item_dlg = ProjectSubDlg(self.structure, item_data, index)   ##  Add custom subdialog 
                self.sub_item_dlgs.append(sub_item_dlg)
                self.AddSeparatorH(2,c4d.BFH_SCALEFIT)
                self.AddSubDialog(self.ID_Item_dlg_START+index, flags=c4d.BFH_SCALEFIT)
                self.AttachSubDialog(sub_item_dlg, self.ID_Item_dlg_START+index) 
                index +=1

        self.GroupEnd()
        self.LayoutChanged(self.ID_ProjectSubDlg_Group)

I have creat a list of subdialogs inside scroll group, and subdialog have a function will open doc.when i do this command, the scroll group will also be randomly changed?
and i also can recive the message use:

def Message(self, msg, result):
        if msg.GetId() == c4d.BFM_SCROLLGROUP_SCROLLED :
            print("scroll group change when document refresh")
        return c4d.gui.GeDialog.Message(self, msg, result)

i think this is a bug because it not happen in r24, is there any solution in r26?

Hello @jack0319,

welcome to the Plugin Café and thank you for reaching out to us. For future postings I would recommend having a look at our Forum Guidelines as they will line out important aspects of the support provided here. One of the important points is to provide executable code and clear instructions how to reproduce a problem.

Your problem seems to be that the scroll position of a scroll group is being reset unintentionally. You mention as the cause 'the doc being refreshed'. Since refreshing documents is not established terminology in the Cinema 4D API, and your code is not executable, the problem is not reproducible for me as I simply do not know what you mean by that. In place of refreshing the documents , I tried:

  • Creating a new document
  • Adding an event to a document
  • Pushing a GUI update event to the scroll group gadget

because it either seemed sensible or you were doing something like this in your code.

None of these have any effect on the scroll position of the scroll group in S26.1. Find the example code I produced and the results at the end of the posting. Please provide executable example code of your problem where all unnecessary elements have been removed. At the moment, I simply cannot reproduce your problem.

Cheers,
Ferdinand

The result:
blah_scroll.gif

The code:

"""Example for scroll groups in S26.1 and possible bugs in it.

The example can be run from the script manager.
"""

import c4d
import typing

doc: c4d.documents.BaseDocument
op: typing.Optional[c4d.BaseObject]

class MyDialog (c4d.gui.GeDialog):
    """Provides the dialog containing the scroll group.
    """
    ID_MENU: int = 1000

    ID_GRP_SCROLL: int = 2000
    ID_GRP_CONTAINER: int = 2001
    ID_GDG_BASE: int = 3000

    GADGET_COUNT: int = 100

    def CreateLayout(self) -> bool:
        """Adds a menu with an item to refresh the scroll group, the scroll group and multiple
        gadgets to the dialog.
        """
        self.MenuSubBegin("Menu")
        self.MenuAddString(MyDialog.ID_MENU, "Refresh")
        self.MenuSubEnd()

        defaultFlags: int = c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT

        self.ScrollGroupBegin(MyDialog.ID_GRP_SCROLL, defaultFlags, c4d.SCROLLGROUP_VERT | c4d.SCROLLGROUP_HORIZ)
        self.GroupBegin(MyDialog.ID_GRP_CONTAINER, defaultFlags, 1)
        self.GroupBorderSpace(5, 5, 5, 5)
        self.GroupSpace(3, 3)

        for i in range(MyDialog.GADGET_COUNT):
            self.AddStaticText(MyDialog.ID_GDG_BASE + i, c4d.BFH_SCALEFIT, name=f"Gadget {i}")

        self.GroupEnd() # ID_GRP_CONTAINER
        self.GroupEnd() # ID_GRP_SCROLL

        return super().CreateLayout()

    def Command(self, cid: int, msg: c4d.BaseContainer) -> bool:
        """Refreshes ID_GRP_SCROLL and also sets off EventAdd when ID_MENU is invoked.
        """
        if cid == MyDialog.ID_MENU:
            print ("Refresh Layout & Event Add")
            self.LayoutChanged(MyDialog.ID_GRP_SCROLL)
            c4d.EventAdd()
        return super().Command(cid, msg)

    def Message(self, msg: c4d.BaseContainer, result: c4d.BaseContainer) -> int:
        """From your code, I commented it out, since I do not understand its purpose.
        """
        if msg.GetId() == c4d.BFM_SCROLLGROUP_SCROLLED :
            # print("scroll group change when document refresh")
            pass
        return super().Message(msg, result)

def main() -> None:
    """Opens the dialog.
    """
    global dlg
    dlg = MyDialog()
    dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=500, defaulth=250)



if __name__ == '__main__':
    main()

MAXON SDK Specialist
developers.maxon.net

hi thanks for quick reply ! I'm sorry I didn't explain my problem clearly. I'm not a native English speaker.
By ‘’refresh doc‘’, I mean to add a new doc.
After some tests, I found that the problem was caused by: self.AddMultiLineEditText(self.ID_MultiText, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, initw=0, inith=80, style=0)

"""Example for scroll groups in S26.1 and possible bugs in it.

The example can be run from the script manager.
"""

import c4d
import typing

doc: c4d.documents.BaseDocument
op: typing.Optional[c4d.BaseObject]

class MyDialog (c4d.gui.GeDialog):
    """Provides the dialog containing the scroll group.
    """
    ID_MENU: int = 1000

    ID_GRP_SCROLL: int = 2000
    ID_GRP_CONTAINER: int = 2001
    ID_GDG_BASE: int = 3000

    GADGET_COUNT: int = 100

    def CreateLayout(self) -> bool:
        """Adds a menu with an item to refresh the scroll group, the scroll group and multiple
        gadgets to the dialog.
        """
        self.MenuSubBegin("Menu")
        self.MenuAddString(MyDialog.ID_MENU, "Refresh")
        self.MenuSubEnd()

        defaultFlags: int = c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT
        scrollflags = c4d.SCROLLGROUP_VERT | c4d.SCROLLGROUP_HORIZ | c4d.SCROLLGROUP_AUTOHORIZ|c4d.SCROLLGROUP_AUTOVERT
        self.ScrollGroupBegin(MyDialog.ID_GRP_SCROLL, defaultFlags, c4d.SCROLLGROUP_VERT | c4d.SCROLLGROUP_HORIZ)
        self.GroupBegin(MyDialog.ID_GRP_CONTAINER, defaultFlags, 1)       
        for index in range(10):
            ###  
            self.AddMultiLineEditText(index+10000,  c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, initw=0, inith=80, style=0)
            ###
        self.GroupEnd() # ID_GRP_CONTAINER
        self.GroupEnd() # ID_GRP_SCROLL

        return super().CreateLayout()

    def Command(self, cid: int, msg: c4d.BaseContainer) -> bool:
        """Refreshes ID_GRP_SCROLL and also sets off EventAdd when ID_MENU is invoked.
        """
        if cid == MyDialog.ID_MENU:
            print ("Refresh Layout & Event Add")
            #self.LayoutChanged(MyDialog.ID_GRP_SCROLL)
            self.init_sub_items()
            c4d.EventAdd()
            
        return super().Command(cid, msg)

    def Message(self, msg: c4d.BaseContainer, result: c4d.BaseContainer) -> int:
        """From your code, I commented it out, since I do not understand its purpose.
        """
        if msg.GetId() == c4d.BFM_SCROLLGROUP_SCROLLED :
            # print("scroll group change when document refresh")
            pass
        return super().Message(msg, result)


def main() -> None:
    """Opens the dialog.
    """
    global dlg
    dlg = MyDialog()
    dlg.Open(c4d.DLG_TYPE_ASYNC, defaultw=500, defaulth=250)



if __name__ == '__main__':
    main()

and i dont know how to solve this.

@ferdinand hi, is that a bug or i did something wrong? (i used 'AddMultiLineEditText ' in your code )

Hello @jack0319,

Yes, this is a bug. I had to do some digging first (debug against c4d) to find out what is going wrong here. It seems like this is a bug in the scroll group gadget. I was unable to pinpoint what is going exactly wrong, but when a new document is created, the scroll group position is set again, because Cinema 4D is reinitializing its layout. You currently cannot do anything about this. I have filed a bug report on our bug tracker and will update this thread when the bug has been fixed.

We cannot make any guarantees regarding an ETA and considering that this is a negligible impact bug, it could take multiple revisions until the bug is fixed.

Cheers,
Ferdinand

MAXON SDK Specialist
developers.maxon.net