Adding Same ActiveX control twice on a dialog causing unexpected behaviour - c++

I have developed a MFC ActiveX control, that displays a graph using data retrieved from Kepware OPC Server using OPC Client. OPC Client code is part of ActiveX control code. The OPC client is launched in a separate thread from main control thread. The control works well when there is only one instance of it on the MFC dialog. However if I add another instance of it on same form, the curve on the graph starts malfunctioning. From the logs I can see that Control app class which is ultimately derived from CWinApp is instantiated only once. Any ideas why it is messing up? Are any global variables being shared between two instances? I am using Visual Studio 2008.

If your ActiveX control is located inside a DLL this DLL is always loaded once into the process that uses the ActiveX control. So it is normal that you only have one CWinApp object even if you have multiple controls.
So you need to design your object in a way, that global data inside the DLL doesn't affect the behaviour or data inside a control instance.
I suppose that you have some global data, that is used by the first control. And when another instance is created this global data is modified by the second instance and the first instance shows wrong data or misbehaves.
All state of such an ActiveX must be located and allocated inside the object.

Related

Is it possible to use CPropertyPage created in DLL in a main application?

I have a dialog-based MFC application that hosts CPropertySheet.
The idea is to scan some folder for DLLs, load each of them dynamically (using LoadLibrary()), acquire a pointer to a function that would work like a CPropertyPage factory, use that function to create per-DLL CPropertyPage instances and insert them to CPropertySheet.
In other words, scan a folder for plugins, acquire the per-plugin property pages and insert them to CPropertySheet of the main application so each plugin would have it's own options GUI.
Plugins are implemented in a form of regular MFC dlls (not extension dlls). I'm aware that AFX_MANAGE_STATE(AfxGetStaticModuleState()) is to be employed.
Each CPropertyPage being created must be derived from an abstract interface (say, IPluginOptionsPropPage) so it would be possible to cast the pointer that factory function returns to IPluginOptionsPropPage.
This task is supposed to be a routine one, however, I could not found any sound examples.
Yes it can be done. You can try these steps
Load the property page library using ::LoadLibrary. The return handle is the handle for the resource.
m_hResInstance = ::LoadLibrary(strFile);
Before creating the instance of the property page, set the instance of the resource handle to the library's handle.
m_hCurrent = AfxGetResourceHandle();
AfxSetResourceHandle(hResInstance);
//Create your property sheet here.
Then reset the resource handle to the current process resource.
//Reset the previous
AfxSetResourceHandle(m_hCurrent);
This will enable you to load the resource of the property page, others like header and library or function pointer can be used as intended.

Why MFC application have both dlg and app?

I am creating a dialog based application, I found there are two components, which are dlg and app.
My question is, what is their different and if I want to write back end logic for the application, which file I should write to for better practice ?
My back end logic means:
e.g: creating an application receives input from two text boxes and sum them up
my back end logic means the function to sum up two variables.
The application (CWinApp) is the outer container, that contains all application specific stuff. The application object is a singleton.
The CMyDialog class carries out the UI and all actions belonging to one dialog.
Because an application may have more than one dialog class, you are not restricted to have only one dialog. But you always have only one application object.
So your logic should all be located in the dialog class.
The dialog and the application may exchange results and data. The normal logic is to copy the data from the application into member objects in the dialog. Launch the dialog. After the dialog is successfully executed the values are copied back.

VST2 interface dll entry points

I am building a VST2 plugin. I want to know when to create a plugin window: on loading the dll (in my case in InitInstance), or some other point (maybe AEffEditor::open)?
I have subclassed AEffEditor. I am creating a window in InitInstance and showing and hiding the window in AEffEditor::open and AEffEditor::close.
It appears that InitInstance (dll load) is not a right point to create a window, but then when?
E.g. the host is creating 3 windows for 2 instances of insert (one on loading the dll).
Another question: when is InitInstance (dll load) called? At the host startup and at each send/insert?
Should I create a window per dll load (m_pMainWnd) or create them in separate threads and keep track of the windows? I.e. will the m_pMainWnd be different or will be same single window?
VST editor windows are supposed to be embedded in a host application window. That means you need a window reference (a HWND on Windows, a WindowRef on Mac with Carbon or an NSView on Mac with Cocoa if you use Cockos extensions) to that host window to be able to create your window.
VST API only passes that window reference when AEffEditor::open is called. And it becomes invalid when AEffEditor::close is called (even though the docs are not very specific about it). Thus, you need to create your window inside AEffEditor::open (as a child window of the window passed to you) and destroy it inside AEffEditor::close.
From this it follows that you need to create a separate window for each plugin instance. The user can put more than one instance of your plugin in different tracks and he/she expects that changes made to one of them don't affect the other.

How to unload ActiveX's ocx without terminating main application to allow the ocx to be overwritten?

I have ActiveX controls implemented in VB6 and are instantiated inside MFC42 application.
I have a tree view structure on the left panel of the application and when different items in the tree are selected, different ActiveX are loaded accordingly on the right panel to display the details of the selected item.
Whenever I want to modify the VB code for the ActiveX, I will need to restart the application. This greatly interrupts the development flow since the application starts pretty slowly.
In some ActiveX we have dummy code/data to allow the ActiveX to be executed inside Internet Explorer, which is faster to load, but not all of our ActiveX have it.
I am expecting that when I click different item in the tree view, the previous ActiveX is unloaded and I can overwrite it with a new version.
If the ActiveX has never been instantiated/displayed, I am able to replace the ocx while the application is still running.
I searched in the internet and found two articles on ActiveX, both of them suggest that the proper way to clean up is to:
m_pControl = new CWnd;
m_pControl->CreateControl(strControlProgid,
"",
WS_VISIBLE,
rc,
this,
5000,
NULL,
FALSE,
NULL);
// ...
m_pControl->DestroyWindow();
delete m_pControl;
The ActiveXs we have are already destroyed using this method but I still need to exit the application in order to overwrite the ocx.
EDIT:
Alternatively, for VC++ 6 (with MFC42), instead of CoFreeUnusedLibrariesEx which is mentioned by Noseratio in his answer; I can use CoFreeUnusedLibraries which will work without delay for Single Threaded Apartement (STA).
Provided the COM reference counting works correctly in your app, you could try forcing to unload the no-longer-in-use ActiveX DLL with CoFreeUnusedLibrariesEx.

Loading DLL and child dll calling parent class

I have an ActiveX dll that loads a child dll (NPAPI plugin). My child plugin creates multiple threads and they need to communicate back to the web page. In my ActiveX (parent dll) I have connection points to fire an event for javascript to provide updates. The problem I am having is that I do not know how the child can call the parent DLL.
What I have tried:
1: Passing a function pointer to the child dll of a function that is not within the class and used a global variable that is a pointer to the ActiveX class (this), but the connection point fails when Invoke with E_UNEXPECTED
2: Passing the child dll a pointer to my class function, and get the same results.
Im still learning C++ and COM at the same time, sorry for my ignorance. Thank you.
COM has ways to set things up so that you can call COM methods from other threads, but the easiest way for you to do this would be to make all calls back to the activex control on the main thread. One way to do this is to create a Message Window and post a windows message to it with the LPARAM being a pointer to a data structure containing the parameters needed to make the call; you create the structure and fill it out, then post the message and free the memory after your WINPROC has made the call.
FireBreath uses this approach and it works quite well. Speaking of which, have you considered implementing your NPAPI plugin as a FireBreath plugin so that it works in both activex and npapi?
Here are some code samples that may help:
WinMessageWindow (.cpp, .h) - this is a class FireBreath uses for creating message windows; pay particular attention to the DefaultWinProc which is used as part of an async (often cross thread) function call
NpapiBrowserHostAsyncWin (.cpp, .h) - this is a class used on some browsers for the npapi plugin to work around NPN_PluginThreadAsyncCall not working. It utilizes WinMessageWindow to make cross thread calls in _scheduleAsyncCall
Hope that helps