How to obtain the IVsCodeWindow from the IVsTextView

[Go to main articles index]

The source-code editing windows in the environment are actually window panes that hold IVsCodeWindow-s. They can contain one or two hosted IVsTextWindows, depending on whether the view has been split or not. It is easy to obtain a reference to them: GetPrimaryView() and GetSecondaryView() return pointers to them (take into account that, as for many COM objects, this operation AddRef's on them - if you are using C++, be sure to store in an auto-Releasing construct such as CComPtr<> or releasing them explicitly, if you trust yourself to remember to do so).

But, there is no obvious way to go the other way around. Researching a bit shows us the wonderful world of non-type-checked COM SetSite()/GetSite() methods (fun how you can build a typeless framework on top of a strongly typed language such as C++). The whole lack of types makes it quite difficult to know what queries to perform on the objects (I got this by trial and error).

Take into account that there may be IVsTextView's which are hosted out of any IVsCodeWindow, so the following code may fail to reach a valid object!


bool VSS_GetCodeWindowFromTextView(
  IVsCodeWindow **ppDest,
  IVsTextView *pTextView
)
{
  *ppDest = 0;

  // Try to get the VsCodeWindow jumping through a lot of hoops...
  CComPtr srpObjectWithSite;
  if (FAILED(pTextView->QueryInterface(IID_IObjectWithSite,
                                       (void**)&srpObjectWithSite.p))
  )
    return false;

  CComPtr srpUnkSite;
  if (FAILED(srpObjectWithSite->GetSite(IID_IUnknown,
                                        (void**)&srpUnkSite.p))
  )
    return false;

  CComPtr srpSite;
  if (FAILED(srpUnkSite->QueryInterface(IID_IServiceProvider,
                                        (void**)&srpSite.p))
  )
    return false;

  CComPtr srpWindowFrame;
  if (FAILED(srpSite->QueryService(SID_SVsWindowFrame,
                                   (IVsWindowFrame**)&srpWindowFrame.p))
  )
    return false;

  if (FAILED(srpWindowFrame->QueryViewInterface(IID_IVsCodeWindow,
                                                (void**)ppDest))
  )
    return false;

  // Got it!
  return true;
}

    

This code has been tested to work with Visual Studio .NET 2003 and with Visual Studio 2005.