Click here to Skip to main content
15,897,371 members
Articles / Desktop Programming / ATL

Docking ActiveX Controls: Principles and Implementation

Rate me:
Please Sign up or sign in to vote.
4.82/5 (7 votes)
28 Aug 200115 min read 183.9K   2.9K   82  
The article decribes how to implement docking ActiveX control using MFC and ATL
////////////////////////////////////////////////////////////////
// Copyright 1999-2001 Dmitri Sviridov, ActiveXStore.com
// 
//
// BaseFrame.cpp : implementation file
//

#include "stdafx.h"
#include <afxpriv.h>
#include "resource.h"
#include "BaseFrame.h"

#include "CuteBar.h"
#include "CToolBar.h"
#include "CMenuBar.h"


#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CBCBaseFrame

IMPLEMENT_DYNCREATE(CBCBaseFrame, CFrameWnd)

CBCBaseFrame::CBCBaseFrame()
{
    m_pCtrl = NULL;
//	m_pParentWnd = NULL;
    m_pwndActvMenuBar = NULL;
//    m_pwndStatusBar = NULL;
}

CBCBaseFrame::CBCBaseFrame(CICuteBar* pCtrl)
{
    m_pCtrl = pCtrl;
//	m_pParentWnd = NULL;

    m_pwndActvMenuBar = NULL;
//    m_pwndStatusBar = NULL;
}

CBCBaseFrame::~CBCBaseFrame()
{
}
BEGIN_MESSAGE_MAP(CBCBaseFrame, CFrameWnd)
	//{{AFX_MSG_MAP(CBCBaseFrame)
	ON_WM_ERASEBKGND()
	ON_WM_TIMER()
	ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
	ON_WM_INITMENUPOPUP()
	ON_WM_SIZE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

static UINT indicators[] =
{
	ID_SEPARATOR,           // status line indicator
	ID_INDICATOR_CAPS,
	ID_INDICATOR_NUM,
	ID_INDICATOR_SCRL,
};

/////////////////////////////////////////////////////////////////////////////
// CBCBaseFrame message handlers


BOOL CBCBaseFrame::OnEraseBkgnd(CDC* pDC) 
{
	if ( m_pCtrl->m_bMDI)
    {
		RecalcLayout();
    }
    Default(); 
	return TRUE;//CFrameWnd::OnEraseBkgnd(pDC);

	// TODO: Add your message handler code here and/or call default
    if (m_pCtrl)
    {
       OLE_COLOR BackColor;
       HRESULT hr=m_pCtrl->GetAmbientBackColor(BackColor);
       COLORREF cr = RGB(0x00,0x00,0x00);
       ::OleTranslateColor(BackColor, NULL, &cr);

       CBrush brAmbientBack(cr);
       pDC->FillRect(&m_pCtrl->m_rcPos, &brAmbientBack);
    }
}

BOOL CBCBaseFrame::Create(DWORD dwExStyle, LPCTSTR lpszClassName,
    LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect,
    CWnd* pParentWnd, UINT nID, LPVOID lpParam )
{
	BOOL ret = SubclassWindow(pParentWnd->m_hWnd);
    if (ret)
	{
        EnableDocking(CBRS_ALIGN_ANY);
        // Set timer for OnIdle emulatation 
	    SetTimer(1, 100, NULL);
	}
	return ret;
}

void CBCBaseFrame::OnTimer(UINT nIDEvent) 
{
#ifdef SDS
    CICuteBar* pCuteBar = m_pCtrl;
    ASSERT(pCuteBar);
    if( pCuteBar->m_spClientSite && pCuteBar->m_pInPlaceSite)
    {
        RECT rcPos, rcClip;
        CComPtr<IOleInPlaceFrame> spInPlaceFrame;
        CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
        OLEINPLACEFRAMEINFO frameInfo;
	    frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);

		pCuteBar->m_pInPlaceSite->GetWindowContext(&spInPlaceFrame,
			&spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
       CComPtr<IOleInPlaceActiveObject> spActiveObject;
       pCuteBar->ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject);
// Reserved for accel proccesing
        if (spInPlaceFrame)
        {
         HRESULT hr = spInPlaceFrame->SetActiveObject(spActiveObject, NULL);
//			CComQIPtr<IOleControlSite, &IID_IOleControlSite> spSite(m_spClientSite);
//			if (spSite != NULL)
//				spSite->LockInPlaceActive(TRUE);
        }
//         if (spInPlaceUIWindow)
//             spInPlaceUIWindow->SetActiveObject(spActiveObject->p, NULL);
    }
#endif
    CWinApp * pApp= AfxGetApp();
	pApp->CWinThread::OnIdle(0);
    return;
	
//	CBCBaseFrame::OnTimer(nIDEvent);
}

void CBCBaseFrame::Unload()
{
    DestroyControlBars();
	KillTimer(1);
	UnsubclassWindow();
}

BOOL CBCBaseFrame::ShowControlBars(BOOL bShow)
{
	ASSERT_VALID(this);

	// show/hide all bars marked with CBRS_HIDE_INPLACE style
	BOOL bResult = FALSE;
	if (bShow)
	{
		POSITION pos = m_listControlBars.GetHeadPosition();
		while (pos)
		{
			CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
			ASSERT_VALID(pBar);
			if ((pBar->GetBarStyle() & CBRS_HIDE_INPLACE) &&
				(pBar->m_nStateFlags & CControlBar::tempHide))
			{
				pBar->m_nStateFlags &= ~CControlBar::tempHide;
				ShowControlBar(pBar, TRUE, TRUE);
				bResult = TRUE;
			}
		}
	}
	else
	{
		POSITION pos = m_listControlBars.GetHeadPosition();
		while (pos)
		{
			CControlBar* pBar =	(CControlBar*)m_listControlBars.GetNext(pos);
			ASSERT_VALID(pBar);
			if (pBar->IsVisible() && (pBar->GetBarStyle() & CBRS_HIDE_INPLACE))
			{
				pBar->m_nStateFlags |= CControlBar::tempHide;
				ShowControlBar(pBar, FALSE, TRUE);
				bResult = TRUE;
			}
		}
	}
	return bResult;
}

void CBCBaseFrame::DestroyControlBars()
{
#ifdef SDS
    if (m_pwndStatusBar)
    {
         m_pwndStatusBar->m_bAutoDelete =TRUE;
        m_pwndStatusBar->DestroyWindow();
 //       delete m_pwndStatusBar;
    }
#endif
    DestroyDockBars();
    // !!!--- Clean up for LOCKED BARs,
    // otherwise OnDestroy Bar will call deleted BaseFrame 
	POSITION pos = m_listControlBars.GetHeadPosition();
	while (pos != NULL)
	{
		CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);
        pBar->m_pDockSite = NULL;
	}
}

void CBCBaseFrame::OnIdleUpdateCmdUI()
{
	// do frame delayed recalc
	if (m_nIdleFlags & idleLayout)
		RecalcLayout(m_nIdleFlags & idleNotify);

	// update control bars
	POSITION pos = m_listControlBars.GetHeadPosition();
	while (pos != NULL)
	{
		CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);
		ASSERT_VALID(pBar);
		AfxCallWndProc(pBar, pBar->m_hWnd, WM_IDLEUPDATECMDUI, TRUE, 0);
	}
}

void CBCBaseFrame::RecalcLayout(BOOL bNotify)
{
	if (!m_bInRecalcLayout)
	{
		m_nIdleFlags &= ~(idleLayout|idleNotify);
        m_bInRecalcLayout = TRUE;

        BOOL bDone = FALSE;
        if (m_pCtrl)
			bDone = m_pCtrl->OnResizeBorder(this, NULL);

        if (bDone == FALSE)
        {
            m_bInRecalcLayout = FALSE;
            CFrameWnd::RecalcLayout(FALSE);
        }
		m_bInRecalcLayout = FALSE;
	}
}

CCMenuBar* CBCBaseFrame::GetActiveMenuBar()
{
    ASSERT(m_pwndActvMenuBar);
    return m_pwndActvMenuBar;
}

BOOL CBCBaseFrame::PreTranslateAccelerator(LPMSG pMsg)
{
    BOOL bRet = FALSE;

// 	CCMenuBar* pMenubar = GetActiveMenuBar();
//    if (pMenubar)
//        bRet = pMenubar->TranslateFrameMessage(pMsg);

    return bRet;
}

void CBCBaseFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) 
{    
    // !!! - Don't call the base class - otherwise the VB menu will be disabled
	        //CFrameWnd::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
    Default();	
}

BOOL CBCBaseFrame::OnCommand(WPARAM wParam, LPARAM lParam) 
{
		// update control bars
	POSITION pos = m_listControlBars.GetHeadPosition();
    BOOL bRET = FALSE;
	while (pos != NULL)
	{
		CControlBar* pBar = (CControlBar*)m_listControlBars.GetNext(pos);
		ASSERT(pBar != NULL);
		ASSERT_VALID(pBar);
        CBCToolBarBase* pTB = DYNAMIC_DOWNCAST (CBCToolBarBase, pBar);
        if (pTB)
            bRET = pTB->OnButtonCommand(wParam, lParam);
        if(bRET)
            break;
	}
    if (bRET)
        return TRUE;

	return CFrameWnd::OnCommand(wParam, lParam);
}

void CBCBaseFrame::OnSize(UINT nType, int cx, int cy) 
{	
	// do not call default - it will reposition the MDICLIENT
	if (nType != SIZE_MINIMIZED && m_pCtrl->m_bMDI)
    {
		RecalcLayout();
        return;
    }

	CFrameWnd::OnSize(nType, cx, cy);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions