Drag and Drop action inside dialog

On 20/01/2013 at 22:30, xxxxxxxx wrote:

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

---------
Hi Folks,
 
I've got myself a custom dialog with two groups side by side in it. The first one has a html browser in it. The second group has a GeUserArea I'm working on. I'm using the browser to search for images on my hard drive. All is working fine up to this point.
 
What I wish to do now is have the userarea update while the mouse button is still held down during a drag operation. I can get messages to work once I let go of the mouse button etc, but I can't get things to happen in the user area while the drag is still in process. It's important that it happens here. How does one go about doing this?
 
I've done a fair bit of experiment with this - DRAG_flags and FOCUS_ change flags in the DLG and UA Message() etc - but I just can't seem to get the user area to update while the drag is still in process. Is anyone able to explain the process of what might need to happen here in order for this to work?
 
Regards,
 
WP.

On 21/01/2013 at 06:53, xxxxxxxx wrote:

This is way too much code and is not relevant to a drag-and-drop operation, but it may provide some way to check the mouse location while dragging in the GeUserArea (as long as these event messages are not being overridden or ignored during the drag-and-drop process!).  The areas of importance are 'while (GetInputState(...)).  Hope it helps!

/ GeUserArea.InputEvent()  
//*---------------------------------------------------------------------------*  
Bool iSUserArea::InputEvent(const BaseContainer &msg)  
//*---------------------------------------------------------------------------*  
{  
  // Mouse Events  
  if (msg.GetLong(BFM_INPUT_DEVICE) == BFM_INPUT_MOUSE) return HandleMouseEvents(msg);  
  return FALSE;  
}  
// iSUserArea.HandleMouse  
//*---------------------------------------------------------------------------*  
Bool iSUserArea::HandleMouseEvents(const BaseContainer& msg)  
//*---------------------------------------------------------------------------*  
{  
  // Get Mouse Click location and other information  
  LONG    chn =                        msg.GetLong(BFM_INPUT_CHANNEL);  
  // Left Button  
  if (chn == BFM_INPUT_MOUSELEFT)        return HandleMouse_LeftButton(msg);  
  return TRUE;  
}  
//*---------------------------------------------------------------------------*  
Bool iSUserArea::HandleMouse_LeftButton(const BaseContainer& msg)  
//*---------------------------------------------------------------------------*  
{  
  // Get Mouse Click location and other information  
  LONG            mx =        msg.GetLong(BFM_INPUT_X);  
  LONG            my =        msg.GetLong(BFM_INPUT_Y);  
  Global2Local(&mx,&my);  
  LONG            pX, pY;  
  ShaderNode*        snode =        IsOverNode(&pX, &pY, mx, my);  
  // Do Something with ShaderNode  
  if (snode)                    return HandleMouse_LBNode(snode, msg, pX, pY, mx, my);  
  // Over Background Area  
  // - Click - Remove all current selections  
  // - Drag - Create/Add to/Remove from Selection  
  return HandleMouse_LBBackground(msg, mx, my);  
}  
//*---------------------------------------------------------------------------*  
Bool iSUserArea::HandleMouse_LBNode(ShaderNode* snode, const BaseContainer& msg, LONG pX, LONG pY, LONG mx, LONG my)  
//*---------------------------------------------------------------------------*  
{  
  // Get Mouse Click location and other information  
  Bool            dblclk =    msg.GetBool(BFM_INPUT_DOUBLECLICK);  
  LONG            qua =        msg.GetLong(BFM_INPUT_QUALIFIER);  
  
  // Setup for dragging  
  BaseContainer    action(BFM_ACTION);  
  BaseContainer    state;  
  action.SetLong(BFM_ACTION_ID,GetId());  
  action.SetLong(BFM_ACTION_VALUE,0L);  
  
  // General variables  
  LONG            i, scount;  
  ShaderNode*        dnode =        NULL;  
  NodeInput*        dinput =    NULL;  
  
  LONG        width =            GetWidth();  
  LONG        height =        GetHeight();  
  LONG        hw =            width>>1;  
  LONG        hh =            height>>1;  
  // Is mouse over ShaderNode Header?  
  if (my < (pY+cellHeight))  
  {  
      // Is mouse over Show/Hide Button  
      if (mx > (pX+previewOffset))  
      {  
          snode->InvertShowPreview();  
      }  
      // Is mouse over Expand/Collapse Button  
      else if ((mx > (pX+expandOffset)) && (mx < (pX+expandOffset+jackplugSize)))  
      {  
          snode->InvertExpanded();  
      }  
      // Is mouse over Output  
      else if (mx < (pX+2L+jackplugSize))  
      {  
          // Get starting values  
          if (snode->IsInstanceOf(SHADERNODETYPE_CHANNEL)) return TRUE;                  
          startX = mx;  
          startY = my;  
  
          // Connecting  
          validConnection = FALSE;  
          drawMode = ISUA_DRAWMODE_CONNECTING;  
          snode->SetConnecting(TRUE);  
          while (GetInputState(BFM_INPUT_MOUSE,BFM_INPUT_MOUSELEFT,state))  
          {  
              if (state.GetLong(BFM_INPUT_VALUE) == 0L) break;  
  
              endX = state.GetLong(BFM_INPUT_X);  
              endY = state.GetLong(BFM_INPUT_Y);  
              Global2Local(&endX,&endY);  
              mx = endX/2L;  
              my = endY/2L;  
  
              // Check for UserArea boundary, scroll if necessary  
              if (endX <= 0L)  
              {  
                  windowX += mx;  
                  startX -= mx;  
              }  
              else if (endX >= width)  
              {  
                  windowX += (mx-hw);  
                  startX -= (mx-hw);  
              }  
              if (endY <= 0L)  
              {  
                  windowY += my;  
                  startY -= my;  
              }  
              else if (endY >= height)  
              {  
                  windowY += (my-hh);  
                  startY -= (my-hh);  
              }  
  
              // Check for Destination input  
              validConnection = FALSE;  
              for (dnode = ishader->GetLastSNode(); dnode; dnode = (ShaderNode* )dnode->GetPrev())  
              {  
                  if ((dnode == snode) || !dnode->GetExpanded()) continue;  
                  // Is it even near the node in question  
                  dnode->GetPos(&pX, &pY);  
                  pX -= windowX;  
                  pY -= windowY;  
                  if ((endX >= pX) && (endY >= pY) && (endX < (pX+cellWidth)) && (endY < (pY+snodeBoxHeight[dnode->GetType()])))  
                      if (validConnection = (dinput = IsOverNodeInput(dnode, pX, pY, endX, endY))?TRUE:FALSE) break;  
              }  
  
              Redraw();  
              action.SetLong(BFM_ACTION_INDRAG,TRUE);  
              SendParentMessage(action);  
          }  
          drawMode = ISUA_DRAWMODE_NORMAL;  
          snode->SetConnecting(FALSE);  
  
          if (dnode && validConnection)  
          {  
              // Check for circular connections  
              scount = snode->GetNodeCount();  
              for (i = 0L; i != scount; ++i)  
              {  
                  if (snode->GetNodeInput(i)->GetNode() == dnode) return ErrorException::Throw(GeLoadString(ISHERR_CIRCULARNODE));  
              }  
              // Break existing connection  
              if (dnode = dinput->GetNode()) dnode->DecConnect();  
              // Make the connection!  
              dinput->SetNode(snode);  
              snode->IncConnect();  
              ishader->UpdatePreview(FALSE);  
          }  
      }  
      // Edit Node data  
      else if (dblclk)  
      {  
          ishader->SetEditSNode(snode);  
          ishader->SelectAll(FALSE);  
          ishader->BringToFront(snode);  
      }  
      // Drag ShaderNodes  
      else  
      {  
          ishader->BringToFront(snode);  
          Redraw();  
  
          while (GetInputState(BFM_INPUT_MOUSE,BFM_INPUT_MOUSELEFT,state))  
          {  
              if (state.GetLong(BFM_INPUT_VALUE) == 0L) break;  
  
              SetMousePointer(MOUSE_MOVE_HAND);  
              pX = state.GetLong(BFM_INPUT_X);  
              pY = state.GetLong(BFM_INPUT_Y);  
              Global2Local(&pX,&pY);  
  
              mx = pX-mx;  
              my = pY-my;  
              for (snode = ishader->GetFirstSNode(); snode; snode = (ShaderNode* )snode->GetNext())  
              {  
                  if (!snode->GetSelected()) continue;  
                  snode->Move(mx, my);  
              }  
              mx = pX;  
              my = pY;  
              Redraw();  
              action.SetLong(BFM_ACTION_INDRAG,TRUE);  
              SendParentMessage(action);  
          }  
      }  
  }  
  // Edit Node data  
  else if (dblclk)        ishader->SetEditSNode(snode);  
  // Add to selection  
  else if (qua == QSHIFT) ishader->BringToFront(snode);  
  // Remove from selection  
  else if (qua == QCTRL)    ishader->SelectNode(snode, FALSE);  
  // Remove all curent selections, select this one  
  else  
  {  
      ishader->SelectAll(FALSE);  
      Redraw();  
      ishader->BringToFront(snode);  
  }  
  
  // Update and Notify  
  Redraw();  
  action.SetLong(BFM_ACTION_INDRAG,FALSE);  
  SendParentMessage(action);  
  return TRUE;  
}  
//*---------------------------------------------------------------------------*  
Bool iSUserArea::HandleMouse_LBBackground(const BaseContainer& msg, LONG mx, LONG my)  
//*---------------------------------------------------------------------------*  
{  
  // Do nothing on DoubleClick  
  if (msg.GetBool(BFM_INPUT_DOUBLECLICK))  
  {  
      ishader->SetEditSNode(NULL);  
      return TRUE;  
  }  
  
  // Check for Keyboard Qualifiers  
  Bool            selmode;  
  LONG            qua =        msg.GetLong(BFM_INPUT_QUALIFIER);  
  if (qua == QSHIFT)            selmode = TRUE;  
  else if (qua == QCTRL)        selmode = FALSE;  
  else  
  {  
      ishader->SelectAll(FALSE);  
      selmode = TRUE;  
  }  
  
  // Setup for dragging  
  BaseContainer    action(BFM_ACTION);  
  BaseContainer    state;  
  action.SetLong(BFM_ACTION_ID,GetId());  
  action.SetLong(BFM_ACTION_VALUE,0L);  
  
  // General variables  
  LONG            width =        GetWidth();  
  LONG            height =    GetHeight();  
  LONG            hw =        width>>1;  
  LONG            hh =        height>>1;  
  LONG            rectX1 =    mx;  
  LONG            rectY1 =    my;  
  LONG            rectX2, rectY2;  
  // Drag Selecting  
  startX = rectX1;  
  startY = rectY1;  
  drawMode = ISUA_DRAWMODE_SELECTING;  
  while (GetInputState(BFM_INPUT_MOUSE,BFM_INPUT_MOUSELEFT,state))  
  {  
      if (state.GetLong(BFM_INPUT_VALUE) == 0) break;  
  
      endX = state.GetLong(BFM_INPUT_X);  
      endY = state.GetLong(BFM_INPUT_Y);  
      Global2Local(&endX,&endY);  
      mx = endX/2L;  
      my = endY/2L;  
  
      // Check for UserArea boundary, scroll if necessary  
      if (endX <= 0L)  
      {  
          windowX += mx;  
          startX -= mx;  
      }  
      else if (endX >= width)  
      {  
          windowX += (mx-hw);  
          startX -= (mx-hw);  
      }  
      if (endY <= 0L)  
      {  
          windowY += my;  
          startY -= my;  
      }  
      else if (endY >= height)  
      {  
          windowY += (my-hh);  
          startY -= (my-hh);  
      }  
  
      Redraw();  
      action.SetLong(BFM_ACTION_INDRAG,TRUE);  
      SendParentMessage(action);  
  }  
  drawMode = ISUA_DRAWMODE_NORMAL;  
  rectX2 = endX;  
  rectY2 = endY;  
  
  // Swap so that 1 is always UL, 2 LR  
  if (rectX1 > rectX2)  
  {  
      mx = rectX1;  
      rectX1 = rectX2;  
      rectX2 = mx;  
  }  
  if (rectY1 > rectY2)  
  {  
      my = rectY1;  
      rectY1 = rectY2;  
      rectY2 = my;  
  }  
  
  // Find and Select/Deselect all ShaderNodes overlapped by Rectangle  
  LONG            pX, pY;  
  for (ShaderNode* snode = ishader->GetFirstSNode(); snode; snode = (ShaderNode* )snode->GetNext())  
  {  
      snode->GetPos(&pX, &pY);  
      pX -= windowX;  
      mx = pX+cellWidth;  
      pY -= windowY;  
      my = pY+GetSNodeHeight(snode->GetType(), snode->GetExpanded(), snode->GetShowPreview());  
  
      if ((my < rectY1) || (pY > rectY2) || (mx < rectX1) || (pX > rectX2)) continue;  
      ishader->SelectNode(snode, selmode);  
  }  
  
  // Update and Notify  
  Redraw();  
  action.SetLong(BFM_ACTION_INDRAG,FALSE);  
  SendParentMessage(action);  
  return TRUE;  
}

On 21/01/2013 at 14:35, xxxxxxxx wrote:

Hi Rob,
 
thankyou very much for your efforts there. I certianly wasn't expecting that. I"ll need to spend some time digesting this one =)
 
Much appreciated,
 
WP.

On 31/01/2013 at 21:07, xxxxxxxx wrote:

OK, I still can't seem to get this one right.
 
I'm dragging from an html browser in my dialog, and am wanting the UA to update while the drag is in progress (if the mouse is hovering over the UA - both items are in the same dialog). I seem to be able to get a few flags to call etc once I let go of the mouse button, but can't seem to get anything to respond while the drag is in progress.
 
Is their a core message or something of the like I might be missing?
 
WP.

On 14/02/2013 at 21:57, xxxxxxxx wrote:

Hi Coders,
 
just posting an update to this one. I seem to have solved this by chaning the HTML viewer to a userarea, and making my own browser (bit of a shame to have to do that but anyway). The following link may provide so further info for those seeking a solution.
https://plugincafe.maxon.net/topic/6844/7627_how-to-use-handlemousedrag
 
Kind regards,
 
WP.