Solved Erratic Keyboard Messages in GeDialog

Hello,
I am having an issue getting a consistent result with the GeDialog.Message and BFM_INPUT_KEYBOARD. In the code below, I'm listening to BFM_INPUT_CHANNEL 69 (the 'E' key) and printing to the Console. The Message will only work once or twice and then lose functionality until I interact with the GeDialog in some way. Sometimes it takes a few interactions to get it started again. In the screencast below, every time the menu icon and window title are flashing is when I am pressing the 'E' key.

Is there a way to make this interaction more consistent, please?

GeUserArea Message with Keyboard

import c4d, random
from c4d import gui

GADGET_ID_GEUSERAREA = 10000
SCROLL_ID = 10001
SLIDER_ID = 10002

class ExampleGeUserArea(c4d.gui.GeUserArea):
    width = 400
    height = 500
    bmp_cache = None

    def GetBitmap(self):
        bmp = c4d.bitmaps.BaseBitmap()
        bmp.Init(self.width,self.height)
        for h in range(self.height):
            for w in range(self.width):
                r = random.randint(0, 70)
                bmp.SetPixel(w, h, r, r, r)
        return bmp

    def DrawMsg(self, x1, y1, x2, y2, msg):
        self.OffScreenOn()
        self.SetClippingRegion(x1, y1, x2, y2)
        self.DrawSetPen(c4d.Vector(1,0,0))
        self.DrawRectangle(x1, y1, x2, y2)
        if self.bmp_cache == None:
            self.bmp_cache = self.GetBitmap()

        self.DrawBitmap(self.bmp_cache, x1, y1, x2, y2, 0, 0,
                        w=self.bmp_cache.GetBw(),
                        h=self.bmp_cache.GetBh(),
                        mode=c4d.BMP_NORMAL)        

    def Message(self, msg, result):
        # Catch the draw message to cancel it (return True)
        # and call ourself the DrawMsg with the dimension we expect
        if msg.GetId() == c4d.BFM_DRAW:
            self.DrawMsg(0, 0, self.width, self.height, c4d.BaseContainer())

            return True
    
        return c4d.gui.GeUserArea.Message(self, msg, result)

    def GetMinSize(self):
        return self.width,self.height

class ExampleDialog(c4d.gui.GeDialog):
    geUserArea = ExampleGeUserArea()

    def DrawUA(self,scale):
        self.geUserArea.width = int(400*scale)
        self.geUserArea.height = int(500*scale)
        self.LayoutChanged(SCROLL_ID)

    def CreateLayout(self):
        self.SetTitle("GeUserArea")
        if self.ScrollGroupBegin(SCROLL_ID, c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, c4d.SCROLLGROUP_HORIZ | c4d.SCROLLGROUP_VERT):
            self.AddUserArea(GADGET_ID_GEUSERAREA, c4d.BFH_CENTER | c4d.BFH_SCALE | c4d.BFV_CENTER | c4d.BFV_SCALE, initw=gui.SizePix(400), inith=gui.SizePix(500))
            self.AttachUserArea(self.geUserArea, GADGET_ID_GEUSERAREA)
        self.GroupEnd()
        return True

    def Message(self, msg, result):
        device = msg.GetLong(c4d.BFM_INPUT_DEVICE)
        channel = msg.GetLong(c4d.BFM_INPUT_CHANNEL)

        if device == c4d.BFM_INPUT_KEYBOARD:
            if channel==69:
                #E
                print("E pressed.")
        return c4d.gui.GeDialog.Message(self, msg, result)

def main():
    global dlg
    dlg = ExampleDialog()
    dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=1234567, defaultw=300, defaulth=300)


if __name__ == "__main__":
    main()

Thank you.

This happens because tools that will be called twice in short succession gain focus in the C4D layout. Therefore your Dialog loses focus as the Move tool is bound toE.
I don't kbnow exactly how to prevent that behavior, but there should be some message that can be processed. SDK team will be more of help here.

edit: Easy fix: return c4d.NOTOK after your print statement. That consumes the message and does not call the base function, so Cinema simply does not get notified of the event.

This happens because tools that will be called twice in short succession gain focus in the C4D layout. Therefore your Dialog loses focus as the Move tool is bound toE.
I don't kbnow exactly how to prevent that behavior, but there should be some message that can be processed. SDK team will be more of help here.

edit: Easy fix: return c4d.NOTOK after your print statement. That consumes the message and does not call the base function, so Cinema simply does not get notified of the event.

Hi,

i don't think it's the reason, it look like more the even isn't propagate to this window if you really spam like hell.
Instead of EEEEEE if you go ERERERERERERERERERERER it works a lot better.(unless you go too fast)

I will ask the devs to see if there's kind of "optimisation" here.

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

@m_magalhaes Hi Manuel, thank you and @mp5gosu for the replies.

I'm trying to create a keyboard shortcut for my plugin so unfortunately ERERERERERERERERERERER isn't a workaround that I can use. Please let me know what the devs say. Thanks!

hi,

If it's a shortcut, it should work as expected. The input key is there, it's the spam of one key that isn't.
Just as if you press and hold the key down. You will see it catchs one input than wait a bit, than 2 and stop receiving the event.

But let's wait for the devs' answers

Cheers,
Manuel

MAXON SDK Specialist

MAXON Registered Developer

Did you try my proposed fix? 😉

@mp5gosu Sorry, I missed it! That works! In case other devs have a solution, I'll mark yours as the right answer. Thank you!