Solved Message when leaving an Edit Text

Hi!
In Javascript there's an event onfocusout triggered when the user has left an editable text input.

Similarly, I want to execute a function when the user leaves the EditText (by Tab or mouse) of my GeDialog. I thought maybe I could listen for the message with the ID of c4d.BFM_LOSTFOCUS, but that seems to be when the entire GeDialog loses focus (similar to c4d.BFM_ACTIVE_CHG). I also tried c4d.BFM_INTERACTEND but that happens after every input, including keystrokes. How can I listen for when a user leaves an EditText please? Thank you!

ids = [c4d.BFM_MARKFOCUS,c4d.BFM_ACTIVE_CHG,c4d.BFM_SETFOCUS,c4d.BFM_INTERACTEND,\
        c4d.BFM_ACTION,c4d.BFM_LOSTFOCUS]

def Message(self, msg, result):
    if msg.GetId() in self.ids:
        for cid,val in msg:
            print cid,val
                
    return c4d.gui.GeDialog.Message(self, msg, result)

@blastframe

Maybe not the best solution, but I have tried the following code (C++) and it displays a text in the console when the Edit Text gets the focus, and displays another text when it loses focus.

Note that 'mActiveEdit' is a custom bool variable, member of MyDialog class,
and ID_TEXTEDIT is the Edit Text gadget id.

Int32 MyDialog::Message(const BaseContainer& msg, BaseContainer& result)
{
	if (IsActive(ID_TEXTEDIT) && !mActiveEdit)
	{
		ApplicationOutput("Activate TextEdit");
		mActiveEdit = true;
	}
	if (!IsActive(ID_TEXTEDIT) && mActiveEdit)
	{
		ApplicationOutput("TextEdit was active");
		mActiveEdit = false;
	}

@blastframe

Maybe not the best solution, but I have tried the following code (C++) and it displays a text in the console when the Edit Text gets the focus, and displays another text when it loses focus.

Note that 'mActiveEdit' is a custom bool variable, member of MyDialog class,
and ID_TEXTEDIT is the Edit Text gadget id.

Int32 MyDialog::Message(const BaseContainer& msg, BaseContainer& result)
{
	if (IsActive(ID_TEXTEDIT) && !mActiveEdit)
	{
		ApplicationOutput("Activate TextEdit");
		mActiveEdit = true;
	}
	if (!IsActive(ID_TEXTEDIT) && mActiveEdit)
	{
		ApplicationOutput("TextEdit was active");
		mActiveEdit = false;
	}

@C4DS This solution works for me! Unless someone from the SDK team advises against for some reason, I'll mark yours as the correct answer. Here's a Python version of your code:

import c4d
from c4d import gui

PLUGIN_ID = 9999996 #Test ID

class My_Dlg(gui.GeDialog):
    mActiveEdit1 = False
    mActiveEdit2 = False
    ID_TEXTEDIT1 = 1001
    ID_TEXTEDIT2 = 1002

    def CreateLayout(self):
        self.SetTitle("Edit Text Focus Events")
        if self.GroupBegin(1000, c4d.BFH_SCALEFIT | c4d.BFV_SCALE |\
            c4d.BFV_CENTER, initw=0, inith=0, cols=1, rows=1, title=""):
            self.GroupBorderSpace(20, 20, 20, 20) #left, top, right, bottom
            self.AddEditText(self.ID_TEXTEDIT1, c4d.BFH_SCALEFIT, 90, 0)
            self.AddEditText(self.ID_TEXTEDIT2, c4d.BFH_SCALEFIT, 90, 0)
        self.GroupEnd()

        return True

    def ActivateEditText(self,id,active):
        activeBool = getattr(self,active)
        if self.IsActive(id) and not activeBool:
            print("Activate TextEdit: %s"%id)
            setattr(self,active,True)
        elif not self.IsActive(id) and activeBool:
            print("TextEdit %s was active"%id)
            setattr(self,active,False)

    def Message(self, msg, result):
        self.ActivateEditText(self.ID_TEXTEDIT1,"mActiveEdit1")
        self.ActivateEditText(self.ID_TEXTEDIT2,"mActiveEdit2")
        return c4d.gui.GeDialog.Message(self, msg, result)

    def Command(self, id, msg):
        return True

def main():
    global myDlg
    myDlg = My_Dlg()
    myDlg.Open(dlgtype=c4d.DLG_TYPE_ASYNC, xpos=-2, ypos=-2,\
        pluginid=PLUGIN_ID, defaultw=300, defaulth=200)

if __name__=='__main__':
    main()

Thanks again!

While the topic is set to solved.

I confirm there is no built-in way for doing what you are asking for.
Maybe it would have more sense to create a Timer, instead of checking in Message (Since Message is called very very often so it may be more interesting to check only each second / 0.5 sec)

Cheers,
Maxime.

@m_adam Great idea! I'll use a Timer :smiley: Thanks Maxime!