home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-12-15 | 24.2 KB | 943 lines | [TEXT/CWIE] |
- // =================================================================================
- // CControlContainer.cpp ©1996-97 Microsoft Corporation All rights reserved.
- // =================================================================================
- //
- // A control that contains other controls
-
- #include "ocheaders.h"
- #include <LArrayIterator.h>
- #include "CControlContainer.h"
- #include "CControlSite.h"
-
- const ArrayIndexT index_Self = -1;
-
- //======================================================================
- //
- // Public Methods
- //
-
- #pragma mark === CControlContainer::Construction & Destruction ===
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::CControlContainer
- // ---------------------------------------------------------------------------
- // Default Constructor
-
- CControlContainer::CControlContainer (void) : CBaseControl(), CContainer()
- {
- mFocusSite = NULL;
- mModalFocusSite = NULL;
- mLastSiteClicked = NULL;
- mScheduledControlsMap = NULL;
- mMapRefCon = 0;
-
- // Create two TextEdit controls
- CreateTextEditControl(10, 10, 150, 150);
- CreateTextEditControl(10, 170, 150, 150);
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::~CControlContainer
- // ---------------------------------------------------------------------------
- // Destructor
-
- CControlContainer::~CControlContainer (void)
- {
- if (mScheduledControlsMap)
- delete mScheduledControlsMap;
- }
-
-
- #pragma mark === CControlContainer ===
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::FindSiteHitBy
- // ---------------------------------------------------------------------------
- // Find which contained control was hit, if any
-
- CControlSite* CControlContainer::FindSiteHitBy (Point inWhere)
- {
- Uint32 i;
- Uint32 numSites;
- CControlSite* theSiteP;
-
- numSites = GetCount();
-
- for ( i = numSites; i > 0; i--)
- {
- FetchSite(i, (CXSite **) &theSiteP);
-
- if (theSiteP)
- {
- if (theSiteP->Contains(inWhere))
- return theSiteP;
- }
- }
-
- return NULL;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::RequestFocus
- // ---------------------------------------------------------------------------
- // Handle request for focus from a contained control
-
- STDMETHODIMP
- CControlContainer::RequestFocus (CControlSite* inSiteP, Boolean inAcquire, FocusSet inFocus)
- {
- ErrorCode theResult = S_OK;
- FocusSet needFocus = EmptyFocusSet;
-
- if (!inFocus)
- return S_OK;
-
- if (!inSiteP)
- return E_FAIL;
-
- if (inAcquire)
- {
- CControlSite* saveModal = mModalFocusSite;
- CControlSite* saveKeyboard = mFocusSite;
- Boolean8 modalReleased = false;
- Boolean8 keyboardReleased = false;
-
- if (inFocus & ModalFocus)
- {
- // If noone has the focus, add it to the list to request
- if (mModalFocusSite == NULL)
- {
- needFocus = FocusSet(needFocus | ModalFocus);
- }
- // Does someone else have the focus?
- else if (mModalFocusSite != inSiteP)
- {
- // Ask them if they'll give it up
- if (mModalFocusSite->SetFocus(RequestReleaseCommand, ModalFocus) == S_OK)
- {
- modalReleased = true;
- mModalFocusSite = inSiteP;
- }
- else // They won't release it - fail the request
- theResult = E_FAIL;
- }
- }
-
- if ((inFocus & KeyboardFocus) && (theResult == S_OK))
- {
- // If noone has the focus, add it to the list to request
- if (mFocusSite == NULL)
- {
- needFocus = FocusSet(needFocus | KeyboardFocus);
- }
- // Does someone else have the focus?
- else if (mFocusSite != inSiteP)
- {
- // Ask them if they'll give it up
- if (mFocusSite->SetFocus(RequestReleaseCommand, KeyboardFocus) == S_OK)
- {
- keyboardReleased = true;
- mFocusSite = inSiteP;
- }
- else // They won't release it - fail the request
- theResult = E_FAIL;
- }
- }
-
- // If we don't hold the requested foces types locally (self or embedded controls)
- if ((needFocus != EmptyFocusSet) && (theResult == S_OK))
- {
- // Request the focus types from our container
- if (mContainerSiteP->RequestFocus(inAcquire, needFocus) == S_OK)
- {
- if (needFocus & ModalFocus)
- mModalFocusSite = inSiteP;
- if (needFocus & KeyboardFocus)
- mFocusSite = inSiteP;
- }
- else // Request to our container failed - fail this request.
- theResult = E_FAIL;
- }
-
- // If there was a problem, attempt to restore the focus holders as existed before
- // this operation.
- if (theResult != S_OK)
- {
- if (modalReleased && (saveModal->SetFocus(TakeNextCommand, ModalFocus) == S_OK))
- mModalFocusSite = saveModal;
- else
- mModalFocusSite = NULL;
-
- if (keyboardReleased && (saveKeyboard->SetFocus(TakeNextCommand, KeyboardFocus) == S_OK))
- mFocusSite = saveKeyboard;
- else
- mFocusSite = NULL;
- }
- }
- else // !inAcquire - release
- {
- if (inFocus & ModalFocus)
- {
- if ((mModalFocusSite != NULL) && (mModalFocusSite == inSiteP))
- {
- mModalFocusSite = NULL;
- mContainerSiteP->RequestFocus(false, ModalFocus);
- }
- }
-
- if (inFocus & KeyboardFocus)
- {
- if ((mFocusSite != NULL) && (mFocusSite == inSiteP))
- {
- mFocusSite = NULL;
- mContainerSiteP->RequestFocus(false, KeyboardFocus);
- }
- }
- }
-
- return theResult;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::SetIdleTime
- // ---------------------------------------------------------------------------
- // Handle request for idle time from a contained control
-
- STDMETHODIMP
- CControlContainer::SetIdleTime (CControlSite* inSiteP, Int32 inWaitTicks, Uint32 inIdleRefCon)
- {
- ErrorCode theResult = E_FAIL;
-
- if (!mScheduledControlsMap)
- mScheduledControlsMap = new LArray(sizeof(SchedControlMap));
-
- if (mScheduledControlsMap)
- {
- switch (inWaitTicks)
- {
- case RemoveAllIdlers:
- theResult = RemoveControlIdler(inSiteP);
- break;
- case RemoveIdler:
- theResult = RemoveRefConIdler(inSiteP, inIdleRefCon);
- break;
- default:
- theResult = SetIdleTimeSelf(inSiteP, inWaitTicks, inIdleRefCon);
- break;
- }
- }
-
- return theResult;
- }
-
- //----------------------------------------------------------------------
- //
- // IUnknown Methods
- //
-
- #pragma mark === CControlContainer::IUnknown ===
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IUnknown::QueryInterface
- // ---------------------------------------------------------------------------
- // Do we implement the requested interface?
-
- STDMETHODIMP
- CControlContainer::QueryInterface (REFIID inRefID, void** outObj)
- {
- ErrorCode theResult;
-
- // Since we are both a container and a control, query each interface
- // from which we derive in turn.
- theResult = CContainer::QueryInterface(inRefID, outObj);
-
- if (theResult == E_NOINTERFACE)
- theResult = CBaseControl::QueryInterface(inRefID, outObj);
-
- // If we don't implement the interface ourself, pass the request up
- // to our containing object.
- if ((theResult == E_NOINTERFACE) && mUnkOuterP)
- theResult = mUnkOuterP->QueryInterface(inRefID, outObj);
-
- return theResult;
- }
-
-
- //----------------------------------------------------------------------
- //
- // IControl Methods
- //
-
- #pragma mark === CControlContainer::IControl ===
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IControl::Draw
- // ---------------------------------------------------------------------------
- // Draw the control and all contained controls
-
- STDMETHODIMP
- CControlContainer::Draw(DrawContext* inContext)
- {
- Uint32 i;
- Uint32 numSites;
- CControlSite* theSiteP;
- IControl* controlP;
-
- if (inContext->DrawAspect != DVASPECT_CONTENT)
- return DV_E_DVASPECT;
-
- // Erase the area and outline the frame
- ::EraseRect(&inContext->Location);
- ::PenSize(1, 1);
- ::FrameRect(&inContext->Location);
-
- // Draw each contained control
- numSites = GetCount();
-
- for ( i = 1; i <= numSites; i++)
- {
- FetchSite(i, (CXSite **) &theSiteP);
-
- if (theSiteP)
- {
- if (SUCCEEDED(theSiteP->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->Draw(inContext);
- controlP->Release();
- }
- }
- }
-
- return S_OK;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IControl::OnContextChange
- // ---------------------------------------------------------------------------
- // Pass context change on to contained controls
-
- STDMETHODIMP
- CControlContainer::OnContextChange(UInt32 inContextID, ContextCommand Command)
- {
- IControl* controlP;
- Uint32 i;
- Uint32 numSites;
- ErrorCode theResult;
- CControlSite* theSiteP;
-
- theResult = CBaseControl::OnContextChange(inContextID, Command);
-
- numSites = GetCount();
-
- for ( i = 1; i <= numSites; i++)
- {
- FetchSite(i, (CXSite **) &theSiteP);
-
- if (theSiteP)
- {
- if (SUCCEEDED(theSiteP->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->OnContextChange(inContextID, Command);
- controlP->Release();
- }
- }
- }
-
- return theResult;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IControl::SetFocus
- // ---------------------------------------------------------------------------
- // Acquire or release one or more focus types
-
- STDMETHODIMP
- CControlContainer::SetFocus(FocusCommand Command, FocusSet Focus)
- {
- ErrorCode result = S_OK;
-
- if (Command == TakeNextCommand || Command == TakePrevCommand)
- result = TakeFocus(Command, Focus);
- else if (Command == RequestReleaseCommand)
- {
- result = RequestReleaseFocus(Focus);
- }
- else if (Command == ReleaseCommand)
- {
- ReleaseFocus(Focus);
- result = S_OK;
- }
- else
- result = E_FAIL;
-
- return result;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IControl::DoMouse
- // ---------------------------------------------------------------------------
- // Handle mouse events for this control. Dispatch to contained controls as appropriate.
-
- STDMETHODIMP
- CControlContainer::DoMouse(MouseEventType inMouseET, PlatformEvent* inEvent)
- {
- IControl* controlP;
- DrawContext theContext = {BeginPortType};
-
- switch (inMouseET)
- {
- case MouseUp:
- // Send mouse-up to the control that received the last mouse down
- if (mLastSiteClicked)
- {
- if (SUCCEEDED((mLastSiteClicked)->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->DoMouse(inMouseET, inEvent);
- controlP->Release();
- }
- }
- break;
-
- case MouseDown:
- // Send mouse-down to the contained control that was hit, if any.
- Point localPt;
-
- mContainerSiteP->AcquireContext(mActiveContext->GetContextID(), &theContext);
-
- localPt = inEvent->where;
- ::GlobalToLocal(&localPt);
- mLastSiteClicked = FindSiteHitBy(localPt);
-
- mContainerSiteP->ReleaseContext(&theContext);
-
- // If a contained control was hit, pass it the mouse down event.
- if (mLastSiteClicked)
- {
- if (SUCCEEDED((mLastSiteClicked)->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->DoMouse(inMouseET, inEvent);
- controlP->Release();
- }
- }
- break;
- }
-
- return S_OK;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IControl::DoKey
- // ---------------------------------------------------------------------------
- // Handle key events for this control. Dispatch to contained controls as appropriate.
-
- STDMETHODIMP
- CControlContainer::DoKey(KeyEventType inKeyET, Char8 inChar, PlatformEvent* inEvent)
- {
- IControl* controlP;
- DrawContext theContext = {BeginPortType};
-
- // Send keyboard events to the embedded control that has the keyboard focus (if any)
- if (mFocusSite)
- {
- if (SUCCEEDED(mFocusSite->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->DoKey(inKeyET, inChar, inEvent);
- controlP->Release();
- }
- }
-
- return S_OK;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IControl::DoActivate
- // ---------------------------------------------------------------------------
- // Note activation state and pass on to contained controls
-
- STDMETHODIMP
- CControlContainer::DoActivate(ActivateEventType inActiveET, UInt32 inContextID, PlatformEvent* inEvent)
- {
- IControl* controlP;
- Uint32 i;
- Uint32 numSites;
- ErrorCode theResult;
- CControlSite* theSiteP;
-
- theResult = CBaseControl::DoActivate(inActiveET, inContextID, inEvent);
-
- numSites = GetCount();
-
- for ( i = 1; i <= numSites; i++)
- {
- FetchSite(i, (CXSite **) &theSiteP);
-
- if (theSiteP)
- {
- if (SUCCEEDED(theSiteP->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->DoActivate(inActiveET, inContextID, inEvent);
- controlP->Release();
- }
- }
- }
-
- return theResult;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::IControl::DoIdle
- // ---------------------------------------------------------------------------
- // Handle null events for this control. Dispatch to contained controls as appropriate.
-
- STDMETHODIMP
- CControlContainer::DoIdle(Uint32 inIdleRefCon)
- {
- ErrorCode theResult = E_FAIL;
-
- if (mScheduledControlsMap)
- {
- LArrayIterator schedControlIter(*mScheduledControlsMap);
- Boolean8 found = false;
- SchedControlMap map;
-
- while (schedControlIter.Next(&map) && !found)
- {
- if (map.ContainerRefCon == inIdleRefCon)
- {
- theResult = map.Control->DoIdle(map.ControlRefCon);
- found = true;
- }
- }
- }
-
- return theResult;
- }
-
- //======================================================================
- //
- // Private Methods
- //
-
- #pragma mark === CControlContainer Private Methods ===
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::CreateTextEditControl
- // ---------------------------------------------------------------------------
- // Create a TextEdit control at the specified position
-
- void CControlContainer::CreateTextEditControl(Uint32 inTop, Uint32 inLeft, Uint32 inHeight, Uint32 inWidth)
- {
- CControlSite* theSiteP;
-
- theSiteP = new CControlSite(this, inTop, inLeft, inHeight, inWidth);
- if (theSiteP)
- {
- theSiteP->SetContainerData( (IContainer *) this, NULL);
- theSiteP->AddParam("src", "textedit.acx");
- theSiteP->AddParam("classid", "CLSID:{03d64580-21d1-11d0-b42d-8215fbcfdd9c}");
- theSiteP->AddParam("codebase", "TextEdit.hqx");
-
- theSiteP->CreateControl(true);
-
- AddSite(theSiteP);
- }
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::FirstFocus
- // ---------------------------------------------------------------------------
- // Find the first contained control that should be offered the focus
-
- ArrayIndexT CControlContainer::FirstFocus (FocusSet Focus, Boolean8 forward)
- {
- ArrayIndexT result = LArray::index_Bad;
- CControlSite* currentSiteP = NULL;
-
- if ((Focus & KeyboardFocus) && (mFocusSite != NULL))
- currentSiteP = mFocusSite;
- else if ((Focus & ModalFocus) && (mModalFocusSite != NULL))
- currentSiteP = mModalFocusSite;
-
- if (currentSiteP != NULL)
- {
- result = mSiteArrayP->FetchIndexOf(currentSiteP);
- if (result != LArray::index_Bad)
- {
- if (forward)
- {
- // Start with the next control on the list.
- // If this is the last item, fail.
- result++;
- if (result > GetCount())
- result = LArray::index_Bad;
- }
- else
- {
- // Start with the previous control on the list.
- // If this is the first item, fail.
- result--;
- if (result < 1)
- result = LArray::index_Bad;
- }
- }
- }
- else
- {
- if (GetCount() > 0)
- {
- if (forward)
- result = LArray::index_First; // Start with the first embedded control
- else
- result = LArray::index_Last; // Start with the last embedded control
- }
- else
- result = LArray::index_Bad; // No sites - fail
- }
-
- return result;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::FocusTaken
- // ---------------------------------------------------------------------------
- // Records the focus types now held by the embedded control
-
- void CControlContainer::FocusTaken(FocusSet inFocus, CControlSite* inSiteP)
- {
- if (inFocus & KeyboardFocus)
- mFocusSite = inSiteP;
-
- if (inFocus & ModalFocus)
- mModalFocusSite = inSiteP;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::HaveFocus
- // ---------------------------------------------------------------------------
- // Are any of these focus types held?
-
- Boolean8 CControlContainer::HaveFocus (FocusSet Focus)
- {
- if (((Focus & KeyboardFocus) && (mFocusSite != NULL)) ||
- ((Focus & ModalFocus) && (mModalFocusSite != NULL)))
- return true;
- else
- return false;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::NextFocus
- // ---------------------------------------------------------------------------
- // Which control should be offered focus next?
-
- ArrayIndexT CControlContainer::NextFocus (Boolean8 forward, ArrayIndexT index)
- {
- ArrayIndexT next;
-
- // Searching forward or backwards?
- if (forward)
- {
- // Forward.
- // The next contained control is the next target. If no more contained
- // controls, fail.
- next = index + 1;
- if (next > GetCount())
- next = LArray::index_Bad;
- }
- else
- {
- // Backward.
- // The prior contained control in the list is the next target.
- // If already at the beginning of the list, fail.
- next = index - 1;
- if (next <= 0)
- next = LArray::index_Bad;
- }
-
- return next;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::ReleaseFocus
- // ---------------------------------------------------------------------------
- // Release the specified foci.
-
- void CControlContainer::ReleaseFocus (FocusSet Focus)
- {
- IControl* controlP;
-
- if ((Focus & KeyboardFocus) && (mFocusSite != NULL))
- {
- if (SUCCEEDED(mFocusSite->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->SetFocus(ReleaseCommand, KeyboardFocus);
- controlP->Release();
- }
-
- mFocusSite = NULL;
- }
-
- if ((Focus & ModalFocus) && (mModalFocusSite != NULL))
- {
- if (SUCCEEDED(mModalFocusSite->QueryInterface(IID_IControl, &controlP)))
- {
- controlP->SetFocus(ReleaseCommand, ModalFocus);
- controlP->Release();
- }
-
- mModalFocusSite = NULL;
- }
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::RequestReleaseFocus
- // ---------------------------------------------------------------------------
- // Attempt to release the specified foci.
-
- ErrorCode
- CControlContainer::RequestReleaseFocus (FocusSet Focus)
- {
- ErrorCode theResult = S_OK;
- IControl* controlP;
-
- if ((Focus & ModalFocus) && (mModalFocusSite != NULL))
- {
- if (SUCCEEDED(mModalFocusSite->QueryInterface(IID_IControl, &controlP)))
- {
- if (controlP->SetFocus(RequestReleaseCommand, ModalFocus) == S_OK)
- mModalFocusSite = NULL;
- else
- theResult = E_FAIL;
-
- controlP->Release();
- }
- else
- theResult = E_FAIL;
- }
-
- if ((theResult == S_OK) && (Focus & KeyboardFocus) && (mFocusSite != NULL))
- {
- if (SUCCEEDED(mFocusSite->QueryInterface(IID_IControl, &controlP)))
- {
- if (controlP->SetFocus(RequestReleaseCommand, KeyboardFocus) == S_OK)
- mFocusSite = NULL;
- else
- theResult = E_FAIL;
-
- controlP->Release();
- }
- else
- theResult = E_FAIL;
-
- mFocusSite = NULL;
- }
-
- return theResult;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::RemoveControlIdler
- // ---------------------------------------------------------------------------
- // Remove all idlers associated with this control.
-
- ErrorCode
- CControlContainer::RemoveControlIdler (CControlSite* inSiteP)
- {
- ErrorCode theResult = E_FAIL;
-
- if (mScheduledControlsMap)
- {
- // Find all control/refcon pairs for this control
- LArrayIterator schedControlIter(*mScheduledControlsMap);
- SchedControlMap tempMap;
-
- while (schedControlIter.Next(&tempMap))
- {
- if (tempMap.Control == inSiteP)
- {
- // Tell our container to remove the corresponding idler.
- theResult = mContainerSiteP->SetIdleTime(RemoveIdler, tempMap.ContainerRefCon);
-
- // Remove the record from our list.
- if (theResult == S_OK)
- mScheduledControlsMap->RemoveItemsAt(1, schedControlIter.GetCurrentIndex());
- }
- }
- }
-
- return theResult;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::RemoveRefConIdler
- // ---------------------------------------------------------------------------
- // Remove the idler for this control with the specified refcon.
-
- ErrorCode
- CControlContainer::RemoveRefConIdler (CControlSite* inSiteP, Uint32 inIdleRefCon)
- {
- ErrorCode theResult = E_FAIL;
-
- if (mScheduledControlsMap)
- {
- // Find a record for this control/refcon pair
- LArrayIterator schedControlIter(*mScheduledControlsMap);
- SchedControlMap tempMap;
- Boolean found = false;
-
- while (schedControlIter.Next(&tempMap) && !found)
- {
- // If found, tell our container to remove the corresponding idler.
- if (tempMap.Control == inSiteP && tempMap.ControlRefCon == inIdleRefCon)
- {
- theResult = mContainerSiteP->SetIdleTime(RemoveIdler, tempMap.ContainerRefCon);
- found = true;
-
- // Remove the record from our list.
- if (theResult == S_OK)
- mScheduledControlsMap->RemoveItemsAt(1, schedControlIter.GetCurrentIndex());
- }
- }
- }
-
- return theResult;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::SetIdleTimeSelf
- // ---------------------------------------------------------------------------
- // Add or update the idler information for this control/refcon pair.
-
- ErrorCode
- CControlContainer::SetIdleTimeSelf (CControlSite* inSiteP, Int32 inWaitTicks, Uint32 inIdleRefCon)
- {
- ErrorCode theResult = E_FAIL;
-
- if (mScheduledControlsMap)
- {
- // see if there is already a record for this control/refcon pair
- LArrayIterator schedControlIter(*mScheduledControlsMap);
- SchedControlMap tempMap;
- Boolean found = false;
-
- while (schedControlIter.Next(&tempMap) && !found)
- {
- // If so, pass the mapped refcon and the new wait time to the container
- if (tempMap.Control == inSiteP && tempMap.ControlRefCon == inIdleRefCon)
- {
- theResult = mContainerSiteP->SetIdleTime(inWaitTicks, tempMap.ContainerRefCon);
- found = true;
- }
- }
-
- if (!found)
- {
- // if not, create a new refcon map entry and fill it in
- tempMap.Control = inSiteP;
- tempMap.ControlRefCon = inIdleRefCon;
- tempMap.ContainerRefCon = ++mMapRefCon;
-
- theResult = mContainerSiteP->SetIdleTime(inWaitTicks, tempMap.ContainerRefCon);
-
- if (theResult == S_OK)
- {
- mScheduledControlsMap->InsertItemsAt(1, 1, &tempMap);
- }
- }
- }
-
- return theResult;
- }
-
-
- // ---------------------------------------------------------------------------
- // • CControlContainer::TakeFocus
- // ---------------------------------------------------------------------------
- // Take the specified foci. If we already have them, advance them to the "next" control.
-
- ErrorCode CControlContainer::TakeFocus(FocusCommand Command, FocusSet Focus)
- {
- ErrorCode result = E_FAIL;
- Boolean8 forward = (Command == TakeNextCommand);
- Boolean8 found;
- Boolean8 done;
- ArrayIndexT index = LArray::index_Bad;
- CControlSite* siteP;
-
- if (HaveFocus(Focus))
- {
- // Embedded control(s) holds one or more of the requested foci.
- // Find first control to which we should try passing the focus and release
- // the current holder(s) of the focus.
- index = FirstFocus(Focus, forward);
- ReleaseFocus(Focus);
- if (index == LArray::index_Bad)
- {
- // We can't take the focus.
- result = E_FAIL;
- }
- }
- else
- {
- // We don't have the requested focus.
- // Find first control to which we should try passing the focus.
- if (mLastSiteClicked)
- {
- index = mSiteArrayP->FetchIndexOf(mLastSiteClicked);
- }
-
- if ((index == LArray::index_Bad) && (GetCount() > 0))
- {
- if (Command == TakeNextCommand)
- index = LArray::index_First;
- else
- index = LArray::index_Last;
- }
- }
-
- done = false;
- while (index != LArray::index_Bad && !done)
- {
- found = mSiteArrayP->FetchItemAt(index, &siteP);
- if (found && siteP)
- {
- IControl* controlP;
-
- if (SUCCEEDED(siteP->QueryInterface(IID_IControl, &controlP)))
- {
- if (controlP->SetFocus(Command, Focus) == S_OK)
- {
- FocusTaken(Focus, siteP);
- controlP->Release();
- result = S_OK;
- done = true;
- }
- else
- controlP->Release();
- }
- }
-
- index = NextFocus(forward, index);
- }
-
- return result;
- }
-
-