LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Is it possible to force the values assigned to the CONSTANT NAMES in client.h?

I am creating a GUI. I have several panels. One of the panels has 2800 radio buttons. These radio buttons are 400 main buttons each with 6 sub-buttons. With so many buttons I created the panel by cutting and pasting. This resulted in the CONTROL NAME definitions in client.h not being in any particular order. I would like to force the order to be somewhat sensical. For instance:

 

#define Main_A_button 1

#define Main_B_button 2

#define Main_C_button 3

.

.

.

#define Main_Z_button 26

#define Sub_A0_button 27

#define Sub_A1_button 28

#define Sub_A2_button 29

.

.

.

#define Sub_A5_button 32

#define Sub_B0_button 33

#define Sub_B1_buttion 34

etc.

 

Or even like this:

#define Main_A_button 1

#define Sub_A0_button 2

#define Sub_A1_button 3

#define Sub_A2_button 4

#define Sub_A3_button 5

#define Sub_A4_button 6

#define Sub_A5_button 7

#define Main_B_button 8

#define Sub_B0_button 9

#define Sub_B1_button 10

#define Sub_B2_button 11

#define Sub_B3_button 12

 

Is there a way to do this?

 

I tried editing client.h and setting them like I want them but then when I compile and stop at a breakpoint in one of the callback functions the contol value that has been passed to the callback function is not the new value that I have assigned it in my edited client.h.

 

Thank you for any help you can offer, Gwen Belt

0 Kudos
Message 1 of 10
(3,968 Views)

Gwen:

 

As you have found out, you can't control the control ID values: the UIR editor does.  But that's the beauty of constants: your program refers to the names and you don't care what the values are.

 

If you want to perform some operation on multiple controls, you can put the control IDs into arrays and operate on the arrays.

 

Here are some previous posts that deal with that topic.

 

http://forums.ni.com/ni/board/message?board.id=180&message.id=15940&query.id=2276543#M15940

http://forums.ni.com/ni/board/message?board.id=180&message.id=8799&query.id=2276897#M8799

http://forums.ni.com/ni/board/message?board.id=180&message.id=6285&query.id=2277389#M6285

http://forums.ni.com/ni/board/message?board.id=180&message.id=43106#M43106

0 Kudos
Message 2 of 10
(3,964 Views)
Thank you AI S. I have used arrays in the past for this purpose but with such a huge amount of controls on a single panel I was hoping there was another way. Thank you again. Gwen
0 Kudos
Message 3 of 10
(3,961 Views)

Gwen:

 

Just out of curiousity, what does an operator do with 2800 radio buttons?

0 Kudos
Message 4 of 10
(3,957 Views)

Probably get really annoyed. : )

 

It's a piece of test equipment that can simulate up to 400 moving "targets". Each of these "targets" has up to 6 waypoints to define it's movement.

0 Kudos
Message 5 of 10
(3,955 Views)

Gwen:

 

Have you given them a way to save and recall the settings for the 400 targets?  Like SavePanelState() and RecallPanelState(), or by creating a script language so settings could be created in a text file?

0 Kudos
Message 6 of 10
(3,949 Views)

AI S,

 

I've picked this project up from another programmer but yes we did have a way to save and restore all of the GUI settings. I'm not quite sure how they did it but I know the capability was there. Thank you for all of your help and feedback. I appreciate your input.

 

Gwen

0 Kudos
Message 7 of 10
(3,946 Views)

400 targets each with 6 waypoints, i suppose that each target behaves identically.

 

personally, i would build only one borderless panel containing one button and 6 sub-buttons. then i would write a little function that will dynamically load this panel 400 times, and arrange them properly on the main window. now you don't have any problem with control constants: the window handle is the handle of the sub-panel, and each control uses the same constant name on every panel.

 

well, here is a little sample which explains my ideas far better than my words... try it, use it, abuse it, and don't hesitate to ask if you need further clarification.

(sorry, the main panel is missing a scrollbar: i had no time to add this feature, maybe in the next version...)

 

Message 8 of 10
(3,939 Views)
i found the option that was missing on the main panel in order to have a vertical scrollbar: now you can add those 1000 sub-panels and actually play with them.
0 Kudos
Message 9 of 10
(3,928 Views)

Another solution for similar problem! 

 

Although not as many as 400, I often have panels with repeated controls for many objects. Even applications where the number of objects is variable. For those objects, I make one set of controls, and I make a structure for housekeeping data. An array-variable with the structure is created that has sufficient memory for the largest number of objects. As an example, some code for a panel that controls many motor-axes. The controls include textbox, buttons, numerical controls, and LED. I copied the 9 names manual from the UIR h-file.

 

#define MotorMaximumNumberOfMotors 40

#define MotorVerticalControlDistance 25  /* vertical displacement of controls */
#define MotorNumberOfControls 9
struct sMotor
{
 int Used;                 /* axis number of selected motors */
 double LowerLimit;        /* temporarily lower limit */
 double UpperLimit;        /* temporarily lower limit */
 .... ....
 .... ....
 int Activated;            /* Activated by Active or Home Search */
 int ControlCallbackData;  /* id for connecting buttons with motor */
    int ControlId[MotorNumberOfControls];
};
static struct sMotor Motors[(MotorMaximumNumberOfMotors+1)];
static int    MotorSetControlId[MotorNumberOfControls] =
                  {MOTORP_NAME_0,MOTORP_NUMBER_0,MOTORP_ACTIVEBUTTON_0,
                   MOTORP_HOMEBUTTON_0,MOTORP_POSDISPLAY_0,MOTORP_VALIDPOSLED_0,
                   MOTORP_STEPSELECT_0,MOTORP_APPOFFSETDISPLAY_0,MOTORP_APPDIRDISPLAY_0};

 

In main-function (or panel-display-update function), I copy the controls as often as needed with a maximum of the allocated structure-array size. When copying, the position for each set is a an increasing (Y-) position in the panel. It is smart to prepare the panel with all other controls and headers at the top, and to make it with a vertical slider.
Each control has automatic the same call-back function. Each control gets its own sequence-number as callbackdata. So if a button is pushed, the callbackdata is used as identifier for the object number.
Each new-copied control ID is stored in the structure array. So when an object property has changed and e.g. a LED has to switch on, the structure can be used to look for control ID.
I have to remember myself what each of the 9 controls do e.g. number 0 is its description, number 3 is an activate-button, etc. (As an alternative I could have made inside the structure 9 seperate fields with readable names e.g.: int IdName; int IdNumber; int IdActiveButton; ....)

 

int  j, MC;
int  FirstLeft, FirstTop, FirstID;
/* copy existing controls to global array at index=0 */
/* fill structure-array with sequence number for callbackdata */
for (j=0; j<=MotorMaximumNumberOfMotors;j++) Motors[j].ControlCallbackData=j;
/* set existing controls - which are only template - to invisible and dimmed */
for (j=0;j<MotorNumberOfControls;j++)
{
 Motors[0].ControlId[j] = MotorSetControlId[j];
 SetCtrlAttribute (motorp, Motors[0].ControlId[j], ATTR_VISIBLE, 0);
 SetCtrlAttribute (motorp, Motors[0].ControlId[j], ATTR_DIMMED, 1);
}
/* set some attributes of the template controls before duplicating */
SetCtrlAttribute (motorp, Motors[0].ControlId[2], ATTR_OFF_COLOR, VAL_LT_GRAY);
SetCtrlAttribute (motorp, Motors[0].ControlId[2], ATTR_ON_COLOR, VAL_GREEN);
SetCtrlAttribute (motorp, Motors[0].ControlId[3], ATTR_OFF_COLOR, VAL_LT_GRAY);
SetCtrlAttribute (motorp, Motors[0].ControlId[3], ATTR_ON_COLOR, VAL_GREEN);
SetCtrlAttribute (motorp, Motors[0].ControlId[5], ATTR_OFF_COLOR, VAL_RED);
SetCtrlAttribute (motorp, Motors[0].ControlId[5], ATTR_ON_COLOR, VAL_GREEN);
/* copy template controls and set visible and dimmed attributes */
/* collect all control-IDs in array, so these can be discarded  */
for (j=0;j<MotorNumberOfControls;j++)
{
 FirstID = Motors[0].ControlId[j];
 GetCtrlAttribute (motorp, FirstID, ATTR_TOP, &FirstTop);
 GetCtrlAttribute (motorp, FirstID, ATTR_LEFT, &FirstLeft);
 for (MC=1; MC<=MotorNumberUsedMotors;MC++)
 {
  Motors[MC].ControlId[j] =
      DuplicateCtrl (motorp, FirstID, motorp, "",
         (FirstTop+(MC-1)*MotorVerticalControlDistance),
         FirstLeft);
  SetCtrlAttribute (motorp, Motors[MC].ControlId[j], ATTR_VISIBLE, 1);
  SetCtrlAttribute (motorp, Motors[MC].ControlId[j], ATTR_DIMMED, 0);
  SetCtrlAttribute (motorp, Motors[MC].ControlId[j],
        ATTR_CALLBACK_DATA, &Motors[MC].ControlCallbackData);
 }
}
/* fill controls with data from the configuration file                 */
/* a.o. upper- and lower-position limts, description, offsets          */
for (MC=1; MC<=MotorNumberUsedMotors; MC++)
{
 /* control 0 is a text / description */
 ResetTextBox (motorp, Motors[MC].ControlId[0], "");
 SetCtrlVal (motorp, Motors[MC].ControlId[0], Motors[MC].Comment);
 /* control 1 is an integer number */
 SetCtrlVal (motorp, Motors[MC].ControlId[1], Motors[MC].Used);
 /* control 4 is a double new-position numeric */
 SetCtrlAttribute (motorp, Motors[MC].ControlId[4], ATTR_MIN_VALUE, Motors[MC].LowerLimit);
 SetCtrlAttribute (motorp, Motors[MC].ControlId[4], ATTR_MAX_VALUE, Motors[MC].UpperLimit);
 SetCtrlVal (motorp, Motors[MC].ControlId[4], 0.0);
 /* control 7 is a double off-position numeric indicator */
 SetCtrlVal (motorp, Motors[MC].ControlId[7], Motors[MC].Offset);
 /* control 8 is a textbutton with -/+ */
 SetCtrlVal (motorp, Motors[MC].ControlId[8], (Motors[MC].Sign < 0 ? 0 : 1));
}

 

When one of the controls is used and its callback function is activated, the callbackdata gives the object number i.e index for the structure-array. Examples are:
 GetCtrlVal(motorp,Motors[*(int *)callbackData].ControlId[2], &State);
 M = Motors[*(int *)callbackData].Used;
 SetCtrlVal(motorp,Motors[*(int *)callbackData].ControlId[5], 0);
 Motors[*(int *)callbackData].Activated = TRUE;
 MotorUpdatePositionDisplay(*(int *)callbackData);

 

 

0 Kudos
Message 10 of 10
(3,901 Views)