This does not solve your initial issue since it requires the use of GetItemDim and it was introduced in R18 but here is how to avoid your second issue:
import c4d
class Dialog(c4d.gui.GeDialog):
def CreateLayout(self):
bc = c4d.BaseContainer()
bc.SetBool(c4d.BITMAPBUTTON_BUTTON, True)
bc.SetInt32(c4d.BITMAPBUTTON_ICONID1, c4d.Ocube)
bc.SetInt32(c4d.BITMAPBUTTON_FORCE_SIZE, 32)
button = self.AddCustomGui(10003, c4d.CUSTOMGUI_BITMAPBUTTON, "but", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 40, 40, bc)
button.SetCommandDragId(c4d.Ocube)
self.AddStaticText(10001, 0, 0, name="test")
return True
def IsPositionOnGadget(self, gadgetId, x, y):
# Be sure that the windows is opened,
# in our case since we call it in BFM_INTERACTSTART it's ok
buttonData = self.GetItemDim(gadgetId)
if not buttonData["x"] < x < buttonData["x"] + buttonData["w"]:
return False
if not buttonData["y"] < y < buttonData["y"] + buttonData["h"]:
return False
return True
def Message(self, msg, result):
# Main thread
if msg.GetId() == c4d.BFM_INTERACTSTART:
c4d.StopAllThreads()
# Check the mouse is clicked
state = c4d.BaseContainer()
self.GetInputState(c4d.BFM_INPUT_MOUSE, c4d.BFM_INPUT_MOUSERIGHT, state)
if state.GetInt32(c4d.BFM_INPUT_CHANNEL) != 0:
# Get coordinates
x = state.GetInt32(c4d.BFM_INPUT_X)
y = state.GetInt32(c4d.BFM_INPUT_Y)
g2l = self.Global2Local()
x += g2l['x']
y += g2l['y']
# Checks the coordinate is within the range of the BitmapButton
if self.IsPositionOnGadget(10003, x, y):
print 'Icon clicked in the GeDialog.'
# Stop others event to be processed
self.KillEvents()
return True
return c4d.gui.GeDialog.Message(self, msg, result)
# Main function
def main():
global dlg
dlg = Dialog()
dlg.Open(c4d.DLG_TYPE_ASYNC)
# Execute main()
if __name__=='__main__':
main()
Note that there is a very similar problem Disable default Right-Click Menu that you may found interesting about how to handle popup in your dialog.
And adding this constraint in mind, I'm afraid I don't see any solution to make it work before R18.
Cheers,
Maxime.