Share via


単一タブと複数タブのビュー

エディターでは、さまざまな種類のビューを作成できます。 1 つの例としてコード エディター ウィンドウがあり、他にはフォーム デザイナーがあります。

複数のタブからなるビューは、複数のタブを持つビューです。 たとえば、HTML エディターの下部には、[デザイン][ソース] の 2 つのタブがあり、それぞれ論理ビューです。 デザイン ビューには、レンダリングされた Web ページが表示されます。もう一方では、Web ページを構成する HTML が表示されます。

物理ビューへのアクセス

物理ビューでは、ドキュメント ビュー オブジェクトがホストされます。それぞれ、コードやフォームなど、バッファー内のデータのビューを表します。 その結果、各ドキュメント ビュー オブジェクトには物理ビュー (物理ビュー文字列と呼ばれるもので識別されます) と、通常は 1 つの論理ビューがあります。

ただし、場合によっては、物理ビューに 2 つ以上の論理ビューを含めることができます。 例としては、サイドバイサイド ビューを備えた分割ウィンドウがあるエディターや、GUI/デザイン ビューとコードビハインド フォーム ビューを持つフォーム デザイナーがあります。

エディターから使用可能なすべての物理ビューにアクセスできるようにするには、エディター ファクトリで作成できるドキュメント ビュー オブジェクトの種類ごとに一意の物理ビュー文字列を作成する必要があります。 たとえば、Visual Basic エディター ファクトリでは、コード ウィンドウとフォーム デザイナー ウィンドウのドキュメント ビュー オブジェクトを作成できます。

複数のタブ付きビューの作成

ドキュメント ビュー オブジェクトは、一意の物理ビュー文字列を使用して物理ビューに関連付けられている必要がありますが、複数のタブを物理ビュー内に配置することで、さまざまな方法でデータを表示することができます。 この複数タブの構成では、すべてのタブが同じ物理ビュー文字列に関連付けられていますが、各タブには異なる論理ビュー GUID が割り当てられています。

エディター用の複数のタブ付きビューを作成するには、IVsMultiViewDocumentView インターフェイスを実装してから、作成した各タブに別の論理ビュー GUID (LogicalViewID) を関連付けます。

Visual Studio HTML エディターは、複数のタブ付きビューを備えたエディターの一例です。 これには、[デザイン] タブと [ソース] タブがあります。 これを有効にするため、[デザイン] タブには LOGICALVIEWID_TextView[ソース] タブには LOGICALVIEWID_Codeと、各タブに別の論理ビューが関連付けられています。

適切な論理ビューを指定することにより、VSPackage から、フォームのデザイン、コードの編集、コードのデバッグなど、特定の目的に対応するビューにアクセスできます。 ただし、ウィンドウの 1 つは NULL 文字列によって識別される必要があり、これはプライマリ論理ビュー (LOGVIEWID_Primary) に対応する必要があります。

次の表に、使用可能な論理ビューの値とその使用方法を示します。

LOGVIEWID GUID 推奨される用途
LOGVIEWID_Primary エディター ファクトリの既定/プライマリ ビュー。

すべてのエディター ファクトリでは、この値をサポートする必要があります。 このビューでは、物理ビュー文字列として NULL 文字列を使用する必要があります。 少なくとも 1 つの論理ビューをこの値に設定する必要があります。
LOGVIEWID_Debugging デバッグ ビュー。 通常、LOGVIEWID_DebuggingLOGVIEWID_Code と同じビューにマップされます。
LOGVIEWID_Code コードの表示コマンドによって起動されたビュー。
LOGVIEWID_Designer フォームの表示コマンドによって起動されたビュー。
LOGVIEWID_TextView テキスト エディター ビュー。 これは、IVsTextView にアクセスするための IVsCodeWindow を返すビューです。
LOGVIEWID_UserChooseView 使用するビューを選択するようにユーザーに求めます。
LOGVIEWID_ProjectSpecificEditor [プログラムから開く] ダイアログ ボックスから次に渡されます

OpenItem

ユーザーが "(プロジェクトの既定のエディター)" エントリを選択したときです。

論理ビュー GUID は拡張可能ですが、VSPackage で定義されている論理ビュー GUID のみを使用できます。

シャットダウン時に、Visual Studio では、エディター ファクトリの GUID とドキュメント ウィンドウに関連付けられている物理ビュー文字列を保持します。これにより、ソリューションを再度開いたときにドキュメント ウィンドウを再び開くために使用できるようになります。 ソリューションが閉じられたときに開いていたウィンドウだけが、ソリューション (.suo) ファイルに保存されます。 これらの値は、GetProperty メソッドの propid パラメーターで渡される VSFPROPID_guidEditorTypeVSFPROPID_pszPhysicalView 値に対応します。

このスニペットは、IVsCodeWindow を実装するビューに TextView オブジェクトを使用してアクセスする方法を示しています。 この場合、SVsUIShellOpenDocument サービスが、ウィンドウフレームへのポインターを取得する OpenDocumentViaProject を呼び出し、LOGVIEWID_TextView を要求するために使用されます。 ドキュメント ビュー オブジェクトへのポインターは、 GetProperty を呼び出し、VSFPROPID_DocView の値を指定することによって取得されます。 ドキュメント ビュー オブジェクトから、IVsCodeWindow のために QueryInterface が呼び出されます。 この場合は、テキスト エディターが返されるため、GetProperty メソッドで返されるドキュメント ビュー オブジェクトがコード ウィンドウになります。

HRESULT CFindTool::GotoFileLocation(const WCHAR * szFile, long iLine, long iStart, long iLen)
{
  HRESULT hr;
  if (NULL == szFile || !*szFile)
    return E_INVALIDARG;

  if (iLine == -1L)
    return S_FALSE;

  VSITEMID                  itemid;
  VARIANT                   var;
  RECT                      rc;
  IVsUIShellOpenDocument *  pOpenDoc    = NULL;
  IVsCodeWindow *           pCodeWin    = NULL;
  IVsTextView *             pTextView   = NULL;
  IVsUIHierarchy *          pHierarchy  = NULL;
  IVsWindowFrame *          pFrame      = NULL;
  IUnknown *                pUnk        = NULL;
  IVsHighlight *            pHighlight  = NULL;

  IfFailGo(CGlobalServiceProvider::HrQueryService(SID_SVsUIShellOpenDocument, IID_IVsUIShellOpenDocument, (void **)&pOpenDoc));
  IfFailGo(pOpenDoc->OpenDocumentViaProject(szFile, LOGVIEWID_TextView, NULL, &pHierarchy, &itemid, &pFrame));
  pFrame->Show();
  VariantInit(&var);
  IfFailGo(pFrame->GetProperty(VSFPROPID_DocView, &var));
  if (VT_UNKNOWN != var.vt) { hr = E_FAIL; goto Error; }
  pUnk = V_UNKNOWN(&var);
  if (NULL != pUnk)
  {
    IfFailGo(pUnk->QueryInterface(IID_IVsCodeWindow, (void **)&pCodeWin));
    if (SUCCEEDED(hr = pCodeWin->GetLastActiveView(&pTextView)) ||
        SUCCEEDED(hr = pCodeWin->GetPrimaryView(&pTextView)) )
    {
      pTextView->SetSelection(iLine, iStart, iLine, iStart + iLen);
      // uncover selection
      IfFailGo(pTextView->QueryInterface(IID_IVsHighlight, (void**)&pHighlight));
      IfFailGo(SUCCEEDED(pHighlight->GetHighlightRect(&rc)));
      UncoverSelectionRect(&rc);
    }
  }

Error:
  CLEARINTERFACE(pHighlight);
  CLEARINTERFACE(pTextView);
  CLEARINTERFACE(pCodeWin);
  CLEARINTERFACE(pUnk);
  CLEARINTERFACE(pFrame);
  CLEARINTERFACE(pOpenDoc);
  CLEARINTERFACE(pHierarchy);
  RedrawWindow(m_hwndResults, NULL, NULL, RDW_ERASE|RDW_FRAME|RDW_INVALIDATE|RDW_ALLCHILDREN);
  return hr;
}