Dialogs and InputsStates

On 24/05/2017 at 23:32, xxxxxxxx wrote:

Hello!

I'm learning about dialogs and inputs states. I'm looking into it, but there are some things I don't fully understand. In this case I want to make a basic dialog that return one string information with one "OK" button and "Cancel" button. I already wrote the code and works correctly but I don't understand the correct way to assign inputs commands to "OK" (Enter Key) and "Cancel" (esc Key).

But, If I execute a basic input states without dialogs works great. When I assign this inputs states the dialog stop working, doesn't recognize the OK and Cancel actions.

Can someone help me to understand what is happening?

Here is the code with one input state for the OK button:

import c4d
from c4d import gui
 
LBL_INFO = 1000
NAME = 10001
GROUP_OPTIONS = 20000
BTN_OK = 20001
BTN_CANCEL = 20002

class OptionsDialog(gui.GeDialog) :
  def CreateLayout(self) :
    self.SetTitle('Title')
    self.AddStaticText(LBL_INFO, c4d.BFH_LEFT, name='String Name:') 
    self.AddEditText(NAME, c4d.BFH_SCALEFIT)
    self.SetString(NAME, 'Default Name') 
    # Buttons
    self.GroupBegin(GROUP_OPTIONS, c4d.BFH_CENTER, 2, 1)
    self.AddButton(BTN_OK, c4d.BFH_SCALE, name='OK')
    self.AddButton(BTN_CANCEL, c4d.BFH_SCALE, name='Cancel')
    self.GroupEnd()
    self.ok = False
    return True
 
  # Action Buttons Inputs
  def Command(self, id, msg) :
    bc = c4d.BaseContainer()
    
    if c4d.gui.GetInputState(c4d.BFM_INPUT_KEYBOARD,c4d.KEY_ENTER,bc) :
        if bc[c4d.BFM_INPUT_VALUE]==1:
           if id==BTN_CANCEL:
              self.Close()
    elif id==BTN_OK:
      self.ok = True
      self.option_find_string = self.GetString(NAME)
      self.Close()
    return True

def dialog_test() :
    dlg = OptionsDialog()
    dlg.Open(c4d.DLG_TYPE_MODAL, defaultw=300, defaulth=50)
    if not dlg.ok:
      return
    print "1"+dlg.option_find_string

if __name__=='__main__':
    dialog_test()

---------------------------------------

Thanks for the help, cheers!

On 25/05/2017 at 03:13, xxxxxxxx wrote:

Hi,

If you want only Ok and Cancel buttons plus associated Enter/Escape keys detection, GetInputState() is not needed as there are already default input commands for these.

A dialog sends Enter/Escape keys events to GeDialog.Command() with the IDC_OK (value 1) and IDC_CANCEL (value 2) IDs.
Also Ok/Cancel buttons can be added with GeDialog.AddDlgGroup() passing c4d.DLG_OK|c4d.DLG_CANCEL.
Then the same IDs are sent for the keys and buttons events to GeDialog.Command().

Here's how to use IDC_OK/IDC_CANCEL IDs and GeDialog.AddDlgGroup() in your OptionsDialog :

class OptionsDialog(gui.GeDialog) :
  
    IDC_LABELNAME = 1000
    IDC_EDITNAME = 1001
  
    def CreateLayout(self) :
  
        self.SetTitle('Enter Name')
  
        self.AddStaticText(self.IDC_LABELNAME, c4d.BFH_LEFT, name='String Name:') 
        self.AddEditText(self.IDC_EDITNAME, c4d.BFH_SCALEFIT)
        self.SetString(self.IDC_EDITNAME, 'Default Name')
  
        # Ok/Cancel buttons
  
        self.AddDlgGroup(c4d.DLG_OK|c4d.DLG_CANCEL)
  
        self.ok = False
  
        return True
  
    def Command(self, id, msg) :
  
        if id == c4d.IDC_OK:
            self.ok = True
            self.findName = self.GetString(self.IDC_EDITNAME)
            self.Close()
        elif id == c4d.IDC_CANCEL:
            self.Close()
  
        return True

On 25/05/2017 at 23:02, xxxxxxxx wrote:

Thanks Yannick! This is great and useful. 🙂

And how can I center my dialog on my screen? I've tried to set xpos and ypos with a c4d.BFH_CENTER and c4d.BFV_CENTER flags but returns in 0. This flags are only for dialogs buttons and XYpos can it only be int?.

Thanks!

On 26/05/2017 at 03:21, xxxxxxxx wrote:

Originally posted by xxxxxxxx

And how can I center my dialog on my screen? I've tried to set xpos and ypos with a c4d.BFH_CENTER and c4d.BFV_CENTER flags but returns in 0. This flags are only for dialogs buttons and XYpos can it only be int?.

BFH_CENTER and BFV_CENTER are also integer and their value is zero. These flags are only valid for layout flags of dialog gadgets. xpos and ypos need coordinates.

To center a dialog on the screen, you have to calculate the center position. The following function uses GeGetScreenDimensions() and returns the screen center:

def GetScreenCenter() :
    # Get mouse input state
    state = c4d.BaseContainer()
    ret = gui.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSELEFT, state)
    if not ret:
        return (0, 0)
  
    # Retrieve mouse X and Y coordinates
    x = state[c4d.BFM_INPUT_X]
    y = state[c4d.BFM_INPUT_Y]
  
    # Get whole screen dimensions
    xmin, ymin, xmax, ymax = gui.GeGetScreenDimensions(x, y, True).values()
  
    # Calculate screen center
    xcenter = xmin + (xmax - xmin) / 2
    ycenter = ymin + (ymax - ymin) / 2
  
    return (xcenter, ycenter)

Then just subtracts half the size of the dialog width and height to open the dialog at the very center of the screen.