Exporting a Dialog class (w/ activex control) from a DLL explicilty

Hi,

I need to create an application that will call a dialog from a dll, in which the dialog has an embedded activex inside.

Is there someone here that knows how export a dialog class from a DLL explicitly?

Thanks,
Mhelinx

mhelinx09Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AndyAinscowFreelance programmer / ConsultantCommented:
declare your class in the dll (MFC Extension dll)
class AFX_EXT_CLASS CMyDlg : public CDialog

make this header available to your app eg.
#include "..\\ext_dll\\ext_dll_dlg.h"

Now in the app
CMyDlg dlg(this);
dlg.DoModal();
0
mhelinx09Author Commented:
Hi Andy,

In the DLL, I'm not going to use any header file. In my application, my only source is the DLL. Using LoadLibrary, I will call the global functions inside my DLL. But the problem is how about returning the dialog class since im application it is only processing function, not returing the dialog class.

I hope I did not make any confusion,
Mhelinx
0
AlexFMCommented:
Don't export the dialog class, this creates resource problems. Export ShowDialog function (global, or some class member - doesn't matter) and show dialog from it:

void CSomeClass::ShowDialog(CWnd* pParent)     // exported
{

    CMyDlg dlg(pParent);

    HINSTANCE h = AfxGetResourceHandle( );

    // set here Dll handle, this ensures that dialog template is found in current Dll resource
    AfxSetResourceHandle(hDll);                      

    dlg.DoModal();

    AfxSetResourceHandle(h);                           // restore caller's current resource handle
}
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

AlexFMCommented:
hDll is HINSTANCE hinstDLL from DllMain.
0
AndyAinscowFreelance programmer / ConsultantCommented:
Hi Alex,
What do you do if you if you want to populate the dialog with info/return info from the dialog.  
Exporting the class enables one to do that without a problem.
0
AndyAinscowFreelance programmer / ConsultantCommented:
Hi mhelinx09,
I don't think you can export a dialog class through a function.
0
mhelinx09Author Commented:
Hi guys,

How about this, I have a activex controls included in the dialog. I have no problem running one instance of the dialog. The problem is when I have two or objects of that dialog, the first is working fine but the other is not.

Any ideas?
Mhelinx
0
AlexFMCommented:
Something like this:

BOOL CSomeClass::ShowDialog(CWnd* pParent,
                                             INPUTINFO* pInputInfo,             // [in]
                                             OUTPUTINFO* pOutputInfo)       // [out]
{

    CMyDlg dlg(pParent);

    dlg.SetInputInfo(pInputInfo);
    dlg.SetOutputInfo(pOutputnfo);

    HINSTANCE h = AfxGetResourceHandle( );
    AfxSetResourceHandle(hDll);                      

    int n = dlg.DoModal();

    AfxSetResourceHandle(h);

    return ( n == IDOK );
}

where INPUTINFO, OUTPUTINFO are some structures. Dialog user [in] pInputInfo to initialize it's controls and writes to [out] pOutputnfo results of it's work.
0
AndyAinscowFreelance programmer / ConsultantCommented:
Thanks Alex.
I prefer to export the dialog directly.  I make certain resource ID's are unique when I add them (eg IDC_1_EDIT for use in dll1 ...)
0
mhelinx09Author Commented:
Hi Alex,

Sorry but I cannot understand your implementation. Is it ok if you could explain in detail. I'm just a new guy in mfc.

I give an example:
I have a start counter and a show counter in activex. Wht I want is I will create to instances of this dialog (w/ activex)

Now when these two instances are running, I will check the counter of both.

Right now, I only have instance correct since they are using on instance of the dialog (I created an instance of the dialog globally)

I hope someone could help me,
Mhelinx
0
AlexFMCommented:
Keeping unique resource ID's among different projects is not a simple task. This is not generic way, but may be good for some situations. mhelinx09 may decide what way is better.
0
mhelinx09Author Commented:
Hi guys,

Also, it is modeless dialog that's why I can create two instance of the dialog.

I hope someone can help.

Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
'Keeping unique resource ID's among different projects is not a simple task'

Create your extension dll
edit resource.h, set the _APS_NEXT_RESOURCE_VALUE etc. to start at say 10000, 11000...
use a naming convention like IDC_1_EDIT

No problems, not very difficult to do either.
0
AndyAinscowFreelance programmer / ConsultantCommented:
Hi Mhelinx,

If you use my approach you can create as many copies of the modeless dialog as you wish.

CMyDlg* pDlg1 = new CMyDlg;
pDlg1->Create(....);
pDlg1->ShowWindow(SW_SHOW);

repeat for other pDlg2, pDlg3...

0
mhelinx09Author Commented:
Hi Andy,

But the problem is I have a function that will monitor the activex control. Actually I dont need to display it. It should run w/o a dialog.

I'll show a scenario

DLL:
In global, I have a dialog instance

CmyDialog dlg

In my global function

ShowDialog
{
          if ( !IsWindow(dlg.m_hWnd) )
             dlg.Create(IDD...,Afx..)                // creation of dialog and creation of activex instance
         
           dlg.Start()                      // function inside the dialog with activex functionalities

Another Global function:

Stop
{
        dlg.stop()                         // function inside the dialog that stop the activex from running
}

My problem is if I have to instance, the second instance will not call the dlg.Create since the dialog is already initialized. Therefore, that's my error.

I hope someone can help me.

Mhelinx
0
mhelinx09Author Commented:
Hi,

My problem is if I have two instance, the second instance will not call the dlg.Create since the dialog is already called at the first instance.

Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
You only have one dlg variable - so when you call ShowDlg the second time it is already being shown.
You require something like an array of pointers of your CMyDialogs, in the ShowDlg create a new one with new, display it and return an index to the exe.
The stop requires this index to know which dlg to close down and delete.
0
mhelinx09Author Commented:
Hi Andy,

Still if I will create and instance in the ShowDialog global function, I need to create also in the "Stop" global function to call the "Dlg.Stop".

Also, I need to get the instance in the ShowDialog and use that in the Stop function.

Maybe you have some ideas how to implement it.

Thanks again for your help.
Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
CmyDialog dlg
In my global function
ShowDialog
{
          if ( !IsWindow(dlg.m_hWnd) )
             dlg.Create(IDD...,Afx..)                // creation of dialog and creation of activex instance
         
           dlg.Start()                      // function inside the dialog with activex functionalities

Another Global function:
Stop
{
        dlg.stop()                         // function inside the dialog that stop the activex from running
}


How about
CArray arDlgs;  //You will have to construct an array that can hold pointers to CWnds.

ShowDialog
{
CMyDlg *pDlg = new CMyDlg;
arDlgs.Add[pDlg];
pDlg->Create(...)
           
           pDlg->Start()                      // function inside the dialog with activex functionalities

return the index of the top of your array

Stop(int nIndex)
{
        (CMyDlg*)arDlgs[nIndex]->stop()                         // function inside the dialog that stop the activex from running
  delete arDlgs[nIndex];//clean up
}

0
mhelinx09Author Commented:
Hi Andy,
About this code:
CArray arDlgs;  //You will have to construct an array that can hold pointers to CWnds.

I think I'm just dumb not to understand this. Can you give an example.

Thanks again,
Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
Try CDWordArray

then
arDlgs.Add[pDlg];
should be
arDlgs.Add((DWORD)pDlg);
0
mhelinx09Author Commented:
Hi Andy,

It seems that your idea doesnt work or I have no idea how to implement.

I hope you can give much detail about this.

Thanks again.
Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
Implementing a modeless dialog in a dll is much more difficult than a modal dialog.
I would strongly recommend you export the class and create your modeless dialogs in the app.
0
mhelinx09Author Commented:
Hi Andy,

Can you give me a sniffet on how to export the Dialog class in a dll?

Thanks again,
Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
This was my first post in this thread

declare your class in the dll (MFC Extension dll)
class AFX_EXT_CLASS CMyDlg : public CDialog

make this header available to your app eg.
#include "..\\ext_dll\\ext_dll_dlg.h"

Now in the app
CMyDlg dlg(this);
dlg.DoModal();



For a modeless dialog you would need something like the following
CMyDlg* pDlg;
pDlg = new CMyDlg(this);
pDlg->Create(.....);
pDlg->ShowWindow(SW_SHOW);

//You could use a CDWordArray in your app as a member variable (because you wanted a number of dialogs)
m_arDlgs.Add((DWORD)pDlg);//cast the pointer to a DWORD for storage


//And when you cleanup or do something with them recast the DWORD back to a pointer
((CMyDlg*)m_arDlgs[0, 1...n])->DoSomething();

0
mhelinx09Author Commented:
Hi Andy,

It seems that I dont get your idea in exporting. Maybe my idea is not correct. How about returning the dialog class in the application?

Example:

In global function:
extern "C" __declspec(dllexport) void ReturnClass()
{

0
mhelinx09Author Commented:
Hi Andy,

It seems that I dont get your idea in exporting. Maybe my idea is not correct. How about returning the dialog class in the application?

Example:

In global function:
extern "C" __declspec(dllexport) void ReturnClass()
{
 new CMyDlg();
}

In my app:

typedef  CAbstractDlg* (* FnShowDialog)();

FnSaveDlg pfnSaveDlg;

pfnSaveDlg = (pfnSaveDlg)GetProcAddress(Hmod, TEXT("ReturnClass"));

pfnSaveDlg->Start();

But my problem is my CAbstractDlg since I dont know how will I create an abstract dialog.

I tried to create an abstract class that inherits a dialog but it is not working properly.

Do you have an idea?

Thanks again for your patience,
Mhelinx


0
AndyAinscowFreelance programmer / ConsultantCommented:
Hi mhelinx09
please could you let me have your e-mail adress, I'll create a minor proj and mail it to you tomorrow.
Mine is info@ainscow.ch if you didn't want to publicise yours here.
0
mhelinx09Author Commented:
Hi Andy,

I already learned returning the dialog from the dll. It seems that I have only one part left to do.
How to get the resource template from the dll?

I hope you have suggestions.

Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
I have tried to send you an e-mail, it got bounced back from my mail server as an invalid address.
I'll try again soon.
0
mhelinx09Author Commented:
Hi Andy,

I solved the problem. What I did is made the dialog resource ID of the DLL the same as the dialog resource ID in the application.

Right now, it running smoothly.

I'll send you my solution to you through email.

Do you think my idea is correct?

Thanks again for your effort.

Mhelinx
0
AndyAinscowFreelance programmer / ConsultantCommented:
Do you think my idea is correct?

NO!  That is a dangerous hack to make it work.
Have you got my e-mail with the attatchment - that will show you how to do it.
0
mhelinx09Author Commented:
Hi Andy,

Based on your implementation, it seems that it is implicit and I have no problem on that. My problem is explicitly linking the dll on my application and get the dialog in the dll.

Once I have the dialog object, I'll call the Create function to dynamically create the activex control.

It seems that I dont have problems with that. Right now, I can create many instances of the dialog by using the vector template and manipulate using the template.

About the resource ID, I have tried to use AfxSetResourceHandle() function just to get the resource dialog inside the dll but it doesnt work. So, what I did I made a Abstract Dialog class. This dialog uses a resource ID the same as the resource ID of the dialog inside the DLL.

That's why I dont have much problem on the implementation.

Maybe you have another approach on this. I will really gld if you can give an detailed idea on what will be my problem.

It seems that it is working pretty well.

Thanks again for your effort.
Mhelinx
0
GhostModCommented:
Closed, 200 points refunded.
GhostMod
Community Support Moderator
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.