LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

SetCtrlAttribute after timer / delay / SyncWait

Hi,
I need to show a graph control for a certain period of time, that has to be as exact as possible and with the fastest possible image formation time, i.e least flickering. I assumed that the best would be to plot the graph and then make it visble with SetCtrlAttribute ATTR_VISIBLE TRUE/FALSE
It did work when I made the Graph visible and after resumed the timer callback function where I made VISIBLE FALSE again after counting my desired time. I now need more then one visible / hidden cycle within one callback function and therefore cannot work with ResumeTimerCallbacks () as they seem to start only after execution of the whole function. I tried SyncWait (mark, 0.3); and also Delay(); but both do not work, i.e. the graph control  disapears but does not show again when visible = TRUE
Any help / standard solution for those sort of problems. Time for the control to be shown is rather short (200-600ms)

idea is :
plot graph
show graph
wait for 400ms
hide graph

thanks tons

Message Edited by DocEye on 02-19-2007 03:26 AM

0 Kudos
Message 1 of 8
(4,984 Views)

Some draw functions are not executed if called inside one callback until you exit the callback. This is not the case of SetCtrlVal which forces a redraw each time is called, but for example SetCtrlAttribute normally is not executed unless you explicitly force the entire UIR to be redrawn with ProcessDrawEvents () function: you try inserting this call immediately after hiding / displaying the graph.

Just for completness, to force all system events to be processed you can use ProcessSystemEvents () function. This one should not be necessary in your callback and could introduce some unexpected problem since all pending events are processed in this moment, so it must be used with caution. The reason for this function to exist is for example to permit sensing a button press when your function is tied in a loop which is long lasting; keep in mind, though, that the callback paradigm should be to have callback functions as short as possible exactly to permit normal processing of system events. Long-lasting functions should be designed other way (e.g. with timed state machines or separate threads).



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?
Message 2 of 8
(4,977 Views)

Sorry this thread is so old.  It's the very closest to my symptoms I could find on this forum.  And Roberto's help is nearly getting me there.

 

Here's what I have in my application.  I have a long-running data capture function.  It looks something like this:

 

for (i=0; i<=nseg; i++)
{
	j = address + i;
	DoStuff(j);
	
	// build a status string 
	sprintf(indexDesc, 
		"wrote '%i' to address 0x%X (0d%d)", 
		cal[i],
		j,
		j);
	
	// update status
	index = i;
	fresh = TRUE;
}

This function take s a while.  My global variables index and fresh are a "poor man's" attempt at passing live looping updates to the caller of this function.

 

I do this by first creating an async timer that can then report the status.  It looks like this:

 

int CVICALLBACK StatusTimer (int reserved, int timerId, int event, void *callbackData, int eventData1, int eventData2)
{
	switch (event)
	{
		case EVENT_TIMER_TICK:
	
			//------------------
			// section info
			//------------------
			
			// only display new section info once
			if (lastSection != section)
			{
				// print step in messages
				sprintf(stemp, "%step %i", section + 1);
				SetCtrlVal(progressPanel,STATUS_TEXT,stemp);
				
				// update progress bar for some sections
				switch (section)
				{
						case 1:
						case 3:
							SetCtrlAttribute(progressPanel,PROGRESS_BAR,ATTR_VISIBLE,TRUE);
							SetCtrlAttribute(progressPanel,PROGRESS_BAR,ATTR_MARKER_STYLE,VAL_FULL_MARKERS);
							SetCtrlAttribute(progressPanel,PROGRESS_BAR,ATTR_TICK_STYLE,VAL_FULL_TICKS);
							SetCtrlAttribute(progressPanel,PROGRESS_BAR,ATTR_MAX_VALUE,maxIndex);
				
							// help GUI
							ProcessDrawEvents();
							break;

						default:
							SetCtrlAttribute(progressPanel,PROGRESS_BAR,ATTR_VISIBLE,FALSE);
				
							// help GUI
							ProcessDrawEvents();
							break;
				}
				
				// make these changes now
				ProcessSystemEvents();
				
				// update section state
				lastSection = section;
				
				// help GUI
				ProcessDrawEvents();
			}
			
			//------------------
			// loop index info
			//------------------
			
			// only display fresh data
			if (fresh)
			{
				// update progress bar for some sections
				switch (section)
				{
					case 1:
					case 3:
						SetCtrlVal(progressPanel,PROGRESS_BAR,index);
						
						// echo step detail in messages
						sprintf(stemp, "%s", indexDesc);
						SetCtrlVal(progressPanel,STATUS_TEXT,stemp);
						break;
						
					default:
						break;
				}
				
				// make these changes now
				ProcessSystemEvents();
				
				// clear flag
				fresh = FALSE;
				
				// help GUI
				ProcessDrawEvents();
			}
			break;
	}
	return 0;
}

But what I'm seeing is that the SetCtrlVal calls update immediately (like Roberto said), whereas the SetCtrlAttribute calls do not, until the complete loop call finishes.

 

Even after adding the ProcessDrawEvents, or even ProcessSystemEvents, I don't see them.  Is there some other way of forcing a redraw of the UIR?

 

0 Kudos
Message 3 of 8
(3,995 Views)

At a first glance to the code you published, I noticed that each call to SetCtrlVal addresses STATUS_something controls, while the calls to SetCtrlAttribute address PROGRESS_BAR control: they cannot be in the same panel! Smiley Wink

It may be a typo in pasting the code, but double check this just to be sure...



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 4 of 8
(3,991 Views)

Ah, indeed.  You are right, these were problems in my copy/paste.  I didn't want to paste as-is from my actual source, due to IP concerns here.  In the actual code, the two controls are indeed on the same panel.

 

After some time, and reviewing your comment here: http://forums.ni.com/t5/LabWindows-CVI/SetCtrlAttribute-only-works-during-debug/m-p/54474#M4842

 

... I found my problem.  It really just amounted to more careful placement of the ProcessDrawEvents calls.  I didn't have to use any ProcessSystemEvents.

 

Thanks.

0 Kudos
Message 5 of 8
(3,982 Views)

Ok, I was suspecting this wasn't the reason but I pointed you to it just in case. I sometimes fall into this kind of error when dealing with complex projects.

 

I'm happy you solved your problem. Smiley Happy



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 6 of 8
(3,975 Views)

I wonder whether this framework could be simplified someway getting rid of the timer and the global flags: if you are using the timer only to update the user interface you could PostDeferredCall a function from inside the loop to update the UI when a cycle is terminated. If a ProcessSystemEvents already exists in your loop, the main thread will execute the deferred function and update the UI only when needed.

 

This could interfere with other parts of your application so forgive it if you don't want/cannot use it.



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 7 of 8
(3,973 Views)

Yeah, I was using PostDeferredCall for a while, but ultimately sought a different way, mostly because the above is going into a DLL.  So it needs to be as portable as possible.  I need the caller to build their own indication mechanism of the loop status.

 

For now, what I have is sufficient I think.  Thanks for your help!

0 Kudos
Message 8 of 8
(3,954 Views)