VST2 interface dll entry points - c++

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.

Related

Intercepting Windows Messages from Webview2 (Edge/Chromium)

I have recently migrated a project of mine to WebView2 and the last part I can't figure out is how to intercept the Windows Messages for the webview. My code is very similar to webview/webview but I was unable to find help on their GitHub.
Previously, I was able to find the hWnd for the webview and use SetWindowSubclass to add my own wndproc to the webview. However, I've used Spy++ and tried SetWindowSubclass on all the windows that showed up there (see below) but none of them had any windows messages in my wndproc other than some window management ones I did not think were useful - The best I got was WM_PARENTYNOTIFY, but I am interested in WM_MOUSEMOVE and WM_NCHITTEST - neither of which I could find.
My goal is to create a borderless, draggable, resizeable WebView2 based app.
The problem is, that the real window that controls and gets all this input is in another process. You just see a window that shows the output in your process.
Look into Spy++. Everything below Chrome_WidgetWin_0 belongs to a new process (MSEDGEWEBVIEW2) and is not part of your process. So you can't subclass such a window with the normal techniques.
So if you want to subclass this window. You need to inject a new DLL into this new process. This DLL might subclass the real window. And this DLL might communicate with you hosting program via any IPC.

Adding Same ActiveX control twice on a dialog causing unexpected behaviour

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.

How to obtain and interact with QWidgets from QProcess

I have Application A which is a third party Windows application (with GUI) that uses the Qt library.
I want to write Application B which will be responsible for starting Application A. I want Application B to also find buttons on Application B (QWidgets) and send them mouse inputs (click, double click etc).
I can run Application A through using the start function on a QProcess.
How do I do the following from my instance of the QProcess:
Get the top level window(s) for the process
Get a widget by name or (other identifiable attribute)
Get the widgets caption, colour and coordinates (and maybe some other data)
Send mouse move and click events to specific coordinates
Give a widget keyboard focus
Send keyboard key presses
Note - I know how to do this with the Windows API, but asking for a way via Qt. The specific Application A in question does not use the native windowing system, therefore window handles will not show up in Spy++ or Windows API functions.
Update 1 - Cannot seem to get any meaningful objects through the process's children
My attempt at getting child widgets for the process:
QProcess* process = new QProcess();
QString program = "\"C:\\Program Files (x86)\\foo\\bar.exe\"";
process->start(program);
auto widgets = process->findChildren<QWidget*>("", Qt::FindChildrenRecursively);
auto i = widgets.count();
// i = 0
If I find children of type <QObject*> I get 4 results. I used metaObject()->className() to see that I have two pairs of QWindowsPipeReader and QWinOverlappedIoNotifier objects.
Update 2 - Cannot create/inject window from another process
I noticed that when I run the QProcess I can use Windows API functions to get the top level window (top level only). I read in the Qt documentation that you can create a QWindow from the handle of a window in another process using QWindow::fromWinId.
Using this function will throw an 0xC0000005: Access violation reading location 0x00000000. error. I am not passing in a null handle. I am using reinterpret_cast to get the HWND to a WId type. It creates a QWindow only when I create a QApplication beforehand.
The new QWindow will have no children (using window->findChildren<QObject*>("", Qt::FindChildrenRecursively); I assume that the creation of the QWindow does not bring across associated child widgets.
Update 3 - I am currently reading into whether inter-process communication can be used
I have come across various threads, questions and code snippets regarding ICP in Qt. I don't see anything so far that specifically shows that ICP is possible when one of the processes is third party.
I have seen that the Squish Gui test tool lets you interrogate QWidget properties.
This will never work the way you intend it to.
If you really wish to take direct control over the other application, you must inject your code into that application. Let's assume that the application uses a dynamically linked Qt. Then:
Build a binary-compatible version of Qt, using the same compiler that was used to build the application you intend to tweak.
Replace the application's Qt with yours. Everything should still work fine, given that yours should be binary compatible. If not, the binary compatibility isn't there, and you must tweak things until they work.
Edit your Qt to add a hook to initialize your code at the end of QApplication constructor. This makes the Qt module that provides QApplication dependent on your code.
Put your code into a dll that the widgets (for Qt 5) or gui (for Qt 4) module is now dependent on.
Again replace the app's Qt with yours, with hooks that start your code.
Your code will of course need to be asynchronous, and will be monitoring the application's progress by inspecting the qApp->activeWindow(), qApp->allWidgets(), etc.
That's pretty much the only way to do it. You can of course inject your code in any other way you desire, but you will need to work with a binary-compatible version of Qt just to compile your code. Note that binary compatibility encompasses more than merely using the same compiler version and Qt version. Many of the configure switches must be the same, too.

Compiled Qt for windows is win api at Low Level

Qt is cross platform c++ Gui Library.Code once and compile for different Platform. Let's for instance, I have compiled a Project(decent text editor with few tool bar) or any such program for Windows(x86).
Statement 1: The Program.exe entry point will be WinMain.
Statement 2: The Text editor and tool bar will created using "CreateWindow" win32 api. Qt have its own class to implement but to ask OS(Windows) for creating a tool bar or text editor, Program exe interface with OS(Windows). OS understand what it know it does not know anything about Qt class,so to create tool bar or text editor program have to use win32 api.
Statement 3: All event processing( button click, mouse click) will handles using windows messeging system.
Note: It may seem i am viewing every thing with win32 api glass on my understanding.
Correct. The WinMain implementation is provided by the Qt library.
Half correct. The top-level windows are created using CreateWindow. Child widgets, such as a non-toplevel toolbar are Qt's own widgets and are opaque outside of your application. They are exposed only via the accessibility APIs. This allows you to create more widgets than Windows would be able to deal with. A million child widgets is doable, if not particularly fast.
Correct - there's no other way. Of course Qt immediately translates native messages into QEvent instances and dispatches them internally to various QObject instances. In Qt-land, all events must be received by a QObject instance.
You're incorrect in your assertion that winapi has anything to do with the kernel. Winapi is implemented by a bunch of user-space DLLs. You could implement those DLLs yourself. Those DLLs themselves call into the kernel using the native api. That's the API actually exposed by the kernel to the user space.

window less Application

i got to do a task that is to find out process /exe/application running in the background.
ie:the process is running but do not have any UI/ Window visible although its an windows GUI application . i thot of reading EXEheader. The header contains a field called 'Subsystem'and application is to run under and the type of interface it requires.
but it returns Windows GUI and it is so. but i want teo detect if that application haves any window or not. also this application is not a service as if it is a service i can easily read the info.
i will be glad if any of you genious put some light on the pronblem stated.
Warm Greetings..
Sarfu
If I understand your question correctly, you want to know if a running application has any visible windows.
To do this, you can call EnumWindows to get all top-level windows. For each window, call GetWindowThreadProcessId to get the process ID and GetWindowLong(hwnd, GWL_STYLE) to get the window style. Test the style for WS_VISIBLE to see if the window is visible. Run through all the windows and see if your process owns a visible one. If you don't have the process ID, you can get them all with EnumProcesses.
The "subssytem" GUI doesn't tell you that the application has a window. In fact, the opposite is closer to the truth. A console application gets a console window. A GUI app is responsible for creating its own windows, if and when it needs them. A GUI process that hasn't called CreateWindow() won't have any windows.
Apparently, you do know the executable you're looking for. In that case, call EnumProcesses() to find all processes, and for each process call EnumProcessModules(). On Windows, "modules" are DLLs and EXEs. Each process will have exactly one EXE module. So, if the one EXE module of any process is the executable you're looking for, then your application is running.