单选项卡和多选项卡视图
编辑器可以创建不同类型的视图。 一个示例是代码编辑器窗口,另一个是窗体设计器。
多选项卡视图是具有多个选项卡的视图。 例如,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) 文件中。 这些值对应于VSFPROPID_guidEditorType
方法中GetProperty参数中propid
传递的值和VSFPROPID_pszPhysicalView
值。
示例
此代码片段说明了对象 TextView 如何用于访问实现的 IVsCodeWindow
视图。 在这种情况下,服务 SVsUIShellOpenDocument 用于调用 OpenDocumentViaProject 和请求 LOGVIEWID_TextView
,后者获取指向窗口框架的指针。 通过调用 GetProperty 和指定值 VSFPROPID_DocView
来获取指向文档视图对象的指针。 从文档视图对象中,调用 <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;
}