Drag and Drop from GeUserArea

On 06/02/2017 at 03:48, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R18 
Platform:   Windows  ;   
Language(s) :     C++  ;


I have a GeUserArea in a Dialog , which shows some bitmaps (they are displayed via DrawBitmap).
I want to drag these bitmaps and drop them into the object Hierarchy.

Can I know on which hierarchy object the bitmap is dropped ?
Also, can I display a little bitmap next to mouse cursor ? (so the user knows, which item is dragged).

I implement the drag and drop mechanism in InputEvent as shown here:
(MouseDragStart/End e.t.c)

Another question, if the above is not applicable, can I have my own menu via right-click on a GeUserArea ?

Thank you very much for your time !

On 06/02/2017 at 23:49, xxxxxxxx wrote:

Hi Peter,

to initiate a drag and drop from a GeUserArea there's HandleMouseDrag(). That might be something to look at. Maybe test your mouse coords in MouseDragStart() and if they're outside the user area, start a HandleMouseDrag() routine.

The second and third questions might have to come from someone with more experience. The mouse cursor might be an OS level thing? You can change the mouse icon to a Cinema icon, but I'm not aware of being able to 'attach' a bitmap to it via Cinema itself.

In answer to your last question,  you can have a mouse context menu by using ShowPopupMenu(). So, something like the following (you'll need to adjust for R18) :

Bool MyUserArea::InputEvent(const BaseContainer &msg)
        BaseContainer bc;
        if(GetInputState(BFM_INPUT_MOUSE,BFM_INPUT_MOUSERIGHT,bc) && bc.GetLong(BFM_INPUT_VALUE) == 1)
            LONG id = Get_MyMenu();
            if(id != NULL)
                // do something based on return id..
        return TRUE;
int MyUserArea::Get_MyMenu()
        BaseContainer MyMenu;
        MyMenu.SetString(FIRST_POPUP_ID + 1,"First menu item");
        MyMenu.SetString(FIRST_POPUP_ID + 2,"Second menu item");
        LONG id = ShowPopupMenu(...);
        if(id != NULL)
            return (id - FIRST_POPUP_ID);
        return NULL;

You'll probably need to play around with testing the coords and whether the mouse is over your bitmap etc somewhere. But maybe that gets you started!


EDIT: updated text.

On 07/02/2017 at 01:49, xxxxxxxx wrote:

Hello and thank you very much for your answer.

Can I get mouse x and Y outside of GeUserArea's  InputEvent ?
I try using BFM_GETCURSORINFO and BFM_DRAG_SCREENX, BFM_DRAG_SCREENY in Message method but it seems they give me C4D's x,y.

Thank you.

On 07/02/2017 at 02:34, xxxxxxxx wrote:


Can I know on which hierarchy object the bitmap is dropped ?

You can't. The receiving side implements the behavior on drop. There's no way to get such information on the initiating side of a drag and drop.

Also, can I display a little bitmap next to mouse cursor ? (so the user knows, which item is dragged).

Unfortunately, no again. You can influence the type of cursor shown to a certain extent via SetDragDestination() (when over your GeUserArea) and HandleMouseDrag() by specifying the type of the drag (DRAGTYPE_xxx) so other places can react accordingly. In other situations you can also use (only from main thread!) GeShowMouse() to change the look of the mouse cursor, see cursor types. But you can not attach a bitmap to the cursor or something alike.

For future readers: The above mentioned GeUserArea manual describes and contains code snippets on all three versions of drag and drop operations:
- dragging something inside of the GeUserArea (e.g. a custom slider), related functions: MouseDragStart(), MouseDrag() and MouseDragEnd()
- receiving a drag and drop operation from other places in Cinema (including the same GeUserArea), related functions: CheckDropArea(), GetDragPosition(), GetDragObject() and SetDragDestination()
- starting a drag and drop of some kind of entity to other places in Cinema (including the same GeUserArea the drag got started from), related function: HandleMouseDrag()

And the last question regarding the popup menu got already answered by WickedP.

On 07/02/2017 at 02:36, xxxxxxxx wrote:

You sure can. You could set some class-level variables inside your Message() function, something like this:

// CursorX and CursorY could be class-level variables
LONG MyUserArea::Message(const BaseContainer &msg,BaseContainer &result)
    switch (msg.GetId())
            BaseContainer bc;
            CursorX = bc.GetLong(BFM_INPUT_X);
            CursorY = bc.GetLong(BFM_INPUT_Y);
            // setter here
    return GeUserArea::Message(msg,result);

In addition, where I've put "setter here" text, you could test the coords to see if they're over a bitmap, and if they are, you could set an index variable, like a bitmap 'index' id, so in your Draw() function if the bitmap you're drawing is the same number as the index, you could highlight it as a "mouse over" feature (if that makes sense!). Just a thought!