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

    EditText: intercept/discard keystrokes

    Cinema 4D SDK
    python r20 windows
    2
    7
    1.2k
    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.
    • M
      mp5gosu
      last edited by

      Hello there,

      is it possible to intercept/discard keystrokes on a gadget (EditText) in a GeDialog?
      Seems like all relevant messages are sent after the content has changed.
      With the Dialogs Message() method, I'm not able to retrieve the previous value, when a user enters a text. How's that actually supposed to be done?

      Thanks in advance,
      Robert

      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @mp5gosu, You can react to BFM_INTERACTSTART and detect what key was pressed and in this case, and return True, so next message will not be dispatched and processed.

        class MyDialog(c4d.gui.GeDialog):
            
        
            def CreateLayout(self):
                self.SetTitle("My Python Dialog")
        
                self.AddEditText(1000, c4d.CUSTOMGUI_DESCRIPTION, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 100, 500)        
                self.AddEditText(1001, c4d.CUSTOMGUI_DESCRIPTION, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 100, 500)
                
                return True
        
            def Message(self, msg, result):         
                if msg.GetId() == c4d.BFM_INTERACTSTART:
                    bc = c4d.BaseContainer()
                    if c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.KEY_LEFT, bc):
                        if bc[c4d.BFM_INPUT_VALUE] == 1:
                            if self.IsActive(1000): return True
        
                    if c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD, c4d.KEY_RIGHT, bc):
                        if bc[c4d.BFM_INPUT_VALUE] == 1:
                            if self.IsActive(1000): return True           
        
                return super(MyDialog, self).Message(msg, result)
        

        If you have any question please let me know.
        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 1
        • M
          mp5gosu
          last edited by mp5gosu

          Hi Maxime

          thank you for the example.
          I was in fact also trying BFM_INTERACTSTART but had to scratch that, because at the same time I wanted to poll the actual key being pressed, not testing for a specific key.

          I simply want to implement some "evaluation" when the user types something in, with regards to a certain scheme. Maybe I should have been more precise here. πŸ™‚
          So for now I was able observe the following: BFM_INTERACTSTART does indeed what I want. If the user types something in, I'm able to check the current value of the text box, before it gets changed and may discard the user input. The downside here is, that the msg value is actually an empty BC with its sole purpose to hold its ID.
          (Maybe the result container could carry some more contextual information when starting to interact with gadgets)

          Then, checking the input state is not working either, because it lets me only check for a specific key.
          GetInputEvent doesn't work either, because it's just an event stack and not reliable at all due to its nature.

          Maybe (and theres a good chance) I'm overcomplicating things now, in germany we call it something like "to not see the forest for the trees". πŸ™‚

          Thank you so far,
          Robert

          1 Reply Last reply Reply Quote 0
          • M
            m_adam
            last edited by m_adam

            May I ask you what's the final goal?

            MAXON SDK Specialist

            Development Blog, MAXON Registered Developer

            1 Reply Last reply Reply Quote 0
            • M
              mp5gosu
              last edited by

              Of course! πŸ™‚
              I have an EditText, into which users may enter some text.
              This EditText has to follow these rules:

              1. It must always have 3 characters.
              2. Those 3 characters are always digits (0-9, in any order)
              3. if 1) or 2) do not apply when the user enters or pastes something, set it to the last valid value. This has to be done while the user enters something.

              My workaround so far is to hold a member variable that always keeps the last valid value and replaces it when a user entered something that does not comply to the rules above. The rules are checked with a regular expression.

              I thought, in Cinema may it be possible as well, to intercept messages and to pass, discard or modify them (like in Windows message queue for example).

              1 Reply Last reply Reply Quote 0
              • M
                m_adam
                last edited by m_adam

                Hi mp5gosu, according to your description, I think you should handle everything in the command.

                class MyDialog(c4d.gui.GeDialog):
                    
                    def __init__(self):
                        self.lastValid = ""
                
                    def CreateLayout(self):
                        self.AddEditText(1000, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 100, 50)
                        return True
                
                    def isCorrect(self, s):
                        # It's not correct if it's larger than 3
                        if len(s) > 3:
                            return False
                        
                        # It's do not conatin only number
                        try:
                            int(s)
                        except ValueError:
                            return False
                        
                        return True
                    
                    
                    def Command(self, id, msg):
                        if id == 1000:
                            newStr = self.GetString(id)
                            
                            # If their is no string stored, we have nothing to do
                            if not newStr:
                                self.lastValid = newStr
                                return True
                            
                            # Check if the string fit our format, if yes store the value
                            elif self.isCorrect(newStr):
                                self.lastValid = newStr
                                
                            # Finally if it does not fil the format, this means we have to revert to last valid
                            else:
                                self.SetString(id, self.lastValid)
                                
                        return True
                

                Actually, you can catch and intercept the message, from the UI element, not from the parent (dlg), so if you want to do so, you have to create your own gadget but this is not possible in Python.

                Cheers,
                Maxime.

                MAXON SDK Specialist

                Development Blog, MAXON Registered Developer

                1 Reply Last reply Reply Quote 2
                • M
                  mp5gosu
                  last edited by

                  Thank you Maxime.

                  My current solution looks pretty similar to yours and works .
                  Implementing an own gadget is of course out of scope - I don't even get paid for that. ☺

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post