// (c) R.I.Allen 2002
// You may use this code in anyway that you feel, no guarantees or waranties are implied
// please keep all headers with any source used.
//
// PlugInLibrary.cpp : Defines the initialization routines for the DLL.
//
#include "stdafx.h"
#include <afxdllx.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
static AFX_EXTENSION_MODULE PlugInLibraryDLL = { NULL, NULL };
extern "C" int APIENTRY
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
// Remove this if you use lpReserved
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("PLUGINLIBRARY.DLL Initializing!\n");
// Extension DLL one-time initialization
if (!AfxInitExtensionModule(PlugInLibraryDLL, hInstance))
return 0;
// Insert this DLL into the resource chain
// NOTE: If this Extension DLL is being implicitly linked to by
// an MFC Regular DLL (such as an ActiveX Control)
// instead of an MFC application, then you will want to
// remove this line from DllMain and put it in a separate
// function exported from this Extension DLL. The Regular DLL
// that uses this Extension DLL should then explicitly call that
// function to initialize this Extension DLL. Otherwise,
// the CDynLinkLibrary object will not be attached to the
// Regular DLL's resource chain, and serious problems will
// result.
new CDynLinkLibrary(PlugInLibraryDLL);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("PLUGINLIBRARY.DLL Terminating!\n");
// Terminate the library before destructors are called
AfxTermExtensionModule(PlugInLibraryDLL);
}
return 1; // ok
}
// this code was taken from the article
// http://www.codeproject.com/menu/mergemenu.asp
// by Oskar Wieland (http://www.codeproject.com/script/profile/whos_who.asp?id=23357)
bool _PLUGIN_API PIMergeMenu(CMenu * pMenuDestination, const CMenu * pMenuAdd, bool bTopLevel /*=false*/)
{
// Abstract:
// Merges two menus.
//
// Parameters:
// pMenuDestination - [in, retval] destination menu handle
// pMenuAdd - [in] menu to merge
// bTopLevel - [in] indicator for special top level behavior
//
// Return value:
// <false> in case of error.
//
// Comments:
// This function calles itself recursivley. If bTopLevel is set to true,
// we append popups at top level or we insert before <Window> or <Help>.
// get the number menu items in the menus
int iMenuAddItemCount = pMenuAdd->GetMenuItemCount();
int iMenuDestItemCount = pMenuDestination->GetMenuItemCount();
// if there are no items return
if( iMenuAddItemCount == 0 )
return true;
// if we are not at top level and the destination menu is not empty
// -> we append a seperator
if( !bTopLevel && iMenuDestItemCount > 0 )
pMenuDestination->AppendMenu(MF_SEPARATOR);
// iterate through the top level of
for( int iLoop = 0; iLoop < iMenuAddItemCount; iLoop++ )
{
// get the menu string from the add menu
CString sMenuAddString;
pMenuAdd->GetMenuString( iLoop, sMenuAddString, MF_BYPOSITION );
// try to get the submenu of the current menu item
CMenu* pSubMenu = pMenuAdd->GetSubMenu(iLoop);
// check if we have a sub menu
if (!pSubMenu)
{
// normal menu item
// read the source and append at the destination
UINT nState = pMenuAdd->GetMenuState( iLoop, MF_BYPOSITION );
UINT nItemID = pMenuAdd->GetMenuItemID( iLoop );
if( pMenuDestination->AppendMenu( nState, nItemID, sMenuAddString ))
{
// menu item added, don't forget to correct the item count
iMenuDestItemCount++;
}
else
{
TRACE( "MergeMenu: AppendMenu failed!\n" );
return false;
}
}
else
{
// create or insert a new popup menu item
// default insert pos is like ap
int iInsertPosDefault = -1;
// if we are at top level merge into existing popups rather than
// creating new ones
if( bTopLevel )
{
ASSERT( sMenuAddString != "&?" && sMenuAddString != "?" );
CString sAdd( sMenuAddString );
sAdd.Remove('&'); // for comparison of menu items supress '&'
bool bAdded = false;
// try to find existing popup
for( int iLoop1 = 0; iLoop1 < iMenuDestItemCount; iLoop1++ )
{
// get the menu string from the destination menu
CString sDest;
pMenuDestination->GetMenuString( iLoop1, sDest, MF_BYPOSITION );
sDest.Remove( '&' ); // for a better compare (s.a.)
if( sAdd == sDest )
{
// we got a hit -> merge the two popups
// try to get the submenu of the desired destination menu item
CMenu* pSubMenuDest = pMenuDestination->GetSubMenu( iLoop1 );
if( pSubMenuDest )
{
// merge the popup recursivly and continue with outer for loop
if( !PIMergeMenu( pSubMenuDest, pSubMenu, false ))
return false;
bAdded = true;
break;
}
}
// alternativ insert before <Window> or <Help>
if( iInsertPosDefault == -1 && ( sDest == "Window" || sDest == "?" || sDest == "Help" ))
iInsertPosDefault = iLoop1;
}
if( bAdded )
{
// menu added, so go on with loop over pMenuAdd's top level
continue;
}
}
// if the top level search did not find a position append the menu
if( iInsertPosDefault == -1 )
iInsertPosDefault = pMenuDestination->GetMenuItemCount();
// create a new popup and insert before <Window> or <Help>
CMenu NewPopupMenu;
if( !NewPopupMenu.CreatePopupMenu() )
{
TRACE( "MergeMenu: CreatePopupMenu failed!\n" );
return false;
}
// merge the new popup recursivly
if( !PIMergeMenu( &NewPopupMenu, pSubMenu, false ))
return false;
// insert the new popup menu into the destination menu
HMENU hNewMenu = NewPopupMenu.GetSafeHmenu();
if( pMenuDestination->InsertMenu( iInsertPosDefault,
MF_BYPOSITION | MF_POPUP | MF_ENABLED,
(UINT)hNewMenu, sMenuAddString ))
{
// don't forget to correct the item count
iMenuDestItemCount++;
}
else
{
TRACE( "MergeMenu: InsertMenu failed!\n" );
return false;
}
// don't destroy the new menu
NewPopupMenu.Detach();
}
}
return true;
}
bool _PLUGIN_API PIMergeAccelerator(HACCEL& hDestination, HACCEL hToMerge)
{
// this function merges the hToMerge accelerator table with that of hDestination
ASSERT(hToMerge) ;
int original_count = 0 ;
int add_count ;
if (hDestination != NULL)
{
// we have an existing table
original_count = CopyAcceleratorTable(hDestination, NULL, 0) ;
}
add_count = CopyAcceleratorTable(hToMerge, NULL, 0) ;
if (add_count > 0)
{
ACCEL *pElements = new ACCEL[original_count + add_count] ;
// copy in the existing data if it exists
if (hDestination != NULL)
CopyAcceleratorTable(hDestination, pElements, original_count) ;
// now add in the merge accelerator
CopyAcceleratorTable(hToMerge, &pElements[original_count], add_count) ;
HACCEL hNew = CreateAcceleratorTable(pElements, original_count + add_count) ;
DestroyAcceleratorTable(hDestination) ; // because it gets replaced
hDestination = hNew ;
delete []pElements ;
return true ;
}
return false ;
}