EditText: intercept/discard keystrokes
-
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 DialogsMessage()
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 -
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. -
Hi Maxime
thank you for the example.
I was in fact also tryingBFM_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 themsg
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 -
May I ask you what's the final goal?
-
Of course!
I have an EditText, into which users may enter some text.
This EditText has to follow these rules:- It must always have 3 characters.
- Those 3 characters are always digits (0-9, in any order)
- 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).
-
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. -
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.