Loading Toolbars through a DLL



This is a little lengthy, but its very urgent for me...

WHAT I AM TRYING TO ACHIEVE:
I have a MFC application with a default toolbar. I want to load an extra toolbar when a user selects a menu item. This toolbar is created and loaded through a function implemented in a separate DLL. This DLL itself is dynamically loaded on selecting the menu item.

PROBLEM:
The toolbar is not being created. I get assertion failure on call pNewToolbar->Create().

CODE:
1. The menu item command handler:

void CMyView::OnViewNewtoolbar()
{
CFrameWnd *pMainFrameWnd = (CFrameWnd *)GetParent();

//Load the DLL
HINSTANCE hLib = LoadLibrary("D:\\tmp\\NewToolbar.dll");

//function pointer declaration
BOOL (*CreateNewTB)(CFrameWnd *);

//Get the pointer to the function which creates toolbar
CreateNewTB =(BOOL (*)(CFrameWnd *))GetProcAddress(hLib,"CreateNewTB");

//Call the function to create a new toolbar
CreateNewTB(pMainFrameWnd);
}

2. The CreateNewTB() function in NewToolBar.dll

BOOL CreateNewTB(CFrameWnd *pMainFrameWnd)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));

//Create toolbar object
CToolBar *pNewToolBar = new CToolBar;

pNewToolBar->Create(pMainFrameWnd); //ASSERTION FAILURE AT THIS POINT
pNewToolBar->LoadToolBar(IDR_TOOLBAR1);

pNewToolBar->EnableDocking(CBRS_ALIGN_ANY);
pMainFrameWnd->EnableDocking(CBRS_ALIGN_ANY);
pMainFrameWnd->DockControlBar(pNewToolBar);

return TRUE;
}

OBSERVATION:
I found that functions like AfxGetMainWnd(), AfxGetInstanceHandle() fails in the Create() call by giving an assertion failure.

ANY SOLUTIONS/SUGGESTIONS ?

Thank you
Prashanth


fidodidoAsked:
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.

galkinCommented:
Actually CWnd* pointers as well as pointers to other MFC classes can be passed to MFC extension DLLs onlly not to shared DLL. Shared DLL has its own MFC internal state and global data like global map connecting HWND to CWnd. so when you pass CWnd pointer and this pointer is used by either MFC function first it is tested with ASSERT_VALID that in turn looks into permamnent and temporary MFc maps and doesn't find this object and asserts. MFC extension DLL uses internal state of application(that's why it can be used only by MFC EXE). you have to choices, one is to convert your DLL to MFC extension DLL, second - is to pas HWND object as parent toolbar window and inside DLL use CWnd::FromHandle to create temporary object and attache to HWND.
Also when loading resources you must set resource handle with AfxSetResourceHandle in MFC extension DLL and explicity specify resource handle when using shared DLL
0
fidodidoAuthor Commented:
Hi galkin, thanks for your suggestion!
   
But I am not fully clear about the second suggestion you have given. Can you be more specific, like giving an example?


0
galkinCommented:
Try to change parameter passed to CreateNewTB from Cwnd* or CFrameWnd* to HWND and inside this function in DLL call CWnd::FromHandle passing HWND parameter. Not that class you get by such a way will differ from that you have in application. Only m_hWnd member will be the same so if you want to access data member from your application frame class you must use MFC extension DLL
0
Cloud Class® Course: Microsoft Windows 7 Basic

This introductory course to Windows 7 environment will teach you about working with the Windows operating system. You will learn about basic functions including start menu; the desktop; managing files, folders, and libraries.

fidodidoAuthor Commented:
hi galkin,

I am still facing problems.
As you said I modified my application as follows.

CMyView :: OnNewToolBar()
{ .......
  CreateNewTB(GetParent()->m_hWnd);
}

BOOL CreateNewTB(HWND hParent)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));

//Create toolbar object
CToolBar *pNewToolBar = new CToolBar;

CFrameWnd *pParent = (CFrameWnd *)CWnd::FromHandle(hParent);

pNewToolBar->Create(pParent);  
pNewToolBar->LoadToolBar(IDR_TOOLBAR1);
pNewToolBar->EnableDocking(CBRS_ALIGN_ANY);
.....
}

This doesn't work since EnableDocking() expect CFrameWnd as the parent of CToolBar which in this case is not, since FromHandle() returns  CWnd object ! EnableDocking() gives ASSERTION FAILURE !

I tried another method:

BOOL CreateNewTB(HWND hParent)
{ .........
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));

//Create toolbar object
CToolBar *pNewToolBar = new CToolBar;

CFrameWnd *pParent = new CFrameWnd;
pParent->Attach(hParent);

pNewToolBar->Create(pParent);  
pNewToolBar->LoadToolBar(IDR_TOOLBAR1);
pNewToolBar->EnableDocking(CBRS_ALIGN_ANY);

.......
}
 
In this case no assertion failures occurs but toolbar does not appear on the screen. Even I tried to call
pNewToolBar->ShowWindow(SW_SHOWNORMAL).

Please HELP!
0
galkinCommented:
I mentioned that you cannot access CFrameWnd class members other then m_hWnd since FromHandle is static CWnd class function that will create temporary CWnd object. In your case you must use MFC extension DLL. Moreover it will reduce size of your DLL and increase performance since your DLL also uses MFC. See online documentation about how to convert shared DLL to MFC extension DLL
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
fidodidoAuthor Commented:
That is GREAT! I converted it into extension DLL and it worked perfectly.

Thank you for such a speedy response and the patience you have shown for my repeated queries.

I am very happy and now its 11:50pm and I can go home !!!
0
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.