Maybe this is something which everybody does already, or maybe it isn't handy at all, comments welcome.
When I started out writing CVI programs I tried to only update the controls that were changed, right from the routine that changed them. However this sometimes yielded unexpected results, as some changed values updated other values, which in turn weren't updated on the display. It can be some work to keep track of all your values and to make sure that what you see on the screen is the actual value that the program uses internally.
I solved this problem by creating the UpdateAllControls(void) function.
The function basically is a long list of SetCtrlVal and SetCtrlAttribute commands. Below is a very trimmed version from one of my programs:
void UpdateAllControls(void)
{
SetCtrlVal(Leis.MainPanel, LEISPANEL_PHYDASCONNECTED, PhyDAS.Connected);
SetCtrlVal(Leis.MainPanel, LEISPANEL_NUMBEROFWINDOWS, Leis.NrOfWindows);
if ((Leis.Mode == LEIS1) || (Leis.Mode == QTOTAL)) {
SetCtrlVal(Leis.MainPanel, LEISPANEL_ENERGYLOW, Leis.Ebegin);
SetCtrlVal(Leis.MainPanel, LEISPANEL_ENERGYHIGH, Leis.Eend);
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYLOW, ATTR_LABEL_TEXT, "ION energy low (eV)");
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYLOW, ATTR_PRECISION, 0);
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYHIGH, ATTR_LABEL_TEXT, "ION energy high (eV)");
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYHIGH, ATTR_PRECISION, 0);
SetMenuBarAttribute (Leis.MenuBar, MENU_MANIP_TRACKWIDTH, ATTR_DIMMED, !(Manip.EnableAreaScanning));
}
if (Leis.Mode == XPS) {
SetCtrlVal(Leis.MainPanel, LEISPANEL_ENERGYHIGH, Leis.XPS_BE_End);
SetCtrlVal(Leis.MainPanel, LEISPANEL_ENERGYLOW, Leis.XPS_BE_Start);
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYLOW, ATTR_LABEL_TEXT, "Binding energy low (eV)");
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYLOW, ATTR_PRECISION, 1);
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYHIGH, ATTR_LABEL_TEXT, "Binding energy high (eV)");
SetCtrlAttribute (Leis.MainPanel, LEISPANEL_ENERGYHIGH, ATTR_PRECISION, 1);
}
if (Manip.Connected) SetCtrlAttribute (Leis.MainPanel, LEISPANEL_MANIP_X, ATTR_VISIBLE, 1);
else SetCtrlAttribute (Leis.MainPanel, LEISPANEL_MANIP_X, ATTR_VISIBLE, 0);
SetCtrlVal(Leis.MainPanel, LEISPANEL_EPRIM, Leis.Eprim);
SetCtrlVal(Leis.MainPanel, LEISPANEL_TIMEPERWINDOW, Leis.TimePerWindow);
...
}
After every function which causes variable values to change, I give the UpdateAllControls() command and I don't have to think about which controls should be updated and which ones not. In the UIR files I give start values like 1234, so I can always see, when my program is started, whether the initial values were updated by the program or not (because most initial values will not be 1234).
Disadvantages of this approach:
- The variables used must be global, at least to the file which uses UpdateAllControls()
- Updating the display may become slower because a lot of controls that don't need updating are updated anyway.
I deal with the global variables by putting them into a large structure, so I only have to "extern" the one structure.
I didn't yet see a panel that got updated noticeably slow, though it may become noticeable on slow computers.
Every panel can have its own UpdateAllControls(), like UpdateMainPanel(), UpdatePressurePanel(), etc etc...
Just a thought, any comments on this approach welcome.