LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Mouse events don't work on a button from a panel ran in a DLL

Solved!
Go to solution

Hi.

 

I have a DLL that loads a panel.

Since it's a DLL I can't do the RunUserInterface() function, because the DLL would be stuck waiting for the panel events.

I only do the LoadPanel().

 

When I click with the mouse on one of the buttons, the pushing down event (simulating the button being pressed) doesn't happen and the callback doesn't run.

 

But if I press the tab button until the focus reaches the button and press Enter, the callback of the button is executed.

 

An even more interesting aspect is that this happens when I call the DLL on TestStand, but on an application of mine that calls the DLL just for debug everything works fine.

 

How can I enable the mouse events?

 

Thanks for your help.

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 1 of 14
(4,519 Views)

Hello Daniel,

 

I got surprised when I read your post, because I am experiencing something almost the same as you do.

 

I have a DLL (generated by an .fp instrument driver I wrote) which performs continious TCP communication with the UUT.

It starts 2 threads, each for reading from one of the 2 different IPs the UUT has.

 

Another DLL tests this UUT (with the help of the communication DLL above) by exporting functions to be called by TestStand steps.

 

If the second DLL wants to display a CVI panel in order to wait for the user response or displays a popup (MessagePopup, ConfirmPopup, etc), user cannot press the buttons.

Actually, there is a point your program and mine differ. I call RunUserInterface and the button's callbacks call QuitUserInterface, so the execution continues after a button is pressed. The problem is buttons cannot be pressed. I also tried looping on GetUserEvent  but it did not solve the problem.

 

There are 2 findings:

1. I had a small exe to test my instrument driver DLL and the popups in it worked pretty well (this coincides with Daniel's findings).

2. We workedaround the problem by shutting down the communication threads in the instrument driver DLL before the popup appears and restrating them afterwards. Although they are separate threads in another DLL, they were somehow blocking user events on another DLL running.

 

S. Eren BALCI
IMESTEK
0 Kudos
Message 2 of 14
(4,510 Views)

Don't you need to use LoadPanelEx(), rather than LoadPanel(), when working inside a dll?

 

JR

0 Kudos
Message 3 of 14
(4,506 Views)

My mistake. I'm in fact using LoadPanelEx().

 

Altough my problem differs a bit from ebalci, the probem remains.

 

I appreciate everyones help.

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 4 of 14
(4,502 Views)
Solution
Accepted by topic author Daniel Coelho

Hi Daniel,

 

In order to operate a CVI panel properly, you do need to call RunUserInterface, ProcessSystemEvents or GetUserEvent in order to run the UI properly, and you need to call those functions in the same that thread that created the panel. If you don't call one of those functions, some things might work, but others, specifically involving mouse clicks, will not. You can't rely on TestStand calling these functions for you. The likely reason why your UI works when you call it from a CVI program is because that CVI program is probably calling one of those functions, whereas TestStand is not.

 

If you can't wait inside the DLL function after displaying the panel, then you will need to rethink your application. You might want to consider creating a dedicated thread inside your DLL that both displays the UI and then performs the event processing indefinitely, thus allowing the thread that called the DLL to return immediately. Another alternative would be to have the same TestStand thread call another function in your DLL repeatedly, on a timer, which would do nothing more than call ProcessSystemEvents and then return.

 

This doesn't explain ebalci's problem, since he was already processing events in the UI thread (also, built-in popup functions, such as MessagePopup, process their own events). It seems as if those problems were being caused by the communication threads starving the UI thread and not allowing it run. But I don't know why that would happen.

 

Luis

Message 5 of 14
(4,481 Views)

Thank you Luis for your help.

I guess I have no alternative but to rethink the application.

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 6 of 14
(4,435 Views)

Here's what I did to solve this issue:

One function of my DLL creates a thread and that thread creates the panel and runs the RunUserInterface() function.

After this everything works well.

 

When I want to close the panel I call one function of the DLL that changes a global variable to tell that the application is exiting.

The user interface has a timer to check this variable, when it changes the timer calls QuitUserInterface() and thats it, the panel closes.

 

Don't know if it is the best way, but it seems to do the job.

 

Thank you for all your help.

 

My best regards.

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 7 of 14
(4,399 Views)

Hi Daniel,

 

Glad you solved it.

 

Maybe you have a reasonable cause, but are you aware that you could also call QuitUserInterface directly from the DLL function, instead of setting a global flag and polling it from a timer.

 

Regards,

S. Eren BALCI
IMESTEK
0 Kudos
Message 8 of 14
(4,380 Views)

Actually, because QuitUserInterface has to be called in the same thread that is running RunUserInterface, he pretty much has to do something like what he's doing, in order to signal, from the DLL's main thread to the DLL's UI thread, that the UI should close.

 

He could also use PostDeferredCallToThread, instead of using a global variable, but either method should work. The one advantage of using PostDeferredCallToThread would be that he would no longer need a timer, which would save him some CPU processing time (depending on the frequency of the timer).

 

Luis

Message 9 of 14
(4,357 Views)

Thanks for that function.

I wasn't aware of PostDeferredCallToThread().

 

I used the timer because I thought that I could only call QuitUserInterface() from the same thread that is running RunUserInterface().

I never even tried calling it directly.

 

I'll try both of those solutions.

 

Thank you.

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 10 of 14
(4,342 Views)