|
I'm not sure if the thread title is really accurate, but it's the best description I can think of.
I'm in the process of creating the GUI part of a software synthesizer (VST). The synthesizer will reside in a dll. An application called the host will load the dll and run the synthesizer. I've chosen MFC for putting together the GUI elements for the synthesizer. My approach has been to test out the GUI elements in an MFC dialog based application. I've reached a point where I now I have most of the GUI work done, and I've been attempting to integrate it with the syth engine. This has meant basically copying relevant MFC files over to my synth dll project. I've made sure that I've set up the project so that it links to MFC in a shared library.
The idea is that when the host asks me for an synth editor, I pass it a class encapsulating an MFC dialog. The dialog displays all of the synth controls.
So for so good, but I've run into a problem in that I get this compile error:
Linking...
mfcs42d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in vstplugmain.obj
There's a conflict between the main function that is implemented in vstplugmain.cpp and the main function implemented some where in the bowels of the MFC library. I've been googling like crazy, but have not found a solution to resolve the conflict.
vstplugmain.cpp is the file that exports the main function. It's the function that the host interacts with when it loads the dll.
Is there something fundamentally wrong with this approach in that I won't be able to use MFC in a dll that exports its own main function?
[EDIT]
Hmm, the error goes away when I statically link to MFC.
[/EDIT]
-- modified at 16:30 Wednesday 3rd October, 2007
|
|
|
|
|
Leslie Sanford wrote: The idea is that when the host asks me for an synth editor, I pass it a class encapsulating an MFC dialog. The dialog displays all of the synth controls.
My approach would be to create an MFC enabled dll and add both the gui and the classes from the synth dll to it. I would tend to use either an MFC extension dll or an inproc COM server with MFC support, but a normal dll with MFC support should do as well.
Nathan
|
|
|
|
|
In addition to Nathan's reply...
This Link[^] has info on choosing MFC DLL types and for
each type, info on proper initialization.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: This Link[^] has info on choosing MFC DLL types and for
each type, info on proper initialization.
Thanks, Mark. That link is very informative.
Since MFC defines it's own DLLMain, I have to get rid of the one provided by the third-party library I'm using for this project. I don't like doing that because it means altering the source code, but I can live with it if it means getting things compiled.
Another problem is that host applications that use my dll pass it an HWND handle. I'm suppose to use this as a parent window and instantiate a child window. This child window provides a UI for interacting with the synth my dll represents. This UI resides within a window displayed by the host application.
However, from the link above:
If the DLL opens modeless dialogs or has a main frame window of its own, the application's main
message pump must call a routine exported by the DLL that in turn calls the
CWinApp::PreTranslateMessage member function of the DLL's application object.
I'm not sure I understand the above, but if it means that I have to require the host application to call a specified function in my dll, all bets are off. I can't make that requirement as the protocol for how hosts and dlls interact within the domain I'm working in is already set. I'm in no position to require a host to do anything.
My attempts to instantiate a CDialog derived class have failed. I've tried using CWnd::FromHandlePermanent to incapsulate the HWND handle given to me by the host application in order to pass it to the CDialog's constructor. But CWnd::FromHandlePermanent returns NULL.
So I may have bet on the wrong horse in using MFC for this project. My goal was to leverage MFC's classes in building a GUI exported from my dll. I may need to do a major rewrite.
|
|
|
|
|
Leslie Sanford wrote: I'm not sure I understand the above, but if it means that I have to require the host application to call a specified function in my dll
Yeah, that's the only way to get messages to windows in a regular DLL linked
to MFC.
If you have an initialization function that hosts are required to call, you could fire up
another UI thread and run all the DLL's windows on that.
Are your host applications always MFC or can they be straight Win32?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: Are your host applications always MFC or can they be straight Win32?
They can be either. I have no way of knowing beforehand if a host is MFC based, so I have to take that into account when writing the dll.
I've managed to get CWnd::FromHandle to work in so far as I can create a CDialog based object that the host can display. But I'm getting all kinds of memory access exceptions and memory leaks. I created a test project with the simplest functionality the host requires so that I can narrow down any problems. So far I haven't been able to pinpoint where the memory problems are occurring.
Others have apparently used MFC to do what I'm attempting to do without problems, but I'm having trouble getting this to work, so I'm currently investigating rewriting my custom controls using straight Win32. It may not be quite as hard as I had thought.
|
|
|
|
|
Leslie Sanford wrote: I've managed to get CWnd::FromHandle to work in so far as I can create a CDialog based object that the host can display.
hmm I'm not clear what you're doing.
What HWND are you obtaining a CWnd for? Are you doing this in your DLL?
There's a couple important issues with this:
1) Windows messages need to get routed to the MFC message system
2) Except with an MFC extension DLL, you can't pass any MFC objects
directly or indirectly across the exe/dll boundary.
These two are the problems most likely to break this scenario, if that helps
you any
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: What HWND are you obtaining a CWnd for? Are you doing this in your DLL?
The HWND handle is given to me by the host. In response, I'm suppose to create a child window using the specified handle as the parent and display it. The user interacts with the child window making edits to the data in the dll. Something like:
void Editor::open(void *ptr)
{
HWND parent = (HWND)ptr;
myEditorDlg = new CMyEditorDlg(CMyEditorDlg::IDD, CWnd::FromHandle(parent));
myEditorDlg->ShowWindow(SW_SHOWNORMAL);
myEditorDlg->UpdateWindow();
}
open is called by the host. On windows ptr is a HWND handle.
Mark Salsbery wrote: There's a couple important issues with this:
1) Windows messages need to get routed to the MFC message system
2) Except with an MFC extension DLL, you can't pass any MFC objects
directly or indirectly across the exe/dll boundary.
This is what I gathered from the link to the webpage you posted. But someone on another group posted code supposedly doing just that (it looks close to what I posted above). When I tried it, I thought it worked at first, but a closer look and I realized I was getting all kinds of memory errors/exceptions.
|
|
|
|
|
Does CMyEditorDlg create itself in the constructor?
If not, you're missing a create call so ShowWindow and UpdateWindow
will probably assert.
Leslie Sanford wrote: But someone on another group posted code supposedly doing just that
I'm skeptical...the window may draw initially, but how is it going to get
window messages?
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Mark Salsbery wrote: I'm skeptical...the window may draw initially, but how is it going to get window messages?
That's what I get for quoting the code from memory. Here's the actual code I'm testing. It's adapted from the post I mentioned on another forum:
bool MyAudioEditor::open(void *ptr)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
ASSERT(m_pPlugView == NULL);
m_pPlugView = new CPlugView();
systemWindow = ptr;
if(m_pPlugView->Create((UINT)CPlugView::IDD, CWnd::FromHandle((HWND)systemWindow)))
{
m_pPlugView->ShowWindow(SW_SHOWNORMAL);
return true;
}
return false;
}
|
|
|
|
|
That's cool. I still don't know how the window will receive messages
after the ShowWindow() call though
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Leslie Sanford wrote: They can be either. I have no way of knowing beforehand if a host is MFC based
In that case, an extension DLL is out. That leaves a regular DLL linked
to MFC as the only option.
Passing any MFC object across the exe/dll boundary cannot be done
(it wouldn't make sense anyway, since the host may not be using MFC).
That means message routing is going to be your problem. There will
be no message pump in the DLL. The DLL will need to create its own
UI thread, since you can't count on the host to pump messages to the DLL.
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
I want to create a application with multiple dialogs such that clicking on the first dialog lands me to the next dialog after closing the previous one..
DoModal doesnt help....as it keeps the parent dialog box open....
Plzzzzzzz help me...
It is very urgent for me.....
mitra.tamoghna@gmail.com
Tom
|
|
|
|
|
are you looking for a Wizard type CPropertySheet ?
|
|
|
|
|
Hi all. Im trying to break a server message up into segments. So i figured i could use strtok(). Problem is the sockets i have setup are defined to STL string for C++ so i cant use strtok() obviously. So i found a tokenizer from this site. But i cant seem to use it for my socket project properly.
The message looks like this:
<br />
:user.client computer1 sysinfo :sync1 smtp.startup <br />
Instead of processing the entire server message, im trying to get the last two words after the last colon (i.e. sync1 smtp.startup)
Note: I got the tokenizer from this url: http://www.codeproject.com/cpp/stringtok.asp
Any suggestions? Thanx in advance!
|
|
|
|
|
|
Thanx for the suggestion, I would try it but i cant seem to find the download link for boost/tokenizer.hpp
EDIT:
Never mind, found it :P
|
|
|
|
|
Why not simply use something like this:
---------------------------------------
// Console.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
void main()
{
string message = ":user.client computer1 sysinfo :sync1 smtp.startup";
istringstream iss(message);
string pt1, pt2, pt3, pt4, pt5;
iss >> pt1 >> pt2 >> pt3 >> pt4 >> pt5;
cout << "pt1 = " << pt1 << endl;
cout << "pt2 = " << pt2 << endl;
cout << "pt3 = " << pt3 << endl;
cout << "pt4 = " << pt4 << endl;
cout << "pt5 = " << pt5 << endl;
}
Steve
|
|
|
|
|
Did you solve your problem yet?
|
|
|
|
|
Yes thank you. Stephen Hewitt's suggestion worked out fine.
|
|
|
|
|
|
I have now downloaded two sets of the ACE TAO Corba (two different sites) for use initally with Visual Studio 2005. You seem to have to download all the source and build it. The first version built OK but something was missing; the IDL compiler did not general the required files. Is seemed that an ACEd.dll wa missing!
Start again, this time the ACE part built but about 57 projects of the TAO failed.
Can I ask where can you download a Corba environment and get it working with VS 2005, without all this hassle. After all I am only trying to 'Get Started' with Corba, not have a melt down before I try and write my first program.
PS I just opted for ACE TAO, are they a better option with some GYS notes?
Many thanks,
Andy.
|
|
|
|
|
Hi all,
I started using MAPs and STL not long ago and I still have some doubt.
I have to use the iData member of the class depicted below.
My Question is when I add new 'CStreetHouseNumber' values to iData,
where these value are stored? In the stack or in the heap?
iData is pointing a map into a heap, that is pointing another
map into the heap that is pointing a vector in the heap CONTAINING
values, but where these last values are
Thanks to everybody
Manu
class CAddressCollection
{
public:
CAddressCollection();
private:
class CStreetHouseNumber
{
public:
CStreetHouseNumber()
: iStreet(""),
iHouseNumber("")
{}
CStreetHouseNumber(string aStreet, string aHouseNumber)
: iStreet(aStreet),
iHouseNumber(aHouseNumber)
{}
string iStreet;
string iHouseNumber;
};
map<string,map<string,vector<CStreetHouseNumber>*>*>* iData;
};
|
|
|
|
|
As the maps & vectors are dynamically created, the wrapper object may be on the stack, but its data will be on the heap, as it will be dynamically allocated. And that will apply to classes allocated by dynamically allocated classes allocated by... (etc).
Iain.
|
|
|
|
|
Thank you very much for your response!
Manu
|
|
|
|