Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

BCGToolControlBar Extension Sample

0.00/5 (No votes)
2 May 2001 2  
An extension for Stas Levin's excellent toolbar library.

Sample Image - SkinPage.gif

The BCGToolbar Library

This article is written as an extension to an excellent toolbar library written by Stas Levin. This article is written with version 5.2 of the library, but take a look at the BCGSoft website for the latest version. I will not get into how you use and install the library. This article describes how to add a custom page to the Customisation dialog box, which is displayed when you right click on a toolbar or menu and choose "Customize...�. The sample program is based on the sample "CustomPages", which comes with the library. Parts of the code are also based on the BCGSkins sample, which demonstrates how to add skins to your application with the BCGControlBar library. I will not describe the CSkinPage class in detail, but rather describe how to use it.

Getting started

Use an existing BCGControlBar application or create a new application using the application wizard. Copy the following files to your application directory from the sample project:

  • Macstyle.*
  • Funnystyle.*
  • MyVisualManager.*
  • SkinPage.*

Also add the necessary resources from the .RC file.

The CSkinPage class

The page to be added is a CPropertyPage derivative called CSkinPage. It extends CPropertyPage with the methods AddSkin() and SelectSkin().

void AddSkin(LPCSTR szName, LPCSTR szDescription, UINT nIDBitmapPreview);

Return Value

none

Parameters

  • szName

    The name of the skin as it is displayed in the list.

  • szDescription

    A short description of the skin, that is displayed below the list with available skins.

  • nIDBitmapPreview

    A bitmap resource to be displayed as a preview when the skin is selected from the list.

Remarks

You may omit the preview by setting nIDBitmapPreview to 0. This way no preview is displayed but you will still be able to see a real-time preview of the change in the actual application.

The bitmap resource should be 256 colors and is fully palette aware.

void SelectSkin(int iSkin); 

Return Value

none

Parameters

  • iSkin

    Index of the skin in the list that should be initially selected.

Remarks

none

1. Adding the custom page

In CMainFrame::OnViewCustomize(), insert this code that will be executed when you choose to customize the toolbars and menus.

CList  lstCustomPages;
lstCustomPages.AddTail (RUNTIME_CLASS (CSkinPage));
//------------------------------------

// Create a customize toolbars dialog:

//------------------------------------

CBCGToolbarCustomize* pDlgCust = new CBCGToolbarCustomize (this,
  TRUE /* Automatic menus scaning */,
  BCGCUSTOMIZE_MENU_SHADOWS | BCGCUSTOMIZE_TEXT_LABELS |
  BCGCUSTOMIZE_LOOK_2000 | BCGCUSTOMIZE_MENU_ANIMATIONS, // default parameters

  &lstCustomPages); // pointer to the list of runtime

                    // classes of the custom property pages

 
pDlgCust->Create ();
 
// Very ugly cast!!!

CMyBCGToolbarCustomize* pTemp = (CMyBCGToolbarCustomize*)pDlgCust;
 
// Get a ptr to the skinpage and add some skins

CSkinPage* pSkinPage = DYNAMIC_DOWNCAST(CSkinPage, 
         pTemp->GetCustomPageList()->GetHead());
pSkinPage->AddSkin("Office XP", "The new Windows look", IDB_PREVIEW2);
pSkinPage->AddSkin("Mac", 
  "That ol\' mac style. For people that just can't let go :-)", 
  IDB_PREVIEW1);
pSkinPage->AddSkin("Stas on mushrooms", 
  "A weird and strange windows look, "
  "that you propably won't stand for long", IDB_PREVIEW3);
 
 
int iSelectedSkin = theApp.GetInt("ActiveSkin", 0);
pSkinPage->SelectSkin(iSelectedSkin);

The interesting part is the last lines where you add the actual pages and select one of them as the active one. Notice that the active skin index is read from the registry - I will get back to that later.

You may see that I do a dirty cast from the CBCGToolbarCustomize class that is created, to my own class CMyBCgToolbarCustomize, which derives from CBCGToolbarCustomize. The reason I do that, is because I need to access one of the protected members of the class. Since I'm not able to change the original source code of the library, I'm forced to do something like that.

If you insert this code and choose "Customize...", you will be able to see a new page among the well-known BCGToolbar pages. You can play around with it and see that it actually displays a preview and a description for each entry in the list - but nothing much else happens.

2. Adding skin support

Add a new member function to you application class to take care of the skins. I have taken the SetSkin() function from the BCGSkins sample that comes with the library, and modified it a bit.

void CCustomPagesApp::SetSkin(int iIndex)
{
    if (CBCGVisualManager::GetInstance () != NULL)
    {
        delete CBCGVisualManager::GetInstance ();
    }
 
    switch (iIndex)
    {
    case 0:
        CBCGVisualManager::GetInstance ();
        break;
 
    case 1:
        new CMyVisualManager ();
        break;
 
    case 2:
        new CMacStyle ();
        break;
 
    case 3:
        new CFunnyStyle ();
        break;
    }
 
    CBCGVisualManager::GetInstance ()->SetLook2000 ();
    CBCGVisualManager::GetInstance ()->RedrawAll ();
 
    // Store the index of the active skin

    WriteInt("ActiveSkin", iIndex);
}

On the last line, the index of the last used skin is written to the registry. This is the value that is used in CMainFrame::OnViewCustomize().

When you use skins, you should be aware that you release any resources allocated on the fly. Refer to the BCGSkins sample for further information. Also make sure that the right header files are included so the application compiles.

In you application class InitInstance(), you should add the following code just before showing the main window.

// Set the skin that is active right now

int iSelectedSkin = GetInt("ActiveSkin", 0);
SetSkin(iSelectedSkin);

This code will make sure that it is the right skin that is selected on start up.

3. Connecting

Now we will connect the customisation page and the application class so the right skin will be activated. As an added bonus, we will get a real-time preview in the application window itself.

Each time you select another skin in the list, a registered Windows message is fired to the main window of the application. To handle this message, add a ON_REGISTERED_MESSAGE() handler to the message map of CMainFrame. I have called the function OnNewSkin(). Below is the implementation.

// Message handler for the BCGM_NEWSKIN message sent from the CSkinPage

LRESULT CMainFrame::OnNewSkin(WPARAM wp,LPARAM lp)
{
    int iSkindex = wp;
    ASSERT(iSkindex>=0);
 
    CCustomPagesApp* pApp = (CCustomPagesApp*)AfxGetApp();
    ASSERT_VALID(pApp);

    pApp->SetSkin(iSkindex);
 
    return 0;
}

This function does not do anything interesting. The index of the selected skin comes in from the WPARAM parameter and is transferred directly to the SetSkin() function in the application class. Make sure that the order in which you add the skins to the list is exactly the same as the order in which the index is handled in SetSkin() - starting from one, since the first entry always is "<no skin>".

That's it! Go ahead and try it out. If you are not familiar with the BCGControlBar library, go ahead and download a copy. The library is free to use for freeware development, and quite inexpensive for commercial applications, compared to similar libraries like the ones from Stingray and Dundas. Keep up the good work Stas!!

Please note that I'm not in any way connected to BCGSoft, other than I use the library in my daily work.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here