Link to home
Start Free TrialLog in
Avatar of fidodido
fidodido

asked on

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


Avatar of galkin
galkin

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
Avatar of fidodido

ASKER

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?


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
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!
ASKER CERTIFIED SOLUTION
Avatar of galkin
galkin

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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 !!!