UserArea DrawLine Problem



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 26/06/2005 at 17:32, xxxxxxxx wrote:

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

    ---------
    I have a userarea in a modal dialog displaying a picture.
    I am trying to use DrawLine on top of the picture in the userarea's Draw() routine.
    It is working fine except for when the dialog is in the upper left quadrant of the screen. Then the bitmap displays fine, but no lines are drawn. I've also tried several other drawing functions with no success.
    Any ideas?

    -Chris



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 26/06/2005 at 22:13, xxxxxxxx wrote:

    The first two commands that should be called in the UserArea::Draw() are:

      
         OffScreenOn();  
         SetClippingRegion(x1,y1,x2,y2);  
    

    Everything is then drawn to the buffer and clipped before being displayed.

    If you are using the mouse to get coordinates, you'll need to convert them using UserArea::Global2Local() in order to be relative to the UserArea and not the Screen.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/06/2005 at 03:45, xxxxxxxx wrote:

    Hi Robert, I just tried SetClippingRegion, but that didn't help.
    I am using the mouse coordinates, and I'm getting the correct local coordinates, but still, those lines wont draw with the dialog positioned near the upper left corner, even with correct local coordinates.
    As soon as I move the dialog toward the right side of the screen or toward the bottom, everything works fine.
    Maybe it has something to do with how I'm getting the mouse coordinates? I'm using BFM_DRAG_SCREENX and BFM_DRAG_SCREENY in the UserArea::Message. Is there another way I should be using to get the mouse position?

    -Chris



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/06/2005 at 05:29, xxxxxxxx wrote:

    Not the best way to get mouse coordinates in a UserArea. Here is a code snippet from one of my projects:

      
    // GeUserArea.InputEvent()  
    Bool iSUserArea::InputEvent(const BaseContainer &msg;)  
    {  
         LONG dev = msg.GetLong(BFM_INPUT_DEVICE);  
         // Keyboard Events  
         if (dev == BFM_INPUT_KEYBOARD) return FALSE; //SendParentMessage(msg);  
         // Mouse Events  
         else if (dev == BFM_INPUT_MOUSE) return HandleMouseEvents(msg);  
         return FALSE;  
    }  
    // iSUserArea.HandleMouse  
    Bool iSUserArea::HandleMouseEvents(const BaseContainer& msg)  
    {  
         // Get Mouse Click location and other information  
         Bool dblclk = msg.GetBool(BFM_INPUT_DOUBLECLICK);  
         LONG chn = msg.GetLong(BFM_INPUT_CHANNEL);  
         LONG qua = msg.GetLong(BFM_INPUT_QUALIFIER);  
         LONG mx = msg.GetLong(BFM_INPUT_X);  
         LONG my = msg.GetLong(BFM_INPUT_Y);  
         Global2Local(&mx;,&my;);  
      
         // Setup for dragging  
         BaseContainer action(BFM_ACTION), state;  
         action.SetLong(BFM_ACTION_ID,GetId());  
         action.SetLong(BFM_ACTION_VALUE,0);  
      
         // General variables  
         UCHAR i, scount;  
         LONG pX, pY;  
      
         LONG width = GetWidth();  
         LONG height = GetHeight();  
         LONG hw = width>>1;  
         LONG hh = height>>1;  
      
         // Left Button  
         if (chn == BFM_INPUT_MOUSELEFT)  
         {  
    ... // For dragging, something like this:  
              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/2;  
                   my = endY/2;  
      
                   // Check for UserArea boundary, scroll if necessary  
                   if (endX <= 0)  
                   {  
                        windowX += mx;  
                        startX -= mx;  
                   }  
                   else if (endX >= width)  
                   {  
                        windowX += (mx-hw);  
                        startX -= (mx-hw);  
                   }  
                   if (endY <= 0)  
                   {  
                        windowY += my;  
                        startY -= my;  
                   }  
                   else if (endY >= height)  
                   {  
                        windowY += (my-hh);  
                        startY -= (my-hh);  
                   }  
                   Redraw();  
                   action.SetLong(BFM_ACTION_INDRAG,TRUE);  
                   SendParentMessage(action);  
              }  
         }  
      
         // Update and Notify  
         Redraw();  
         action.SetLong(BFM_ACTION_INDRAG,FALSE);  
         SendParentMessage(action);  
         return TRUE;  
    }  
    

    Note: I store the variables needed in Draw() rather than draw directly in InputEvent().



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/06/2005 at 16:41, xxxxxxxx wrote:

    My InputEvent code is quite similar to yours (combined with HandleMouseEvents).
    That does not seem to work for detecting mouse movements though.
    What I'm trying to do is set up hyperlink type hotspots on the userarea, and underline them as the mouse moves over them.
    I've got it working great except when the dialog is at the upper left of the screen. =)
    I'm gonna keep playing with it and post any progress I make.

    Thanks Robert.

    -Chris



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/06/2005 at 18:06, xxxxxxxx wrote:

    Ok... got it working.
    I looped through the msg elements using GetIndexId and found that i was getting invalid coordinates (the size of the bitmap) when id's 0 and 1 were present. Now I check for ids 0 and 1, and skip the line drawing if they are there.
    Any idea what 0 and 1 are?
    Also, how would I go about getting the mouse pointer to change? SetMousePointer doesn't seem to be working.

    -Chris



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/06/2005 at 18:17, xxxxxxxx wrote:

    Ok... when only id's 2 and 3 are present, that's BFM_DRAG_SCREENX and BFM_DRAG_SCREENY. When I have id's 1, 2, 3, and 4 I think I'm getting BFM_DRAW_LEFT, BFM_DRAW_TOP, BFM_DRAW_RIGHT, and BFM_DRAW_BOTTOM. Which makes sense, because the values correspond to the draw size of the bitmap. I also noticed that it seems to work fine if the dialog is partially off screen (I dont get the BFM_DRAW messages).
    Now that we know all of this, why would the position of the dialog have anything to do with whether or not I receive the BFM_DRAW_x messages? And is there a better way to determine whether I'm getting the BFM_DRAG_x or BFM_DRAW_x message?

    -Chris



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 27/06/2005 at 21:27, xxxxxxxx wrote:

    1. What are you getting BaseContainer Indices for?

    2. I'm not sure that BFM_DRAG_SCREENX/Y are really the best. These are for 'Drag and Drop'.

    If you want to know what rectangular area you are over representing your URL links, you should store relative (local) coordinates (Top/Left/Bottom/Right) for each 'URL' object and check the mouse coordinates against them to see if the mouse is within the bounds. You don't need to check for mouse buttons - as you can see in my code snippet, the mouse coordinates are extracted even before any button clicks or holds are checked.

    I have never encountered a problem with any dialog UserArea mouse coordinates or drawing using the InputEvent/Draw method (which is the one officially supported and recommended for UserAreas).

    I've found that setting the mouse pointer in UserAreas is hit-or-miss. The only way to retain the mouse pointer setting when looping is to change within the loop (yes, constantly). There is no other way to change the mouse pointer except maybe through Windows procedure calls (I'm not sure if that is recommended as it may not be thread or process safe).

    As the code from which the snippet is extracted is 'proprietary', I could email you the entire iSUserArea class to see the entire scope of operations if you'd like.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/06/2005 at 03:56, xxxxxxxx wrote:

    1. I was looking a the BaseContainer msg in the Message handler.

    2. I have gotten rid of the BFM_DRAG_SCREENX/Y stuff. While they were working very well, it doesn't seem like a good practice to rely on them. I have switched to calling GetInputState during polling, which seems to work equally well. The problem I was having was that the InputEvent handler was not being executed during mouse move events.

    So two final questions as far as that goes:

    For handling of mouse moves, is it better to use GeInputState in the Message handler, or through the UserArea's Timer?

    Is there a way to make InputEvent handle mouse moves?

    -Chris



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/06/2005 at 12:22, xxxxxxxx wrote:

    For mouse moves, use InputEvent(). GetInputState() is used for event polling. So, if you need to continuously track the mouse while redrawing, then use GetInputState() in a loop (as shown above) and call Redraw() within to refresh any graphics affected by this process.

    InputEvent() handles mouse and keyboard input.

    Now, my question is how you set up your UserArea. For instance, I don't think they work well from a dialog resource. It is best to derive your own class from GeUserArea (like my iSUserArea class above). I would need to see the code that you use to make the UserArea and the derived class to see why you are not getting input events. To really take control of the GeUserArea methods, you need to derive a class in order to override the default methods.

    When the UserArea 'has focus' (when the cursor is in the UserArea), input events should arrive to the UserArea first. Any that are not handled there are sent to the dialog and then to Cinema 4D.

    In your Dialog's CreateLayout(), these two lines should exist to realize the UserArea. 'IS_ISUSERAREA' is an id assigned to this dialog gadget (just like any other). 'isUserArea' is an instance of the derived class.

    AddUserArea(IS_ISUSERAREA, BFH_SCALEFIT|BFV_SCALEFIT);
         AttachUserArea(isUserArea, IS_ISUSERAREA, 0);

    If your UserArea can be resized, then you must have this method to invoke redraws:

    // GeUserArea.Sized
    void iSUserArea::Sized(LONG w, LONG h)
    {
         Redraw();
    }

    A skeleton for the derived class:

    // CLASS: MyUserArea
    // -- for GeUserArea
    class MyUserArea : public GeUserArea
    {
         private:
              // - Events
              Bool HandleMouseEvents(const BaseContainer& msg);
         public:
              MyUserArea();
              ~MyUserArea();
              // - Functions to overload
              Bool Init(void);
              void Sized(LONG w, LONG h);
              void Draw(LONG x1, LONG y1, LONG x2, LONG y2);
              Bool InputEvent(const BaseContainer& msg);
    };

    Once the UserArea is attached to the dialog (and the dialog opened), InputEvent() automatically receives events relevant to the UserArea.



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/06/2005 at 14:30, xxxxxxxx wrote:

    Lets see... my UserArea is set up as a derived class and it is being created in the dialog with AddUserArea and AttachUserArea. So that wasn't my problem.

    My InputEvent handler was working just fine for detecting clicks (and getting the mouse position while clicking), but not plain old mouse moves.

    I am now using GetInputState in the UserArea's Timer for tracking the mouse position and everything is working perfectly. =)

    Thank you for all of your help Robert. It is much appreciated.

    -Chris



  • THE POST BELOW IS MORE THAN 5 YEARS OLD. RELATED SUPPORT INFORMATION MIGHT BE OUTDATED OR DEPRECATED

    On 28/06/2005 at 14:56, xxxxxxxx wrote:

    Sounds like you were going about this properly. Don't know why mouse movements were not getting sent to InputEvent(). If it works, it works. :)


Log in to reply