LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Cursors moving with Graph panning?

Hi,

I´m using LabWindows 7.01 and got a little question.

When i pan or zoom in an Graph my cursors don´t move with the graph panning.
So it is not possible to zoom in a graph, set the cursor with high accuracy an zoom back again to set the next cursor, because the first cursor doesn´t stay at his position while zooming out or panning to the other cursor.

Also i can´t figure out how to get an event_handle that tells me that the panning is finished (left or right mousebutton released) to set the cursors manually.

Hope you can help me with my question and sorry for my broken/basic english.

Manuel

Message 1 of 5
(3,650 Views)
Manuel,

By default, cursors are in "free form" state, which means that they are not tied to a precise position in graph units. In order to lock them to a particular coordinate, you will have to put them in "snap to point" mode. But this means that you will have to have a plot at the point where you want the cursor to snap to. Once it is attached to a point, you can zoom the graph and the cursor should remain at that location.

Now, if I understand your question correctly, you want to allow users to place a cursor in a particular coordinate location and then have the cursor remain there, even while the graph range changes. I can think of a possible way of doing this, but I haven't tried it myself and there might be some caveats I haven't thought of. But it's worth a shot:

When you detect that the user has started to move a cursor (you receive an EVENT_VAL_CHANGED at that time) you should set the cursor to "free form" mode. This will allow the cursor to remain wherever the user releases it (rather than snap to the nearest plot). When you detect that the user releases the cursor (you get an EVENT_COMMIT at that time) you need to obtain the cursor's position, and plot a point (PlotPoint function) at that position. You should make the plot color transparent, so that the plot isn't visible). You should then set the cursor back to "snap to point" mode after you plot. This will attach the cursor to the nearest plot point, which should be the plot that you just plotted. But because their positions are the same, the cursor shouldn't move at all. Now, whenever you zoom the graph, the cursor should remain attached to that point, thereby preserving its coordinate position. You should also remove the previous plot that was "holding" the cursor prior to this move operation.

That's basically it. I hope you get the general idea, in any case. This should work okay, at least as long as the zooming doesn't drag the cursor outside the graph range. You'll have to decide what you want to do in that case.

Finally, you asked how you can tell when the zooming or panning finishes. Currently, there are no specific events for that (these are being introduced with CVI 8.1), but you can improvise, by detecting when the mouse up takes place (look at the extended mouse events functions in the Programmer's Toolbox).

Hope this helps.

Luis
Message 2 of 5
(3,640 Views)
Hi LuisG.

Now, if I understand your question correctly, you want to allow users to place a cursor in a particular coordinate location and then have the cursor remain there, even while the graph range changes.
that hab been what i  tried to explain.

Your  method sounds just nice but it doesn´t work. The cursors don´t stay at the  right point. When I pan, the Cursor goes with the panning and then locks to the now nearest plotpoint.  Smiley Sad

But thank you very much for that hint with the extended mouse functions. I found a getGlobalMouseState() function that could really help me in a few problems at my programm.
So I tried to program my own zoom and pan function... that I can store the cursor position befor the zomming and then set them back to the original position after zooming.
It also should be not so difficult to catch the exception, that the cursors get out of the graph-range.

but I got some problems with the getGlobalMouseState() function, it seems that the function ist not working correctly (or more likely I´m making an few misstakes), so here is my code:

int CVICALLBACK graph_timeDomain (int panel, int control, int event,
        void *callbackData, int eventData1, int eventData2)
{

    int mod, left, right;
    double min, max;
   
    switch (event)
        {
       
        case EVENT_LEFT_CLICK:
        case EVENT_RIGHT_CLICK:
            do
            {
                GetGlobalMouseState (NULL, NULL, NULL, &left, &right, &mod);
                if (mod & VAL_SHIFT_MODIFIER)
                {
                    GetAxisScalingMode (panel, control, VAL_BOTTOM_XAXIS, VAL_MANUAL, &min, &max);
                    if (right & !left)
                    {
                        min *= 1.05;    //zoom by 5%
                        max /= 1.05;
                    }

                    if (left & !right)
                    {
                        min /= 1.05;
                        max *= 1.05;
                    }
                    SetAxisScalingMode (panel, control, VAL_BOTTOM_XAXIS, VAL_MANUAL, &min, &max);
                   
                    if (left & right)
                    {
                        //maybee autoscaling...
                    }
               
                }
            }
            while (left | right);
           
            break;
       }
    return 0;
}


I set a debug point  to the
GetGlobalMouseState function put left or right never become true.
The event_left_klick is generated but the GetGlobalMouseState function returns me 0 for left.

Where is my mistake?

Message Edited by Manuel H on 11-17-2006 03:01 AM

0 Kudos
Message 3 of 5
(3,634 Views)
Hello Manuel

Well, I guess this will teach me to recommend some solution without trying it myself first... sorry about that. I had forgotten the behavior of snapped cursors during a zoom.

I tested your code, and although I wasn't able to reproduce the symptom you describe (GetGlobalMouseState always returned 1 for left or right), I can see how it's possible for it to happen. I think it's a matter of timing. By the time your callback is called, it's possible that the user has already released the mouse button, in which case the function will return 0. Did you experiment with long clicks, so that button is definitely still down at the time you call the function?

In any case, it is probably not a good idea to rely on length of clicks in the code, so I'd suggest doing something different, and simpler:

The extended mouse events in the toolbox allow you to receive an event when the user releases the mouse. The function call looks like this:

    EnableExtendedMouseEvents (panelHandle, PANEL_GRAPH, 0.1);

After calling the function, you will receive mouse-up events in the graph's callback. Thus, you can rearrange your code so that you don't have to code the mouse loop yourself. Simply enable a timer when the mouse-down happens, and disable it when the mouse up happens. For example:

        case EVENT_LEFT_CLICK:
            SetCtrlAttribute (panel, PANEL_TIMER, ATTR_ENABLED, 1);
            break;
        case EVENT_LEFT_MOUSE_UP:
            SetCtrlAttribute (panel, PANEL_TIMER, ATTR_ENABLED, 0);
            break;

The scaling then takes place in the timer callback:

        case EVENT_TIMER_TICK:
            GetAxisScalingMode (panel, PANEL_GRAPH, VAL_BOTTOM_XAXIS, VAL_MANUAL, &min, &max);
            oldRange = max - min;
            newRange = oldrange / 1.1;
            offset = (oldRange - newRange) / 2.0;
            min += offset;
            max -= offset;
            SetAxisScalingMode (panel, PANEL_GRAPH, VAL_BOTTOM_XAXIS, VAL_MANUAL, min, max);
            break;

Notice that the scaling is a bit more complicated than what you had previously. You can't simply apply a scaling factor to min and max, since these may be negative, or zero. You need to scale the range up or down, not the individual end-points. In the code above, the range is being reduced by 10% in each iteration. This is accomplished by adding half of the difference to the min, and subtracting the other half from the max.
You can control the speed of the zoom by setting the timer interval accordingly. Also, remember to start out with the timer disabled.
If you want to use right-clicks for zooming out, you can still use this solution. You would have to set some flag that will tell the timer callback to zoom out instead.

Luis

Message 4 of 5
(3,600 Views)
Hi Luis,

thank you for testing my code... i also tryed long mouse clicks, but it didn´t work.

However your new method of resolution sounds really nice and I´ll give it a try.
Right now I´m bit busy with 2 other projects, so it could take some time, until i can try it.

so far, thanks for your work. 🙂
Of course I´ll tell you if the solution is working fine.

Manuel
0 Kudos
Message 5 of 5
(3,577 Views)