LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Understanding Callbacks

Solved!
Go to solution

I've been programming with CVI since the BASIC days in the '90's, transitioned to the C-based code but have always programmed top-down and never used callbacks much. I want to change that. So here I am with my first serious attempt and something just isn't making sense.

 

I have a child Panel (SetupPanel as a handle) with a hot Numeric control. I want the user to be able to type in a number and hit enter to grab the value and return back to the main loop. I know callback events are being generated with the number entry, so I have an if statement to get the control's value when it sees a VAL_ENTER_VKEY event. The code executes fine, but the new value the user entered into the numeric control is not being grabbed and stored into referenced variable after the GetCtrlAttribute function sucessfully executes (returns a 0 indicating success).

 

The same GetCtrlAttribute function with the same variables works fine elsewhere in the code when called, it's only in the callback chunk where it doesn't grab the current numeric control's value. There's got to be something fundamental I'm not understand about using callbacks.

 

int     MaxDSCallback(int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
    if (eventData1 == VAL_ENTER_VKEY) {
        ret = GetCtrlAttribute (SetupPanel, Setup_AxisMax, ATTR_CTRL_VAL, &ddum);
    }    
    return(0);
}    // MaxDSCallback

 

After execution, ret = 0, but the value of ddum is what it was before the user changed the control, not the newly entered value. Tried a ProcessSystemEvents() after the GetCtrlAttribute, no joy.

 

Can someone explain to me what's going on here?

 

0 Kudos
Message 1 of 13
(4,692 Views)

Hello... I'd like to assist but I did not understand your statement

"I know callback events are being generated with the number entry, so I have an if statement to get the control's value when it sees a VAL_ENTER_VKEY event."

Why don't you simply check for a COMMIT or VAL_CHANGED event? Your user enters a number and then hits the return key, right? So why not use

    if ( event == EVENT_VAL_CHANGED ) ...?

0 Kudos
Message 2 of 13
(4,679 Views)

Thanks for the reply.

Each time a number character is entered into the control, an event (but not commit event) is processed. For instance, entering "2" "4" "0" "0" for the value 2400 causes four callback events in which the value changed each time. I only want the value after the user is finished entering the value and selects the Enter key.

0 Kudos
Message 3 of 13
(4,678 Views)
Solution
Accepted by topic author scottrod

Now I am even more confused... Did you try the following:

 

int MaxDSCallback ( int panel, int control, int event, void *callbackData, int eventData1, int eventData2 )
{
    if ( event == EVENT_VAL_CHANGED ) {
        ret = GetCtrlAttribute ( SetupPanel, Setup_AxisMax, ATTR_CTRL_VAL, &ddum );
    }    
    return(0);
}   

This should return only after you hit the enter key, not after every keystroke...

Message 4 of 13
(4,664 Views)

That works, thank you!

 

Still not understanding how the earlier code is not allowing the GetCtrlAttribute() function to pull in the data, but actually getting it working is what matters at the moment. Will investigate more later.

 

I see I have a bit to learn working with callbacks. Thanks again!

 

Scott

0 Kudos
Message 5 of 13
(4,660 Views)

I am glad to hear that Smiley Happy

For the explanation: your callback routine is called many times, when your control receives focus, for a key press, when the mouse is moved, after user input,...for a list see here

So what one usually needs is just one single event, hence you check for event == ... otherwise your code will be executed many times as you have observed.

0 Kudos
Message 6 of 13
(4,652 Views)

Also, one major problem with the first code snippet that you pasted is that you were checking the wrong parameter for the event:

 

    if (eventData1 == VAL_ENTER_VKEY) {
        ret = GetCtrlAttribute (SetupPanel, Setup_AxisMax, ATTR_CTRL_VAL, &ddum);
    }    

 

The correct parameter to check is "event", not "eventData1".

 

I don't know what you found when you were debugging this, but that certainly would have caused you problems, since eventData1 will almost never happen to be equal to that value (it might for some particular events, but that would be a very unpredictable coincidence, if it did happen at all).

 

Luis

0 Kudos
Message 7 of 13
(4,551 Views)

I've since noticed that you said that the value was the previous value of the control, not the newest value. So that tells me that the problem I mentioned earlier was not really a problem for you -- your real code must have been different than you pasted, so you can ignore my previous message.

 

In any case, what you're describing is the expected behavior: at the time that you receive a KEYPRESS event in your callback, the control hasn't yet changed its internal value. This is what allows you to return 1 from the KEYPRESS event's callback function in order to prevent the control from even seeing that key.

 

To get the new control value, Wolfgang's suggestion was the correct one: you needed to receive the COMMIT or VAL_CHANGED events instead.

0 Kudos
Message 8 of 13
(4,548 Views)

how callback is working....is it using filemapping??

0 Kudos
Message 9 of 13
(4,273 Views)

Hi sudhirvasudevacahrya,

 

Is something not working for you? And could you expand on your question a bit more?

 

Andy F.
Applications Engineering
National Instruments
0 Kudos
Message 10 of 13
(4,262 Views)