Solved

Loading Toolbars through a DLL

Posted on 1998-05-13
6
427 Views
Last Modified: 2013-11-20


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


0
Comment
Question by:fidodido
  • 3
  • 3
6 Comments
 
LVL 7

Expert Comment

by:galkin
ID: 1310484
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
 

Author Comment

by:fidodido
ID: 1310485
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
 
LVL 7

Expert Comment

by:galkin
ID: 1310486
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
Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

 

Author Comment

by:fidodido
ID: 1310487
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
 
LVL 7

Accepted Solution

by:
galkin earned 150 total points
ID: 1310488
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
 

Author Comment

by:fidodido
ID: 1310489
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

Featured Post

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Hints for the grid button.  Nested classes, templated collections.  Squash that darned bug! Continuing from the sixth article about sudoku.   Open the project in visual studio. First we will finish with the SUD_SETVALUE messa…
Introduction: The undo support, implementing a stack. Continuing from the eigth article about sudoku.   We need a mechanism to keep track of the digits entered so as to implement an undo mechanism.  This should be a ‘Last In First Out’ collec…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Although Jacob Bernoulli (1654-1705) has been credited as the creator of "Binomial Distribution Table", Gottfried Leibniz (1646-1716) did his dissertation on the subject in 1666; Leibniz you may recall is the co-inventor of "Calculus" and beat Isaac…

785 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question