LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Is there a vSetCtrlAttribute? va_list and SetCtrlAttribute(panel,control,attribute,...)

  • Are there va_list versions of the UI functions like SetCtrlAttribute?  Like vsprintf vs. sprintf.
Or is there a va_args parser for them that someone has?
I want to disassociate the panel and control in a wrapper but dont want to code up pulling out the va_args for each attribute.
 
The function below doesnt seem to work.
int find_control(int panel,char *control_name);
int SetCtrlAttributeW(int panel,char *control_name,int size,int attribute,...)
{
va_list ap;
int i;
i = find_control(panel,control_name);
if(i) {
va_start(ap,attribute);
SetCtrlAttribute(panel,i,attribute,ap);
va_end(ap);
}

return(0);
}
 
int find_control(int panel,char *control_name)
{
char *cname;
int count;
int i;  
char name[500];
if(control_name[0] == 'P') //always put a P_ in panel names
 {
 cname = strstr(&control_name[2],"_");
 cname++;  //strip out P_WHATEVER_ to get just the control name
 }
GetPanelAttribute (panel, ATTR_NUM_CTRLS,&count);
count +=2;
for(i=2;i<count;i++)
 {
 GetCtrlAttribute (panel, i, ATTR_CONSTANT_NAME, name);
 if(strcmp(name,cname) == 0) break;
 }
if(i>= count) i = 0;
return(i);
}
0 Kudos
Message 1 of 6
(4,275 Views)

I'm not sure to understand exactly what you are aiming to and why you want to treat control constant names instead of their handles, but I suppose your find_control function could be rewritten in a simpler way:

int find_control (int panel, char *control_name)

// Finds a control on a panel
{
 int  pNameLen, next;
 char cName[64], msg[128];

 GetPanelAttribute (panel, ATTR_CONSTANT_NAME, cName);
 DebugPrintf ("Panel name: %s\n", cName);
 strcat (cName, "_"); pNameLen = strlen (cName);

 GetPanelAttribute (panel, ATTR_PANEL_FIRST_CTRL, &next);
 // Iterate through all controls on the panel
 while (next) {
  GetCtrlAttribute (panel, next, ATTR_CONSTANT_NAME, msg);
  strcpy (cName + pNameLen, msg);
  DebugPrintf ("Control #%d: %s\n", next, cName);

  if (!strcmp (name, control_name)) break;
  GetCtrlAttribute (panel, next, ATTR_NEXT_CTRL, &next);
 }
 if (next)
  DebugPrintf ("Found: %d\n", next);
 else
  DebugPrintf ("Not found.\n");
 return next;
}
 



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 6
(4,265 Views)
Thanks for your fine suggestion.  I have never looked at those ATTR_FIRST_CONTROL and ATTR_NEXT_Control before.
 
Currently I have some panels that encode alot of user options.  How to write and read those options from the hardware are encoded in the control constant names.  So generic options are encoded by the control name for those panels and any new panels based on them.  These generic options can be processed on a per panel basis by just inspecting the control names and their values.
 
However, there are also some functions which do actions based on the values of just a few constants.  I wish to use those same functions for several sets of new panels which are very similar.  Since the panel constant changes, the constant names in the functions would change for these new panels, and I wanted to avoid recoding those functions.  I thought I could do that by replacing the constant values (PANEL_CONTROL) of the old panel programmatically with the new panel constant (i.e. find the value of PANEL1_CONTROL) and then pass that to SetCtrlVal, SetCtrlAttribute.  For the functions to work the only requirement is that any time I get a value or an attribute it actually finds the replacement control.  It works already for Get values and Get attributes since those parameters can be cast as void *.
 
It would also work fine if there were a vSetCtrlAttribute(panel,control,attribute,va_list) and a vSetCtrlVal(panel,control,va_list) instead of just the unvectorized versions vSetCtrlAttribute(panel,control,attribute,...) and a vSetCtrlVal(panel,control,...).
 
 
 
 
 
0 Kudos
Message 3 of 6
(4,249 Views)

This works for me  since I was only using integer values for the set ctrl attribute.  You would have to code with a switch like in the set ctrl val to pull out the right argument.  Alternately, CVI could have the vectorized versions of the base calls and people could wrap them more easily.

Robertos find control is better above.

int find_control(int panel,char *control_name)
{
char *cname;
int count;
int i;  
char name[500];
//works only if panel constants are of the form P_SOMENAME
if(control_name[0] == 'P') //always put a P_ in panel names
 {
 cname = strstr(&control_name[2],"_");
 cname++;  //strip out P_XXXX_ to get just the control name
 }
GetPanelAttribute (panel, ATTR_NUM_CTRLS,&count);
count +=2;
for(i=2;i<count;i++)
 {
 GetCtrlAttribute (panel, i, ATTR_CONSTANT_NAME, name);
 if(strcmp(name,cname) == 0) break;
 }
if(i>= count) i = 0;
return(i);
}

int SetCtrlAttributeW(int panel,char *control_name,int attribute,...)
{
va_list ap;
int i;
i = find_control(panel,control_name);
if(i) {
va_start(ap,attribute);
SetCtrlAttribute(panel,i,attribute,va_arg(ap,int));
va_end(ap);
}

return(0);
}

int GetCtrlAttributeW(int panel,char *control_name,int attribute,void *v)
{

int i;
i = find_control(panel,control_name);
if(i) {
GetCtrlAttribute(panel,i,attribute,v);
}
else
{
char x[1000];
strcpy(x,"Control not found: ");
strcat(x,control_name);
MessagePopup("Problem",x);
}
return(0);
}

int GetCtrlValW(int panel,char *control_name,void *v)
 {
 int i;
 i = find_control(panel,control_name);
 if(i)
  {
  GetCtrlVal(panel,i,v);
  }
 else
  {
  char x[1000];
  strcpy(x,"Control not found: ");
  strcat(x,control_name);
  MessagePopup("Problem",x);
  }
 return(0);
 }
 
int SetCtrlValW(int panel,char *control_name,...)
{
int type;
va_list ap;
int i;
i = find_control(panel,control_name);
if(i) {
GetCtrlAttribute (panel, i, ATTR_DATA_TYPE, &type);
va_start( ap,control_name);
switch(type)
 {
 case VAL_SHORT_INTEGER: return(SetCtrlVal(panel,i,va_arg(ap,short)));
 case VAL_INTEGER: return(SetCtrlVal(panel,i,va_arg(ap,int)));
 case VAL_CHAR: return(SetCtrlVal(panel,i,va_arg(ap,char)));
 case VAL_UNSIGNED_CHAR: return(SetCtrlVal(panel,i,va_arg(ap,unsigned char)));
 case VAL_UNSIGNED_INTEGER: return(SetCtrlVal(panel,i,va_arg(ap,unsigned int)));
 case VAL_UNSIGNED_SHORT_INTEGER: return(SetCtrlVal(panel,i,va_arg(ap,unsigned short)));
 case VAL_STRING: return(SetCtrlVal(panel,i,va_arg(ap,char *)));
 case VAL_FLOAT: return(SetCtrlVal(panel,i,va_arg(ap,float)));
 case VAL_DOUBLE: return(SetCtrlVal(panel,i,va_arg(ap,double)));
 }
va_end(ap);
}
return(0);
}

 

Just change the function calls to the X version and then use this switch to call the new stuff above or the standard calls.


#if 1
#define SetCtrlValX(panel,control,value) SetCtrlValW(panel,#control,value)
#define GetCtrlValX(panel,control,value) GetCtrlValW(panel,#control,value)
#define SetCtrlAttributeX(panel,control,attribute,value) SetCtrlAttributeW(panel,#control,attribute,value)    
#define GetCtrlAttributeX(panel,control,attribute,value) GetCtrlAttributeW(panel,#control,attribute,value)    
#else
#define SetCtrlValX(panel,control,value) SetCtrlVal(panel,control,value)
#define GetCtrlValX(panel,control,value) GetCtrlVal(panel,control,value)
#define SetCtrlAttributeX(panel,control,attribute,value) SetCtrlAttribute(panel,control,attribute,value)    
#define GetCtrlAttributeX(panel,control,attribute,value) GetCtrlAttribute(panel,control,attribute,value)    
#endif

 

0 Kudos
Message 4 of 6
(4,245 Views)

Just an idea I got from your message: if the different panels are *really* very similar one to each other you could consider designing only one panel in the UIR editor with all elements needed and load it more than once adapting its aspect to that particular instance characteristics (hiding / showing some controls, changing some text message or so). Operating this way, both control constant names and control callbacks remains unchanged so your software could end to be simpler than expected.

This solution is feasible is panels have little difference between them, becoming more and more complex as they differentiate, so it's up to your application characteristics to define if this can be a practical option for you.



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 5 of 6
(4,229 Views)
the functions part is identical.  the rest is all different.  maybe 10% of the controls are the same which run all the functions behind the buttons.  the rest of the functionality is taken care of by coding the control constant names like ADDR_MASK where the value of the control will read modify address with the mask specified.  that way they are just indicators.
 
 
 
 
0 Kudos
Message 6 of 6
(4,213 Views)