편집기에서 다양한 유형의 보기를 만들 수 있습니다. 한 가지 예는 코드 편집기 창이고, 다른 하나는 양식 디자이너입니다.
다중 탭 보기는 여러 탭이 있는 보기입니다. 예를 들어 HTML 편집기 아래쪽에는 디자인 및 원본이라는 두 개의 탭이 있으며 각각 논리적 보기입니다. 디자인 보기는 렌더링된 웹 페이지를 표시하고 다른 하나는 웹 페이지를 구성하는 HTML을 표시합니다.
물리적 보기 액세스하기
물리적 뷰는 각각 코드 또는 폼과 같은 버퍼의 데이터 보기를 나타내는 문서 뷰 개체를 호스트합니다. 따라서 각 문서 뷰 개체에는 물리적 뷰(실제 뷰 문자열이라고 하는 것으로 식별됨)가 있으며 일반적으로 단일 논리 뷰가 있습니다.
그러나 일부 경우에는 실제 뷰에 둘 이상의 논리 뷰가 있을 수 있습니다. 몇 가지 예로는 나란히 보기 기능을 제공하는 분할 창이 있는 편집기 또는 GUI/디자인 보기와 코드-비하인드 보기를 지원하는 양식 디자이너가 있습니다.
편집기에서 사용 가능한 모든 실제 보기에 액세스할 수 있도록 하려면 편집기 팩터리에서 만들 수 있는 각 유형의 문서 보기 개체에 대해 고유한 실제 보기 문자열을 만들어야 합니다. 예를 들어 Visual Basic 편집기 팩터리는 코드 창 및 양식 디자이너 창에 대한 문서 보기 개체를 만들 수 있습니다.
다중 탭 보기 만들기
문서 보기 개체는 고유한 물리적 뷰 문자열을 통해 실제 뷰와 연결되어야 하지만 물리적 뷰 내에 여러 탭을 배치하여 다양한 방식으로 데이터를 볼 수 있도록 할 수 있습니다. 이 다중 탭 구성에서는 모든 탭이 동일한 실제 보기 문자열과 연결되지만 각 탭에는 다른 논리 뷰 GUID가 제공됩니다.
편집기용 다중 탭 보기를 만들려면 인터페이스를 IVsMultiViewDocumentView 구현한 다음 만든 각 탭에 다른 논리 뷰 GUID(LogicalViewID)를 연결합니다.
Visual Studio HTML 편집기는 다중 탭 보기가 있는 편집기의 예입니다.
디자인 및 원본 탭이 있습니다. 이를 가능하게 하기 위해 각 탭에는 LOGICALVIEWID_TextView디자인 탭과 LOGICALVIEWID_Code원본 탭에 대해 다른 논리 보기가 연결됩니다.
적절한 논리 뷰를 지정하면 VSPackage는 양식 디자인, 코드 편집 또는 코드 디버깅과 같은 특정 용도에 해당하는 뷰에 액세스할 수 있습니다. 그러나 창 중 하나는 NULL 문자열로 식별되어야 하며 이는 기본 논리 뷰(LOGVIEWID_Primary)에 해당해야 합니다.
다음 표에는 사용 가능한 논리 뷰 값 및 해당 사용이 나열되어 있습니다.
| LOGVIEWID GUID | 권장 사용 |
|---|---|
LOGVIEWID_Primary |
편집기 팩터리의 기본 보기입니다. 모든 편집기 팩터리에서 이 값을 지원해야 합니다. 이 뷰는 NULL 문자열을 실제 뷰 문자열로 사용해야 합니다. 하나 이상의 논리 뷰를 이 값으로 설정해야 합니다. |
LOGVIEWID_Debugging |
디버깅 뷰. 일반적으로 LOGVIEWID_Debugging는 LOGVIEWID_Code와 동일한 보기에 매핑됩니다. |
LOGVIEWID_Code |
코드 보기 명령으로 시작된 뷰입니다. |
LOGVIEWID_Designer |
폼 보기 명령으로 시작된 보기입니다. |
LOGVIEWID_TextView |
텍스트 편집기 보기입니다. 이 보기에서 IVsCodeWindow를 반환하며, 이를 통해 IVsTextView에 접근할 수 있습니다. |
LOGVIEWID_UserChooseView |
사용자에게 사용할 보기를 선택하라는 메시지를 표시합니다. |
LOGVIEWID_ProjectSpecificEditor |
'다른 프로그램으로 열기' 대화 상자로 전달됨. OpenItem 사용자가 "(프로젝트 기본 편집기)" 항목을 선택하면 됩니다. |
논리 뷰 GUID는 확장 가능하지만 VSPackage에 정의된 논리 뷰 GUID만 사용할 수 있습니다.
종료 시 Visual Studio는 편집기 팩터리의 GUID와 문서 창과 연결된 실제 보기 문자열을 유지하므로 솔루션을 다시 열 때 문서 창을 다시 여는 데 사용할 수 있습니다. 솔루션을 닫을 때 열려 있는 창만 솔루션(.suo) 파일에 유지됩니다. 이러한 값들은 GetProperty 메서드의 propid 매개 변수로 전달되는 VSFPROPID_guidEditorType 값과 VSFPROPID_pszPhysicalView 값에 해당합니다.
Example
이 코드 조각은 TextView 객체를 사용하여 IVsCodeWindow을(를) 구현하는 뷰에 액세스하는 방법을 보여줍니다. 이 경우 SVsUIShellOpenDocument 서비스는 OpenDocumentViaProject을(를) 호출하고 LOGVIEWID_TextView을(를) 요청하여 창 프레임에 대한 포인터를 가져오는 데 사용됩니다. 문서 뷰 객체에 대한 포인터는 GetProperty을(를) 호출하여 VSFPROPID_DocView 값을 지정함으로써 얻을 수 있습니다. 문서 뷰 개체에서 QueryInterface이(가) IVsCodeWindow를 호출합니다. 이 경우 텍스트 편집기가 반환되므로 메서드에서 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;
}