LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Multipanel and/or Multiple GUI DLL

Hello,

I am in the process of writing an application that will use some CVI GUI DLL's   The thought is each DLL is associated with an instrument and will have an instrument specific user interface that can be accessed through an exported function (RUNUI).   The inital problem I ran into was that each RUNUI function would call RunUserInterface() and each DLL had a callback with a QuitUserInterface() which resulted in strange behavoir ( the calling application was also written in CVI)  After searching the forums i realized that I should be running each DLL's user interfaces in seperate threads each with it's own RunUserInterface() and QuitUserInterface() so i had modified my code according to what I thought would be the correct solution:

 

Each DLL has the following three functions along with some exported functions like init read and close and other associted callbacks for the GUI:

 

int __stdcall Photo1980A_RunUI (void)
{
     int threadFunctionId1 = 0;
    CmtScheduleThreadPoolFunction (DEFAULT_THREAD_POOL_HANDLE, ThreadFunctionPhoto, NULL,  &threadFunctionId1);
    CmtWaitForThreadPoolFunctionCompletion (DEFAULT_THREAD_POOL_HANDLE, threadFunctionId1, OPT_TP_PROCESS_EVENTS_WHILE_WAITING);
    CmtReleaseThreadPoolFunctionID (DEFAULT_THREAD_POOL_HANDLE, threadFunctionId1);
        return 1;  
}

 

static int CVICALLBACK ThreadFunctionPhoto (void *functionData)
{
    int DLLpanel;
    if ((DLLpanel = LoadPanelEx (0, "1980APhotomGUI.uir", PANEL1980A, __CVIUserHInst)) < 0) return 0;
    SetPanelPos (DLLpanel, 200, 200);
    DisplayPanel (DLLpanel);
    SetSleepPolicy (VAL_SLEEP_MORE);
    RunUserInterface ();
     /* Free resources for the UI and return success */
    DiscardPanel (DLLpanel);
    return 1;
}

 

int CVICALLBACK quitCB (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
{
    switch (event)
    {
        case EVENT_COMMIT:
            HidePanel (panel);
            QuitUserInterface (0);
            break;
    }
    return 0;
}

 

 

My Main application has two buttons (one for each of the two DLL's) and pressing a button calls associated RUNUI function.

 

So the application works fine as long as I don't try and have two DLL GUI's up at the same time. (open one and as long as it gets closed before calling the other no problems, all the callbacks work etc.)

As soon as I try and call the second RUNUI function from the main application it partially displays the panel and then goes off in the weeds and I have to abort everything. It seems to hang in the DisplayPanel() function (ie never get's to the RunUserInterface() when i'm single stepping).   So my question is if I'm approaching this the wrong way?

Other info CVI2010 Windows7 64bit

Another item is that I have seen the Multipanel example but when I try and run it I get similar behavor (ie when I select the Schedule Function button the panel pops but everything seems to lockup and I dont' see the start button ever fully display)

 

Any help would be much appreciated.

Regards,

 

0 Kudos
Message 1 of 4
(3,528 Views)

Hi,

 

I have a similiar setup and no problem. Each dll main has a 

 

int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)

  switch (fdwReason)   

  {   

    case DLL_PROCESS_ATTACH:     

        if (InitCVIRTE (hinstDLL, 0, 0) == 0)       

          return 0;   /* out of memory */     

        sprintf (gDllName, "Task_%s", "ManualDeviceMeasurement"); // some dll-internal variables ...

        break;   

    case DLL_PROCESS_DETACH:     

        CloseCVIRTE ();     

        break;   

  }   

  return 1;

}

 

and no additional RunUserInterface! The dll contains it's own uir-files (embed ...) and can Load and display them as supposed to.

 

Hope that helps

 

0 Kudos
Message 2 of 4
(3,509 Views)

Thanks for the response.  I didn't include my code for the process attach and dettach but it looks very similar (right out of the example).

 

int __stdcall DllMain (HINSTANCE hinstDLL, DWORD fdwReason,
                       LPVOID lpvReserved)
{
    if (fdwReason == DLL_PROCESS_ATTACH)
        {
         /* Place any initialization which needs to be done when the DLL */
        /* is loaded here. */
        if (InitCVIRTE (hinstDLL, 0, 0) == 0)
            return 0;
        }
    else if (fdwReason == DLL_PROCESS_DETACH)
        {
       
        /* Place any clean-up which needs to be done when the DLL */
        /* is unloaded here. */
        if (!CVIRTEHasBeenDetached ())
            CloseCVIRTE (); 
        }
   
    /* Return 0 to abort if initialization fails */
    return 1;
}

 

How does your DLL handle GUI callbacks and process events if you aren't running the RunUserInterface?  If you call this from something other than a CVI application does it still work?

Regards,

 

0 Kudos
Message 3 of 4
(3,495 Views)

The main exe (a CVI prog) will have RunUserInterface() and QuitUserInterface(); therefore the the GUI callbacks are working...

0 Kudos
Message 4 of 4
(3,487 Views)