LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

GetUserEvent and InstallPopup

I have a panel which I display with InstallPopup. I use GetUserEvent to wait for an event on that panel. After the event, I RemovePopup. When I install the popup on top of a panel which I displayed using DisplayPanel, it works fine.

However, sometimes I install that popup (popup2) on top of another popup (popup1 installed with InstallPopup before popup2). GetUserEvent (in a callback for a control on popup1) doesn't see the event on popup2; it waits for an event on popup1.

Can I InstallPopup on top of a previously installed popup?

Details about what I'm really trying to do:
I want to be able to change the radix on a number of numeric controls scattered about various panels. I use a popup (on right click) which is a panel just big
enough for three buttons: Binary, Hex, Decimal. A Quit button is active with Escape as the shortcut key, but I sized the panel so it wouldn't display. I popup the panel wherever I rightclicked. It works fine unless the numeric I want to change is on another popup: the SelectRadix popup is displayed, but the radix isn't changed when I click a radix button. It's changed after I generate an event on the popup with the numeric.

Should I be using a menu bar instead? Can I install a menu on top of a popup? Can I place the menu where I want it (at the numeric, not at the top of the panel)?

Thanks,

Al
0 Kudos
Message 1 of 18
(5,129 Views)
Hi, I tried to build a simple test project but I didn't manage to repeat the behaviour you told.
In my experience I never had such problem, so I suppose there's some non-evident reason for this in your code (i.e. for example not raising the wait/no-wait flag when calling GetUserEvent or something else).

I attach my project: maybe you can modify it to adapt to your actual situation so to reproduce the error, so I can study it and suggest some hint.

Hope this helps
Roberto


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 18
(5,129 Views)
Thanks Roberto!
Using your example I was able to duplicate and find my problem. I had the RemovePopup() for panel 2 in the callbacks for panel 2. You had the RemovePopup() for panel 2 in the callbacks for panel 1, not panel 2.

What are the guidelines for installing and removing popups? Am I removing popup 2 too early for GetUserEvent? In general, I want to be able to remove a popup in a function that didn't install it, but am I asking for trouble by doing that? In this case (popup on a popup with a GetUserEvent in the function that installed the second popup) it looks like I need to remove the second popup in the same function that installed it.

To see the problem, run the attached program:
Set Remove Popup 2 to Remove in Popup 2.
Click on Sho
w the first popup.
Click on Trigger the second popup.
Click on 1 (calls Quit).
Popup 2 closes, but no Test Message is displayed.
Click on Trigger the second popup.
GetUserEvent sees the event and the Test Message dialog is displayed.
Click OK
Click Quit
Test Message dialog is displayed.
Click OK
Click Quit

To have it work as intended:
Set Remove Popup 2 to Remove in Popup 1.
Click on Show the first popup.
Click on Trigger the second popup.
Click on 1 (calls Quit).
Popup 2 closes and the Test Message is displayed.
Clock OK
Click Quit
Click Quit program.

Thanks!
0 Kudos
Message 3 of 18
(5,133 Views)
Well, I get an error while loading the UIR in your project, so I couldn't look at it, but reading your message, maybe I can suggest you some hint.

The main advantage of GetUserEvent is that it returns on the first commit event generated in the user interface: since you are using a popup panel, commit events can only be triggered by controls on the panel showed as popup; BUT you definitely don't need to associate a callback to those controls; a callback associated to them can lead to strange behaviours like those you are experimenting in your program.

If you do need to manage events IN the popup panel BEFORE quitting it, you must set the control mode as 'normal' and manage the left_click or keypress event in the callback associated with
them. I modified my original project to show you this behaviour (this example is not complete since I should manage the event_keypress also and discriminate which key has been hit and operate on enter or spacebar key as for left_click event...).

Hope this helps
Roberto

Ok, I manged to open your project (I was using CVI 5.5 instead of 6...); your problem is the callback associated to button b1: it removes the event_commit from the queue before it's managed by getuserevent, so this one intervene on buttons in the first popup (the one live once p2 has been removed). As I said before, either you change p2_b1 mode to normal and manage the mouse and keyboard events on it, or you must remove the callback by the button and manage all commit events in an infinite loop inside ChangeType callback (exit from the loop for the quit button, otherwise manage buttons as usual); the second solution seems to me more complicated, but it's probably a matter of style...


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 18
(5,137 Views)

I have a similar problem. I have a control which does an InstallPopUp. This works fine using GetUserEvent. However when the child (the 1st popup) creates a grandchild (2nd popup) the GetUserEvent doesn't see the events until both pop-ups are extinguished. N.I. says that I shouldn't use a 2nd popup. I should use a display panel instead to avoid the problem. But I can't. Because Install pop-ups are modal, and I need the pop-up to be modal because I cannot let the user do anything else but act on the active pop-up panel.

I even created a very small project with all kinds of debug details to show N.I. how it works, (or not works as expected), but it seems they are not going to fix it because they insist I should not do a 2 level Instal Pop-up.

Has anyone had or seen this problem?

Thank you for answering.

0 Kudos
Message 5 of 18
(4,324 Views)

It seems to me that previous answers on this thread should help you in solving your situation. Nevertheless, in the 13 years passed from the original posts I have changed a lot in my programming habits, and avoiding the use of GetUserEvents is one of the changes. I have found difficult in some conditions to discriminate "where" the event generated, which seems exactly your situation.

 

At present I handle all control events inside control callbacks leaving GetUserEvents to very few situations in which it's clear that only a few controls can fire events; in order to simplify the code, in case of small dialogs with a few controls and a few lines of code I use the same callback for all controls, discriminating which one fired it with a switch on on 'control' variable.

 

Is such an approach not feasible to 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?
0 Kudos
Message 6 of 18
(4,305 Views)

Thanks for getting back to me. This program is HUGE, 200,000 lines of code, so your suggestion would not apply to my case unfortunately. However we only have one instance where this problem ocurrs. Having a control create an InstallPopup, who in turns creates also an InstallPopup. We do this because we need to be modal in the popup and not let the user do anything else but answer the present popup, and extinguish it when done. I guess the only solution I see is to create my own global varaible which sets a flag when the corresponding popup is extinguished, and just have the while loop test for that condition, and forget the GetUserEvent function. But it is kludgy and for that reason it is not liked or accepted by my superiors.

0 Kudos
Message 7 of 18
(4,296 Views)

Would you mind posting that little project you made for NI? 'cause I tried the code below and seems to me that it runs correctly, so you may be doing something different and I'd like to see it.

 

int CVICALLBACK TestPopup (int panel, int control, int event,
		void *callbackData, int eventData1, int eventData2)
{
	int		pnl, ctl, tmp1H = 0, tmp2H = 0;

	if (event != EVENT_COMMIT) return 0;

	// Load a popup panel and handle buttons on it
	tmp1H = LoadPanel (0, UIR, MyPanel);
	InstallPopup (tmp1H);
	while (TRUE) {
		// Continue trapping events...
		GetUserEvent (1, &pnl, &ctl);
		switch (ctl) {
			case MyPanel_go:	// Load the panel another time
						// and handle buttons on it
				tmp2H = LoadPanel (0, UIR, MyPanel);
				InstallPopup (tmp2H);
				while (TRUE) {
					// Continue trapping events...
					GetUserEvent (1, &pnl, &ctl);
					if (ctl == MyPanel_quit) {
						// Dismiss the panel
						DiscardPanel (tmp2H);
						break;
					}
				}
				break;
			case MyPanel_quit:
				// Dismiss the panel
				DiscardPanel (tmp1H);
				goto Out;
		}
	}
Out:
	return 0;
}

 



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

int CVICALLBACK CreateAchild (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
int WhichPanel, WhichCtrl;
 switch (event)
 {
  case EVENT_COMMIT:
   InitValues();         // Mainly reset counters
   if (StaticTest == 1)
   {
    SetCtrlVal(FatherUir,PANEL_Child_PanelId,Child);   // static from .h
    SetCtrlVal(FatherUir,PANEL_GrandChild_PanelId,Grandchild); // static from .h
   }
   else           // dynamic 
   {
    SetCtrlVal(FatherUir,PANEL_Child_PanelId,child);   // dynamic from Load above
    SetCtrlVal(FatherUir,PANEL_GrandChild_PanelId,grandchild); // dynamic from Load above
   }
   SetCtrlVal(FatherUir,PANEL_Child_ControlId,Child_ChildDone);
   SetCtrlVal(FatherUir,PANEL_GrandChild_ControlId,Grandchild_GrandchildDone);
            InstallPopup(child);
            while (waitingForMyEvent)    // wait for either Pop-up Done event
            {
             GetUserEvent (1, &WhichPanel, &WhichCtrl);
             if (StaticTest == 1)
            {
              if ((WhichPanel == Child) && (WhichCtrl == Child_ChildDone)) // static from .h
               {
                 BlinkAndBumpChild();  // blink once and bump counter
               }
              else if ((WhichPanel == Grandchild) && (WhichCtrl == Grandchild_GrandchildDone)) // static from .h
              {
                 BlinkAndBumpGrandChild(); // blink once and bump counter
              }
              else if (ChildEventDone == 1) // this flag was set when control was clicked
              {
                 BlinkChildTwice();   // this does NOT bump counter However it blinks TWICE
              }
              else if (GrandChildEventDone == 1) // this flag was set when control was clicked
              {
                 BlinkGrandChildTwice();   // this does NOT bump counter However it blinks TWICE
              }
             else
             {
                BlinkNothing();    // theoretically we should never get here but we do
             }
          }
          else        // dynamic
         {
              if ((WhichPanel == child) && (WhichCtrl == Child_ChildDone)) // dynamic from Load above
             {
               BlinkAndBumpChild();  // blink once and bump counter
             }
              else if ((WhichPanel == grandchild) && (WhichCtrl == Grandchild_GrandchildDone)) // dynamic from Load above
             {
                BlinkAndBumpGrandChild(); // blink once and bump counter
             }
              else if (ChildEventDone == 1) // this flag was set when control was clicked
             {
               BlinkChildTwice();   // this does NOT bump counter However it blinks TWICE
             }
              else if (GrandChildEventDone == 1) // this flag was set when control was clicked
             {
                BlinkGrandChildTwice();   // this does NOT bump counter However it blinks TWICE
             }
             else
             {
                BlinkNothing();    // theoretically we should never get here but we do
              }
          }
      }
      break;
   case EVENT_RIGHT_CLICK:
        MessagePopup("When creating a child (pop-up) observe the 3 check boxes below","Each time a box turns black then white an event ocurred.\nSome events create multiple user events.\nThese check boxes are there to understand how the system works.");
      break;
  }
 return 0;
}

0 Kudos
Message 9 of 18
(4,286 Views)

attached is the entire project

0 Kudos
Message 10 of 18
(4,284 Views)