[MFC] MFC in MFC-loze applicatie gebruiken

Pagina: 1
Acties:
  • 266 views sinds 30-01-2008
  • Reageer

Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Hallo,

Ik heb hier een Visual Studio project dat een dll genereert en tot voor kort geen gebruik maakte van MFC . Nu wil ik echter een bepaalde methode een dialoogvenstertje doen tonen .

Als ik nu gewoon met de resource editor een dialoogvenstertje aanmaak en het volgende doe:
code:
1
2
    TestDlg *test = new TestDlg();
    test->DoModal();

Dan krijg ik een ASSERT in afxwin1.inl:
code:
1
2
3
_AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle()
    { ASSERT(afxCurrentResourceHandle != NULL);
        return afxCurrentResourceHandle; }

En eigenlijk zowat alles wat ik probeer te doen ivm MFC triggert deze assert.

Ik heb al behoorlijk wat gezocht op deze fout, maar ik krijg ze niet opgelost...

Een eerste suggestie die ik heb tegengekomen is om de volgende regel toe te voegen aan het begin van de functie:
code:
1
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));

Dit veroorzaakt echter de onderstaande fout:
code:
1
2
3
1>Linking...
1>mfcs80d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in Blah.obj
1>mfcs80d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in Blah.obj


Géén idee wat die regel juist doet en waarom dit tot deze error leidt ...
Ik ben niet thuis in het het module state verhaal ...

Een tweede suggestie die ik heb tegengekomen is om een CWinApp object toe te voegen.
Aangezien mijn project echter een dll genereert is er geen WinMain methode die opgeroepen wordt om mijn CWinApp object te 'activeren' .
Bovendien lijkt me dit erg lastig te combineren met de huidige code ...

Is het sowieso mogelijk om MFC te gebruiken voor hetgeen ik wil?
Indien ja: kan er mij iemand in de richting helpen van hoe ik dit aanpak?

Bedankt!

Acties:
  • 0 Henk 'm!

  • The End
  • Registratie: Maart 2000
  • Laatst online: 14:47

The End

!Beginning

Als je een nieuw project maakt in Visual Studio, dan kan je kiezen voor een MFC dll. Als je hier gebruik van maakt, dan kan je de MFC gebruiken in een DLL.

Anders moet je zonder de MFC een dialog maken...

Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Ik dacht dat die setting ervoor zorgde dat gewoon de optie 'Use MFC in a Shared DLL' gebruikt werd en er wat basiscode gegenereerd werd ...

Maar in ieder geval, het dialoogvenstertje móet echt wel in de huidige code komen.
Er moet toch een manier zijn om alles te initialiseren wat MFC nodig heeft zodat dit kan?

Acties:
  • 0 Henk 'm!

  • The End
  • Registratie: Maart 2000
  • Laatst online: 14:47

The End

!Beginning

Ja, dan moet je alle code overnemen van een leeg MFC dll project. :)

Het is trouwens niet zoveel:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
header:

class CMijnDLL: public CWinApp
{
public:
   CMijnDLL();

   virtual BOOL InitInstance();
   virtual int ExitInstance();

   DECLARE_MESSAGE_MAP()
};

cpp:

BEGIN_MESSAGE_MAP(CMijnDLL, CWinApp)
END_MESSAGE_MAP()

CMijnDLL::CMijnDLL()
{

}

CMijnDLL theApp;

BOOL CMijnDLL::InitInstance()
{
   COleObjectFactory::RegisterAll();

   return TRUE;
}

STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   return AfxDllGetClassObject(rclsid, riid, ppv);
}

STDAPI DllCanUnloadNow()
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   return AfxDllCanUnloadNow();
}

STDAPI DllRegisterServer()
{
   AFX_MANAGE_STATE(AfxGetStaticModuleState());
   COleObjectFactory::UpdateRegistryAll();
   return S_OK;
}

int CMijnDLL::ExitInstance()
{
   return CWinApp::ExitInstance();
}

[ Voor 88% gewijzigd door The End op 15-05-2006 16:31 ]


Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Lijkt doenbaar en te combineren met wat er nu is ...
Ik smijt mij er even op!

Bedankt in ieder geval al, I'll keep you posted!

Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 18-07 09:02
Voor een enkel dialoogvenster zou ik geen MFC dependency erbij plempen eigenlijk.

[ Voor 5% gewijzigd door farlane op 15-05-2006 16:44 ]

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Het moet uiteindelijk een soort propertysheet ding worden waaraan dynamisch property pages kunnen toegevoegd worden.
MFC heeft daar de klassen CPropertySheet en CPropertyPage voor die perfect zouden moeten doen wat ik wil. Ik zie dat niet echt zitten om dat helemaal in Win32 API aan te maken ...

Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
De enige error die ik nu nog krijg is de volgende:

code:
1
2
1>Linking...
1>mfcs80ud.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in TranscoderFilter.obj

Als ik mijn DllMain methode wegcommentariëer dan kan ik de linker error doen verdwijnen,
naar dan faalt het registreren van mijn filter met een ASSERT in AMovieDllRegisterServer2() ...

Ik ben er bijna ... Ideeën?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:00

.oisyn

Moderator Devschuur®

Demotivational Speaker

Denk even na wat er precies gebeurt :)

De dll die je aan het aanpassen bent heeft al een DllMain. Nou is er voor MFC ook wat code nodig die uitgevoerd moet worden in de DllMain, en standaard komt ie dus met z'n eigen DllMain. Dat conflicteert natuurlijk, je kunt niet 2 functies met dezelfde naam hebben. Je zal dus op de een of andere manier de code van MFC's DllMain en de DllMain van je project moeten mergen. Maar dat wordt wat lastig, aangezien MFC's DllMain in de runtime gebakken zit.

Je moet dus wat meer moeite doen, en daarvoor is dit stukje uit de MSDN relevant:
The C/C++ run-time library code performs the DLL startup sequence, eliminating the need to link with a separate module as was necessary in Windows 3.x. Included in the C/C++ run-time library code is the DLL entry-point function called _DllMainCRTStartup. The _DllMainCRTStartup function does several things, including calling _CRT_INIT, which initializes the C/C++ run-time library and invokes C++ constructors on static, non-local variables. Without this function, the run-time library would be left in an uninitialized state. _CRT_INIT is available for both a statically-linked CRT, or linking to the CRT DLL msvcrt.dll, from a user DLL.

While it is possible to specify another entry-point function using the /ENTRY: linker option, it is not recommended because your entry-point function would have to duplicate everything that _DllMainCRTStartup does. When building DLLs in Visual C++, _DllMainCRTStartup is linked in automatically and you do not need to specify an entry-point function using the /ENTRY: linker option.
Met de /ENTRY linker optie kun je namelijk een ander entrypoint specificeren, zodat je vanuit die functie zelf _DllMainCRTStartup aan kunt roepen (die weer MFC's DllMain aanroept), zodat je daarna je eigen DllMain, die je dan een andere naam hebt gegeven, aan kunt roepen. Maar dit vereist wel wat onderzoek naar de specifieke calling conventie van _DllMainCRTStartup, en de benodigde parameters die je aan DllMain moet geven.

Maar een veel makkelijkere optie is wellicht gewoon een compleet nieuwe MFC-enabled dll te maken, en die vanuit je huidige dll te laden :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • ReverendBizarre
  • Registratie: December 2001
  • Laatst online: 24-03-2021
Wellicht is WTL een optie. WTL is een wrapper om het win32 API heen en bevat veel control wrappers die erg veel lijken op de MFC equivalenten. Het is ook gewoon van MS afkomstig dus geen third party library ofzoiets. Nadeel is dat WTL compleet unsupported is, dus buiten de artikelen op de site hieronder is er weinig over te vinden. Voordeel is echter weer dat het wel helemaal opensource is en je dus wel weer de mogelijkheid hebt om zelf dingen uit te zoeken indien nodig.

http://www.codeproject.com/wtl/WTL4MFC8.asp (of http://www.codeproject.com/wtl/ voor meer handige WTL artikelen zoals waar te vinden, hoe te installeren, etc.)

Het is gewoon een dunne wrapper en dus niet zoiets als MFC waar je heen hele berg meuk erbij hoeft te trekken voordat je het kan gebruiken (MFC werkend krijgen in een applicatie die niet als MFC applicatie is opgezet is zoals je waarschijnlijk al gemerkt hebt nogal een gedoe).

Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Klinkt interessant, maar het doel van dit hele ding is ook om wat met MFC te leren werken eigenlijk.
Ik zou het dus wel echt graag met MFC werkende krijgen...

Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Ik heb nu een nieuwe MFC Extension DLL aangemaakt en daar mijn code ingezet, en wééral klaagt 'm over die _DllMain@12 already defined ...
Maar de DllMain methode die ik nu heb is aangemaakt door de projectwizard zelf!
Een 'vers' MFC Extension DLL project compileert nochtans wel...
Uitzoeken wat het precies is dat ik toevoeg dat de boel verziekt dus maar ...

Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Ok ik heb het gevonden.
Ik heb de error kunnen terugtracen naar 1 lijntje in de DllRegisterServer() methode, namelijk:
code:
1
    AFX_MANAGE_STATE(AfxGetStaticModuleState());


Ik had dit toegevoegd omdat ik dacht dat dat misschien de oplossing tot mijn problemen kon zijn op een bepaald punt, en blijkbaar impliceert dat dus een extra DllMain definitie of zo ...
Het lijntje verwijderen zorgt ervoor dat mijn project nu eindelijk compileert! Johei!

Edit: Werken is een ander zaak ...
Als ik de boel nu even debug tijdens een "regsvr32 mijn.dll", dan wordt eerst de DllMain() methode opgeroepen, daarna de DllRegisterServer() methode die door AMovieDllRegisterServer2() op te roepen blijkbaar een nieuwe DllMain() oproep tot gevolg heeft.
Waarna een assert gegenereerd wordt in AMovieDllRegisterServer2() ...
Diepe zucht ...

Die assert gebeurt omdat DllEntryPoint niet opgeroepen is in mijn DllMain methode,
maar een DllEntryPoint oproep moet alleen bij de initialisatie van een niet-MFC DLL volgens MSDN ...

Edit2: DllEntryPoint() oproep toegevoegd aan DllMain en dat lijkt te werken...
CDialog.DoModal() geeft echter een assert ... Grr ...
Het heeft zeker iets te maken met die module state, maar ik snap het niet genoeg om het uit te kunnen dokteren.
Volgens mij zou die AFX_MANAGE_STATE(AfxGetStaticModuleState()); de boel wel moeten oplossen, maar die genereert dan die linker error ... Waarom.??

[ Voor 58% gewijzigd door DieterVDW op 16-05-2006 16:02 ]


Acties:
  • 0 Henk 'm!

  • DieterVDW
  • Registratie: Juli 2002
  • Laatst online: 12-02-2017
Na nog heel wat research vraag ik mij toch af of het wel mogelijk is om DirectShow en MFC te combineren ...

Als ik ga voor een MFC Extension DLL, dan kun je de MFC-enabled functies uit de DLL niet of nauwelijks gebruiken vanuit een niet-MFC applicatie.
Ik kan er niet vanuit gaan dat elke DirectShow applicatie MFC enabled is, dus die mogelijkheid wordt geschrapt.

Als ik ga voor een MFC Regular DLL, dan wordt de DllMain() functie verzorgd door MFC.
Voor DirectShow is het echter vereist dat de DirectShow implementatie van DllMain (DllEntryPoint) ook wordt opgeroepen. Dit is bij mijn weten niet mogelijk of zeer moeilijk.
Initialisatie moet in theorie gebeuren in de CWinApp::InitInstance() methode die door MFC's DllMain() wordt opgeroepen. Die methode krijgt echter niet de nodige parameters die nodig zijn voor een DllEntryPoint() oproep. Zonder een DllEntryPoint() oproep in DllMain() valt de DLL niet te registreren door regsvr32.exe .

Mijn laatste optie: zoals .oisyn suggereerde een volledig aparte MFC-enabled dll maken die het GUI gedeelte van de filter afhandelt ... Ik hoop dat dat lukt ...
Pagina: 1