Solved

Loading Toolbars through a DLL

Posted on 1998-05-13
6
442 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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

Database Solutions Engineer FAQs

In this series, we will discuss common questions received as a database Solutions Engineer at Percona. In this role, we speak with a wide array of MySQL and MongoDB users responsible for both extremely large and complex environments to smaller single-server environments.

Question has a verified solution.

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

Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
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.
Visualize your data even better in Access queries. Given a date and a value, this lesson shows how to compare that value with the previous value, calculate the difference, and display a circle if the value is the same, an up triangle if it increased…

624 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