LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Disabling events

To NI,


I use CVI 6.0!

When I push a certain button on my panel a callback function is called.
In this function I use ClientTCPWrite to send a command ... then, I
call ClientTCPRead (with a timeout value of 2000 milliseconds).
However, I DO NOT want to new events caused by button clicks to
come through during this period ...

In Microsoft tools (VC++, VB) events DO NOT come through in a situation
like this ... unless you start multiple threads yourself or make explicit
system
calls like DoEvents in VB.

Is there any (easy) way you can disable (user) events to avoid this
situation?


Kind regards
Martin Trock
0 Kudos
Message 1 of 8
(4,595 Views)
The simplest way I can think is to disable temporarily the individual control that fires the TCP function, inserting SetInputMode (panel, control, 0); at the beginning and SetInputMode (panel, control, 1); at the end of the callback (eventually, in conjunction with SetWaitCursor to signal system busy to the operator). This way, while the callback is executing, it's not possible to fire it a second way.

If you want to block all control events, you could define a global variable and use it as a blocking flag. As an example, in the blocking callback set
BlockFlag = 1
In the individual control's callback, put
if (event != EVENT_COMMIT && BlockFlag) return 0;

Hope this helps
Roberto


Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 2 of 8
(4,595 Views)
Hi Martin,
the easiest solution is to disable the offending buttons. i.e. at the start of the callback that get's called from your button, simply
SetCtrlAttribute(panel,control,ATTR_DIMMED,1);
You can do this for all the buttons you don't want to queue the message of.
I'm not aware of a function to disable callbacks, unless it's the timer callback which can be suspended and resumed.
If you want to get a little more complicated, you can remove the callback pointer from the control through it's attribute
SetCtrlAttribute(panel,control,ATTR_CALLBACK_FUNCTION_POINTER,NULL);
and then re-instate it afterwards (as long as you know the name of the callback function!
The button presses shouldn't be handled until after the function has run. All panel/control events are s
ynchronous callbacks. Windows will still put information into it's message queue for events that have occured on your panel, but if there's not a callback assigned, nothing will be internally queued (to cvi).
The equivalent to DoEvents (VB) would be ProcessSystemEvents() in CVI. You need this because if you're in a lengthy callback, and you need to see what else has gone into the message queue, you can call this to process those items.
Swallowing the event (returning a 1 from a callback function instead of a 0) means that after the first call, the callback doesn't get called again - watch out if you try to swallow events on EVENT_COMMIT - a EVENT_LEFT_CLICK will have already occured and swallowed the event (depending on your program flow).

Hope that helps

S.
// it takes almost no time to rate an answer Smiley Wink
0 Kudos
Message 3 of 8
(4,595 Views)
Martin,

There is no way to completely disable all the events generated by a button in CVI. However, the easiest way to ensure that the TCP portion of the callback is not executed twice, just change the mode of the control to indicator so that it doesn't generate EVENT_COMMIT events. Inside your callback, make sure your TCP code is executed inside the EVENT_COMMIT case only as such:

int CVICALLBACK CommandClicked (...)
switch (event)
{
case EVENT_COMMIT:
SetCtrlAttribute (panel,PANEL_COMMANDBUTTON, ATTR_CTRL_MODE, VAL_INDICATOR);
// control will no longer generate EVENT_COMMIT events; this portion of code won't be executed twice.
// TCP calls
break;
}
return 0;
}

Later if you want your button to continue generating event com
mits, just call SetCtrlAttribute (panel, PANEL_COMMANDBUTTON, ATTR_CTRL_MODE, VAL_HOT).

Regards,
Azucena
NI
0 Kudos
Message 4 of 8
(4,595 Views)
Just a small correction: swallowing events doesn't exactly mean the "callback doesn't get called again". It only prevents future events from getting generated (such as LEFTCLICK and VALCHANGED). For example, suppose you have a command button. When you click on this button, at least two events will be generated and the callback will get called at least two times--once for EVENT_LEFT_CLICK and once for EVENT_COMMIT. If you "swallow" the event (by returning 1) when processing the EVENT_LEFT_CLICK event, the EVENT_COMMIT or any future events corresponding to that single mouse click will not be generated or processed. You can read more about what EVENTs are available and how to swallow events in the LabWindows/CVI Online Help, which you can access through Help»CV
I Libraries in LabWindows/CVI or through Start»(location of LabWindows/CVI)»CVI Manuals.

My $0.02

Azucena
0 Kudos
Message 5 of 8
(4,595 Views)
Hi Azucena,
You're right of course. I explained it badly - I was referring to the problem that if you have say a button on a front panel, and only code for the EVENT_COMMIT, but regardless of the event, your return a 1, (with the default layout for the callback), the event commit will never get called (tried it). If however, you put in an Event_Left_Click at the same time, the LEFT_CLICK section of code gets called (it went first), but the EVENT_COMMIT never gets to run.

Is that a better explanation?

Try attaching this to a UIR with a couple of buttons (one for quit of course) ....

int CVICALLBACK Swallowed (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_LEFT_
CLICK:
{
MessagePopup("LEFT_CLICK","");
}
break;
case EVENT_COMMIT:
{
MessagePopup("COMMIT","");
}
break;
}
return 1;
}

S.
// it takes almost no time to rate an answer Smiley Wink
0 Kudos
Message 6 of 8
(4,595 Views)
Thanks ...
However, I was aware of this technique. Now, I implement my code as a DLL
which is used by several applications. In this solution I leave the
resposibility
to every application which calls my DLL that the application doesn't call
my DLL reentrantly!
This is not really fair ... it is my responsibility to implement the DLL as
a safe
piece of code.

Also, suppose I have 10 buttons ending in the same function. I would
have to disable all 10 buttons ...
And I would have to do this in every application which calls my DLL!

This is not really a nice solution ...

Function calls like ClientTCPRead do have the side-effect that user events
are
processed ... it should be possible to disable this processing.

Kind regards
Martin
0 Kudos
Message 7 of 8
(4,595 Views)
Hi SachaE,

Yes you are right. In the Swallowed callback you posted, because the return 1 is outside the switch statement and the LEFT_CLICK event is generated before an EVENT_COMMIT, then the LEFT_CLICK event will execute, return 1, and prevent the subsequent EVENT_COMMIT from being executed. However if the user left-clicks on the button once more, the callback will be called again with the LEFT_CLICK event, repeating the process outlined above. I guess it's a matter or wording?

Cheers,
Azucena
0 Kudos
Message 8 of 8
(4,595 Views)