|
|
// MstscMhst.cpp : Implementation of CMstscMhst
// Multi host control for TS activeX control.
// contains multiple instances of the activeX control. Used by the MMC control
// Copyright(C) Microsoft Corporation 2000
// nadima
#include "stdafx.h"
#include "multihst.h"
//Pos/width of sessions that are not active
#define X_POS_DISABLED -10
#define Y_POS_DISABLED -10
#define X_WIDTH_DISABLED 5
#define Y_WIDTH_DISABLED 5
/////////////////////////////////////////////////////////////////////////////
// CMstscMhst
/*
*Function Name:Add * *Parameters: (out) ppMstsc pointer to newly added TS control * *Description: Add's a new TS ActiveX control to the multihost * *Returns: HRESULT * */ STDMETHODIMP CMstscMhst::Add(IMsRdpClient** ppMstsc) { if (::IsWindow(m_hWnd)) { CAxWindow* pAxWnd = new CAxWindow(); ATLASSERT(pAxWnd); if (!pAxWnd) { return E_OUTOFMEMORY; }
RECT rc; GetClientRect(&rc); //
// Window is created invisible and disabled...
// Must be made with active client for it to become enabled and visible
//
if (!pAxWnd->Create( m_hWnd, rc, MSTSC_CONTROL_GUID, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0)) { delete pAxWnd; return E_FAIL; }
CComPtr<IMsRdpClient> tsClientPtr; if (FAILED(pAxWnd->QueryControl( &tsClientPtr))) { delete pAxWnd; return E_FAIL; }
//
// Store the pointer to the control
//
m_coll.push_back( pAxWnd);
//If no MSTSC windows are active then make this first
//one the active window
if (!m_pActiveWindow) { SwitchCurrentActiveClient( pAxWnd); }
if (ppMstsc) { //
// return the pointer, Detach does not decrement the ref count
// so we still hold a reference to the control from the QueryControl
// that is the +1 refcount needed to pass the pointer as an out
// parameter.
//
*ppMstsc = (IMsRdpClient*)tsClientPtr.Detach(); }
return S_OK; } else { return E_FAIL; } }
/*
*Function Name:get_Item * *Parameters: (in) Index (index of the item to return) * (out) ppMstsc pointer to the TS control returned * *Description: returns the TS control at a particular index * *Returns: HRESULT * */
STDMETHODIMP CMstscMhst::get_Item(long Index, IMsRdpClient** ppMstsc) { if (Index <0 || Index >= m_coll.size()) { ATLASSERT(Index > 0 && Index < m_coll.size()); return E_INVALIDARG; }
if (!ppMstsc) { return E_INVALIDARG; }
//Return the interface pointer associated
//with the AxWindow container
CAxWindow* pAxWnd = m_coll[Index]; if (!pAxWnd) { return E_FAIL; }
CComPtr<IMsRdpClient> tsClientPtr; if (FAILED(pAxWnd->QueryControl( &tsClientPtr))) { delete pAxWnd; return E_FAIL; }
//
// Return the pointer to the ts control. Detach does not
// decrement the AddRef from QueryControl so the refcount is
// correctly incremented by one for the out parameter
//
*ppMstsc = (IMsRdpClient*)tsClientPtr.Detach();
return S_OK; }
/*
*Function Name:get_Count * *Parameters: (out) pCount * *Description: returns number of items in the collection * *Returns: HRESULT * */
STDMETHODIMP CMstscMhst::get_Count(long* pCount) { if (!pCount) { return E_INVALIDARG; }
*pCount = m_coll.size(); return S_OK; }
/*
*Function Name:put_ActiveClientIndex * *Parameters: (in) ClientIndex * *Description: sets the active client by Index * *Returns: HRESULT * */
STDMETHODIMP CMstscMhst::put_ActiveClientIndex(long ClientIndex) { if (ClientIndex < 0 || ClientIndex >= m_coll.size()) { return E_INVALIDARG; }
CAxWindow* pNewClientWnd = m_coll[ClientIndex]; if (!pNewClientWnd) { return E_FAIL; }
if (SwitchCurrentActiveClient(pNewClientWnd)) { m_ActiveClientIndex = ClientIndex; return S_OK; } else { return E_FAIL; } }
/*
*Function Name:get_ActiveClient * *Parameters: (out) ppMstsc pointer to active client * *Description: returns the ActiveClient * *Returns: HRESULT * */
STDMETHODIMP CMstscMhst::get_ActiveClient(IMsRdpClient** ppMstsc) { if (!ppMstsc) { return E_INVALIDARG; } if (!m_pActiveWindow) { *ppMstsc = NULL; return S_OK; }
CComPtr<IMsRdpClient> tsClientPtr; if (FAILED(m_pActiveWindow->QueryControl( &tsClientPtr))) { return E_FAIL; }
//
// Detach keeps the +1 ref from QueryControl
//
*ppMstsc = (IMsRdpClient*)tsClientPtr.Detach();
return S_OK; }
/*
*Function Name:put_ActiveClient * *Parameters: ppMstsc * *Description: sets the active client given a pointer to * to the client instance * *Returns: HRESULT * */ STDMETHODIMP CMstscMhst::put_ActiveClient(IMsRdpClient* ppMstsc) { CAxWindow* pAxWnd = NULL;
//find AxWindow that hosts this client
//in the collection
std::vector<CAxWindow*>::iterator iter; for (iter = m_coll.begin(); iter != m_coll.end(); iter++) { CComPtr<IMsRdpClient> tsClientPtr; HRESULT hr = (*iter)->QueryControl( &tsClientPtr); if (FAILED(hr)) { return hr; } if (tsClientPtr == ppMstsc) { pAxWnd = *iter; break; } }
if (!pAxWnd) { //We were given a control reference that could not be found
return E_INVALIDARG; }
if (!SwitchCurrentActiveClient(pAxWnd)) { return E_FAIL; }
return S_OK; }
/*
*Function Name:SwitchCurrentActiveClient * *Parameters: (in) newHostWindow - AxWindow that will become * the active window * *Description: sets the active client given a pointer to * to the client instance * *Returns: success flag * */ BOOL CMstscMhst::SwitchCurrentActiveClient(CAxWindow* newHostWindow) { //Switch the current active client window
if (!newHostWindow) { return FALSE; }
m_pActiveWindow = newHostWindow;
//
// Make sure the window is sized properly
//
RECT rcClient; GetClientRect(&rcClient); m_pActiveWindow->MoveWindow(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); m_pActiveWindow->SetFocus();
//
// This window is made the active child window by brining
// it to the top of the Z-order of child windows
//
newHostWindow->BringWindowToTop();
return TRUE; }
/*
*Function Name:RemoveIndex * *Parameters: ClientIndex * *Description: removes a client by index * *Returns: HRESULT * */ STDMETHODIMP CMstscMhst::RemoveIndex(long ClientIndex) { HRESULT hr; CComPtr<IMsRdpClient> tsClientPtr; hr = get_Item(ClientIndex, (IMsRdpClient**) (&tsClientPtr));
if (FAILED(hr)) { return hr; }
//Pass in interface pointer without addref'ing
hr = Remove( (IMsRdpClient*)tsClientPtr);
return hr; }
/*
*Function Name:Remove * *Parameters: (in) ppMsts client to remove * *Description: removes a client from the collection * *Returns: HRESULT * */ STDMETHODIMP CMstscMhst::Remove(IMsRdpClient* ppMstsc) { //Look for the ax window container and if found delete it
//also, remove the entry from the collection
//find AxWindow that hosts this client
CAxWindow* pAxWnd = NULL;
std::vector<CAxWindow*>::iterator iter; for (iter = m_coll.begin(); iter != m_coll.end(); iter++) { CComPtr<IMsRdpClient> tsClientPtr; HRESULT hr = (*iter)->QueryControl( &tsClientPtr); if (FAILED(hr)) { return hr; } if (tsClientPtr == ppMstsc) { pAxWnd = *iter; break; } }
if (!pAxWnd) { //We were given a control reference that could not be found
return E_INVALIDARG; }
m_coll.erase(iter); return DeleteAxContainerWnd(pAxWnd); }
/*
*Function Name:DeleteAxContainerWnd * *Parameters: (in) pAxWnd CAxWindow to delete * *Description: deletes an activeX container window * *Returns: HRESULT * */
HRESULT CMstscMhst::DeleteAxContainerWnd(CAxWindow* pAxWnd) { if (!pAxWnd) { return E_FAIL; }
if (m_pActiveWindow == pAxWnd) { m_pActiveWindow = NULL; }
if (!pAxWnd->DestroyWindow()) { return E_FAIL; }
delete pAxWnd; return S_OK; }
//
// OnCreate Handler
//
LRESULT CMstscMhst::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ::SetWindowLong(m_hWnd, GWL_STYLE, ::GetWindowLong(m_hWnd, GWL_STYLE) | WS_CLIPCHILDREN);
if (!AtlAxWinInit()) { return -1; }
return 0; }
/*
*Function Name:OnDestroy * *Parameters: * *Description: handler for WM_DESTROY * *Returns: * */ LRESULT CMstscMhst::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { m_pActiveWindow = NULL;
if (!AtlAxWinTerm()) { return -1; }
//
// Delete everything in the collection
//
std::vector<CAxWindow*>::iterator iter; for (iter = m_coll.begin(); iter != m_coll.end(); iter++) { //
// This frees any remaining controls
//
DeleteAxContainerWnd(*iter); }
//
// Erase the CAxWindow items in the collection
//
m_coll.erase(m_coll.begin(), m_coll.end());
return 0; }
/**PROC+*********************************************************************/ /* Name: OnFrameWindowActivate */ /* */ /* Purpose: Override IOleInPlaceActiveObject::OnFrameWindowActivate */ /* to set the focus on the core container window when the control */ /* gets activated */ /* */ /**PROC-*********************************************************************/
STDMETHODIMP CMstscMhst::OnFrameWindowActivate(BOOL fActivate ) { if (fActivate && IsWindow() && m_pActiveWindow) { m_pActiveWindow->SetFocus(); }
return S_OK; }
LRESULT CMstscMhst::OnGotFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ATLTRACE("CMstscMhst::OnGotFocus"); if (m_pActiveWindow) { m_pActiveWindow->SetFocus(); } return 0; }
LRESULT CMstscMhst::OnLostFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ATLTRACE("CMstscMhst::OnLostFocus"); return 0; }
LRESULT CMstscMhst::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { RECT rcClient; if (m_pActiveWindow) { GetClientRect(&rcClient); m_pActiveWindow->MoveWindow(rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); } return 0; }
|