LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

two panels both calling same third panel

Solved!
Go to solution

Hi there, I'm designing a new application.  I have two main panels, each displays on a unique PC monitor.  I have a third panel that displays detailed data common to both of the first two panels.  This third panel is a configuration panel, such that it needs to place its updated fields back into the calling panel.

 

I would prefer to open this same third panel from either of the first two panels.  But to do so, I need to know which of the two panels opened the third.

 

How would I go about doing this withouth making a global variable?  Would this be a case for using callbackData?  If so, I'm not clear how to go about this.

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

Hi,

 

in a similar application I have used callbackdata. Because I needed more information I have used a structure to pass this information:

 

void CVICALLBACK ProcessDisplayPanelMenu ( int menuBar, int menuItem, void *callbackData, int panel )

 

{
    process = ( struct process_structure * ) callbackData;

Message 2 of 8
(4,672 Views)

Thanks, Wolfgang.  A similar approach without a struct I found here:

 

http://forums.ni.com/t5/LabWindows-CVI/Panel-has-identical-halves-determine-which-half-callback-came...

 

For my particular need, I did this:

 

// panel #1:
			SetPanelAttribute(overridePanel,ATTR_CALLBACK_DATA,(void *)1);
DisplayPanel(overridePanel);

....

// in a control callback on the overridePanel:

switch(callbackData)
{
case PANEL_1:
// do something
break;
}

 

0 Kudos
Message 3 of 8
(4,667 Views)
Solution
Accepted by topic author ElectroLund

Hi ElectroLund,

I can see a problem in your code.

In the calling callback you are setting the panel callbackData.

This means that in a control callback you must retrieve this value, which is different from the control callbackData you receive in the callback. To retrieve the panel callbackData you must do something like this (I have no CVI install at the moment to test it):

void  *cbkd;


GetPanelAttribute (panel, ATTR_CALLBACK_DATA, &cbkd);
if (cbkd) {
  // The panel has some callbackData installed
}
else {
  // No callbackData installed on the panel
}

 

Finally, comparing callbackData value (that you set to a simple '1') to PANEL_1 which I suppose is a panel constant name is not good: PANEL_1 can be equal to '1' only by chance and this can change if you modify the z-plane order of panels.



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

@RobertoBozzolo wrote:
In the calling callback you are setting the panelcallbackData.

This means that in a control callback you must retrieve this value, which is different from the control callbackData you receive in the callback.

 

Finally, comparing callbackData value (that you set to a simple '1') to PANEL_1 which I suppose is a panel constant name is not good: PANEL_1 can be equal to '1' only by chance and this can change if you modify the z-plane order of panels.


You are right, Roberto. I must first get the value of the panel callbackData.  The reason I chose to set that value for the panel, rather than a particular control on that panel, is that the panel has several controls that have callback functions.  I need all of them to know who originally called the panel do behave differently.

 

Also, regarding my undefined "PANEL_1", this was supposed to be some enum value.  However, instead now I'm taking advantage of the UIR include file IDs.  So my declaration of the panel callbackData looks like this:

 

SetPanelAttribute(mainPanel,ATTR_CALLBACK_DATA,(void *)PANEL);

 

Finally, when checking the value of the callbackData with a switch statement, it's invalid to use void pointers.  So I found that I needed to cast as an int (provided I set the value with an int).

 

0 Kudos
Message 5 of 8
(4,620 Views)

Wolfgang, care to elaborate on your syntax for how you assigned your structure to the callbackdata?  I'm referring to either a

 

SetCtrlAttribute(panel,control,ATTR_CALLBACK_DATA,???);

or

 

SetPanelAttribute(panel,ATTR_CALLBACK_DATA,???);

 

I'm unclear how exactly to pass a struct into a void pointer without errors.

0 Kudos
Message 6 of 8
(4,535 Views)

Hello ElectroLund,

 

in my case I use a menu callback, but the principle of course is the same. I have

 

SetMenuBarAttribute ( menu_bar_handle, menu_id, ATTR_CALLBACK_DATA, ( void * ) &sensor.process );

 

to provide the address of the structure.

 

Hope it helps Smiley Wink

Message 7 of 8
(4,528 Views)

Yeah, that works really nicely!  In my case, I'm assigning my structure to a control callback:

structtype testGlobal;

SetCtrlAttribute(panel,CONTROL1,ATTR_CALLBACK_DATA,(void *)&testGlobal);

 And then in the callback function of that control:

 

int CVICALLBACK TestButton (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
     structtype* testLocal;

     testLocal = (structtype*)callbackData;
}

 

0 Kudos
Message 8 of 8
(4,516 Views)