Solved

Loading Toolbars through a DLL

Posted on 1998-05-13
6
435 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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
bobThere java chalenge 45 97
Host to IP 7 84
ShiftLeft challenge 21 95
Updating statistics with error notification email in SQL server 4 130
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…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
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.
Attackers love to prey on accounts that have privileges. Reducing privileged accounts and protecting privileged accounts therefore is paramount. Users, groups, and service accounts need to be protected to help protect the entire Active Directory …

751 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