LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

User Interface access within .dll

Hi, I am having trouble getting access to a user interface in a dll that I wrote in LabWindows CVI when using the dll in a Visual C++ application.
 
I'll the setup and problem here in detail.
 
Setup
LabWindows CVI 6.0 .dll
Visual C++ application
 
The CVI .dll serves to take measurements from a PNA and graphs the results on a CVI user interface panel embedded in the C++ GUI.  The graph panel consists of a canvas that I convert to a tab control as well as a command button to clear the graph data.
 
The basic algorithm for the application is as simple as this:
    1. Load Measurement .dll which includes loading and displaying graph panel (CVI .dll)  
    2. Move part into fixture (C++app)
    3. Run device measurement (CVI .dll)
    4. Put next part in fixture (C++ app)
    5. Return to step 2
 
Problem  
The problem I am having is that I can only switch tabs and activate the command button when the CVI .dll is running code, and not the C++ app.  I would like for the user to be able to switch tabs at any time because placing a part in the fixture takes a bit of time, but events seem to be only processed when some form of the .dll code is being run, and ignored otherwise.
 

I've tried a couple of different ways to get the interface to recognize input.  One try was to start a new thread when I load the .dll with a call to SetActivePanel and RunUserInterface hoping that the thread would keep an instance of the .dll running at all times, but that didn't work.

Any suggestions on a possible fix here would be welcome.

0 Kudos
Message 1 of 9
(5,050 Views)

Hi MattZ,

I had a couple of clarifying questions, I just want to make sure I understand your setup correctly...

The CVI dll:
I understand that it collects the data and graphs it. You mention that the graph panel (I assume that is in CVI) contains a button and a canvas. What do you mean by the canvas?

Algorithm:
You mention that you move/put parts into the fixture. What do you mean by the fixture?
Do you run the measurement several times and add the new measurements to the graph? If so, do you re-load the dll or simply call a function on the dll?

Also, you want to be able to switch tabs and be able to click the button from the UI. Are the tabs in the CVI UI dll or in the C++ dll? I assume from your problem that they are in CVI. What do the other tabs contain?
You mention that you can manipulate the dll UI when the dll code is running. What specifically is running in the dll at this point?

Thanks.

Jervin Justin
NI TestStand Product Manager
0 Kudos
Message 2 of 9
(5,029 Views)

Thanks, to answer your questions:

Understand that it collects the data and graphs it. You mention that the graph panel (I assume that is in CVI) contains a button and a canvas. What do you mean by the canvas? To get the tabs, I use the CVI function EasyTab_ConvertFromCanvas to convert the canvas into a tab control.  The tab control consists of several panels with graphs corresponding to different measurements, so the canvas is is the tab control I want to be able to switch.

You mention that you move/put parts into the fixture. What do you mean by the fixture?  The fixture is just a mecahnical housing that a robot puts a part to be tested in.  The only reason I even mentioned the fixture was to illustrate that the process takes a little time.  If you just think of the situation as an application takes a lot of time and then calls a .dll function that takes a couple of seconds and then returns to the application again, that's probably a good enough idea of what's happening.

Do you run the measurement several times and add the new measurements to the graph? Yes, the measurement is ran several hundred times and a new plot is added to one of the graph tabs. 

If so, do you re-load the dll or simply call a function on the dll? The .dll is only loaded once when entering the program.  Everytime the .dll takes a measurement, it graphs the resulting data.

Also, you want to be able to switch tabs and be able to click the button from the UI. Are the tabs in the CVI UI dll or in the C++ dll? The tabs are from the CVI dll.

What do the other tabs contain?  Each tab contains a different graph corresponding to a different measurement.

You mention that you can manipulate the dll UI when the dll code is running? What specifically is running in the dll at this point?  It is one function that takes a measurement, collects data, and graphs the data to the appropriate CVI tab.  It's pretty envolved.  The one function and it's subfunctions probably run about 2500 lines of code, but most of that is opening files, processing data, doing GPIB calls, some DCOM calls, and graphing.

I might be able to take a screen shot of the entire user interface, if you are interested.  A picture might explain things much better and faster.  Thanks for the help.  I was thinking about putting together a experiment where I just sit in a Visual C++ application for a number of seconds and then call some CVI .dll code and see if I can manipulate the CVI user interfaces, but I don't know Visual C++ well enough to do that.

0 Kudos
Message 3 of 9
(5,004 Views)

Hi MattZ,

A screenshot might be helpful in understanding what you have setup.

Meanwhile I can try to create a similar setup on my end and see what I get. Basically I am thinking:
1. Create CVI dll that has a UI with buttons and graph. The graph displays data from an analog input and the buttons start/stop the acquisition.
2. Create a VC++ application that loads the CVI UI on it.
3. Now, the dll code should not be running, since I did not tell it to acquire. I will test to see if I can manipulate the 'Start' button.

Would that be a similar enough setup for test purposes?

Jervin Justin
NI TestStand Product Manager
0 Kudos
Message 4 of 9
(4,977 Views)
I think that would get to the root of the problem.  It's a little different from what I do, but it seems like it would recreate the problem.  I'll try to post a screenshot tomorrow.
0 Kudos
Message 5 of 9
(4,970 Views)
Hi MattZ,
 
Thanks for the update, I will try and reproduce it on the test application we discussed and let you know what I find.
Jervin Justin
NI TestStand Product Manager
0 Kudos
Message 6 of 9
(4,944 Views)
Thanks, I couldn't grab a screen shot because the production floor was on there doing something else.
0 Kudos
Message 7 of 9
(4,922 Views)
Hi MattZ,
 
In the middle of trying to reproduce the issue, I found the following comments in the InitUIForDLL function in CVI:
 
 /* Uncomment this call to RunUserInterface or call it from elsewhere */
 /* in your code to begin issuing user interface events to panels     */
 /* RunUserInterface (); */
 
This was autogenerated when I autogenerated the dll code and might be related to what you are seeing.
 
How exactly are you embedding your CVI UI in VC++? What version of Visual C++ are you using?
Jervin Justin
NI TestStand Product Manager
0 Kudos
Message 8 of 9
(4,886 Views)
OK, as soon as I find the version of C++ being used, I'll respond.
 
As to how the CVI UI is embedded, there is just some space carved out on the C++ GUI.  On the cvi side, the code looks like this...
 
gPanelHandles[GRAPHS]=LoadPanelEx(0,fsUIR_FULLPATH, GRAPHS,__CVIUserHInst);    //fsUIR_FULLPATH is just the path name
 
//*** this code I got from a sample at National Inst.
  parent=*graphsHandle;
  GetPanelAttribute(gPanelHandles[GRAPHS],ATTR_SYSTEM_WINDOW_HANDLE,graphsHandle);
 
  /* Windows SDK function SetParent(..) changes the parent of the child handle
     so that the parent handle is now the parent of the child handle's window.
     This will effectively embed the child panel into the parent panel while
     still potentially allowing the child panel to have its maximize,
     dMinimize, and close buttons on the upper right corner.
  */
  oldparent=SetParent((HWND)*graphsHandle, (HWND)parent);  
 
// load the returned graphs window handle
  GetPanelAttribute(gPanelHandles[GRAPHS],ATTR_SYSTEM_WINDOW_HANDLE, graphsHandle);
//yPos, xPos are pased in values from C++ application
  status=SetPanelPos(gPanelHandles[GRAPHS],yPos,xPos); 
/*row 1 - 10 different tabs loaded for different measurements*/ 
status=EasyTab_LoadPanels (gPanelHandles[GRAPHS], fSettingsTabGraphsHandle,
             1,  fsUIR_FULLPATH, __CVIUserHInst,
                  THREE12,   &gPanelHandles[THREE12],
                  THREE13,   &gPanelHandles[THREE13],
                  THREE23,   &gPanelHandles[THREE23],
                  FIXTUREALL,&gPanelHandles[FIXTUREALL],
                  ACTIVE12,  &gPanelHandles[ACTIVE12],
                  ACTIVE13,  &gPanelHandles[ACTIVE13],
                  ACTIVE23,  &gPanelHandles[ACTIVE23],
                  BITALL,    &gPanelHandles[BITALL],
                  FLINTALL,  &gPanelHandles[FLINTALL],
                  LOADALL,   &gPanelHandles[LOADALL],0);
 
DisplayPanel(gPanelHandles[GRAPHS]);
 
If you would like to see the C++ side, I can ask for that code.
 
0 Kudos
Message 9 of 9
(4,879 Views)