前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(翻译)LearnVSXNow! #14- VSCT文件基础

(翻译)LearnVSXNow! #14- VSCT文件基础

作者头像
明年我18
发布2019-09-18 11:36:15
7180
发布2019-09-18 11:36:15
举报
文章被收录于专栏:明年我18明年我18

在第13篇里,我说过我要给你们展示一些菜单、工具栏和命令的示例代码,但是相关的东西太多了,一篇文章没办法全部囊括,所以在这里我只涉及一些和vsct文件相关的代码。

前言

在本系列前面的文章里,我多次提到过Package是按需加载的,IDE只有在真正用到Package的时候才去加载它们。但这样就带来一个问题:IDE如何在不加载Package的情况下,显示Package里定义的菜单和工具栏?或者说当我们在IDE里看到某个Package的菜单的时候,这个Package到底有没有被加载到IDE里?

当Package被注册后(通过regpkg.exe),Package里代表菜单和工具栏的资源实际上是被单独存放在一个地方,所以在Visual Studio启动后,它就可以从这个地方读取出这个信息,并显示相应的菜单和工具栏,而不必加载Package本身。

实现这种模式的关键,就在于vsct(Visual Studio Command Table)文件。这个文件是旧版的Visual Studio SDK中ctc文件的替代品,是用来定义命令以及与命令相关的UI的。编译完package后,vsct文件被编译到一个cto文件中,并且作为一个资源添加到package的dll里。

在VS 2005版本的Visual Studio SDK里,用的是文本格式的ctc文件。编辑和理解ctc文件并不是一个简单的任务。所以在Visual Studio 2008 SDK里,微软创建了一种新的基于xml的vsct文件和相应的编译器,负责把vsct编译成cto格式。

应用vsct文件的最大的优势在于它就是一个xml文件,它拥有xml文件固有的特性,例如自动生成结束标签或者智能感知。所以微软建议我们用vsct文件来代替ctc文件,当然,ctc文件目前依然可以使用。

在这篇文章里,我将给大家介绍一些在前面的文章里没有提到的关于vsct文件的细节。首先我要先介绍一下vsct文件的基础,然后再用一些例子来说明它。

VSCT文件的结构

xml文件的xsd架构可以告诉我们一个xml文件里应该包含什么内容,因为xsd文件里定义了相应的xml文件的语法、词法等很多信息,并且“据说”不管是对计算机还是对人来说,可读性都很好。毫无疑问,计算机可以很牛逼的识别xsd文件,但对于我们人类来说,其实它的可读性并不是那么好。所以在这里我就不给大家展示vsct的xsd架构了,而是通过例子来解释一下vsct的结构。

外层节点

VSCT文件的根结点是CommandTable

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><CommandTable xmlns="http://schemas.microsoft.com/VisualStudio/..."   xmlns:xs="http://www.w3.org/2001/XMLSchema">  <!-- Content of the command table --></CommandTable>

command table的元素的命名空间是“http://schemas.microsoft.com/VisualStudio/2005-10-18/CommandTable”,不要忘了加上它,但是我为了使示例代码更短,所以不加这个命名空间。

CommandTable的子节点是:

代码语言:javascript
复制
<CommandTable xmlns="..." xmlns:xs="...">  <Extern/>  <Include/>  <Define/>  <Commands/>  <CommandPlacements>  <VisibilityConstraints/>  <KeyBindings/>  <UsedCommands/>  <Symbols/></CommandTable>

其中,最重要的是Extern、Commands和Symbols节点,让我们看一下VSPackage向导帮我们生成的vsct文件:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><CommandTable xmlns="..." xmlns:xs="...">  <Extern href="stdidcmd.h" mce_href="stdidcmd.h"/>  <Extern href="vsshlids.h" mce_href="vsshlids.h"/>  <Extern href="msobtnid.h" mce_href="msobtnid.h"/>     <Commands package="guidSimpleCommandPkg">    <Groups>      <Group guid="guidSimpleCommandCmdSet" id="MyMenuGroup" priority="0x0600">        <Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/>      </Group>    </Groups>      <Buttons>      <Button guid="guidSimpleCommandCmdSet" id="cmdidMyFirstCommand"         priority="0x0100" type="Button">        <Parent guid="guidSimpleCommandCmdSet" id="MyMenuGroup" />        <Icon guid="guidImages" id="bmpPic1" />        <Strings>          <CommandName>cmdidMyFirstCommand</CommandName>          <ButtonText>My First Command</ButtonText>        </Strings>      </Button>    </Buttons>    <Bitmaps>      <Bitmap guid="guidImages" href="Resources\Images_32bit.bmp" mce_href="Resources\Images_32bit.bmp"         usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>    </Bitmaps>  </Commands>    <Symbols>    <GuidSymbol name="guidSimpleCommandPkg"       value="{2291da24-92e5-4ea4-bdb7-72a9b5ac7d59}" />    <GuidSymbol name="guidSimpleCommandCmdSet"       value="{a982b107-4ad4-437e-b2bc-cdf2708aa376}">      <IDSymbol name="MyMenuGroup" value="0x1020" />      <IDSymbol name="cmdidMyFirstCommand" value="0x0100" />    </GuidSymbol>    <GuidSymbol name="guidImages" value="{5c3faf04-8190-48c4-a6e9-71f04f1848e5}" >      <IDSymbol name="bmpPic1" value="1" />      <IDSymbol name="bmpPic2" value="2" />      <IDSymbol name="bmpPicSearch" value="3" />      <IDSymbol name="bmpPicX" value="4" />      <IDSymbol name="bmpPicArrows" value="5" />    </GuidSymbol>  </Symbols>  </CommandTable>

Symbols和IDs

我在第6篇里已经说过了,VS IDE里的对象(例如命令和相关的UI元素)都有唯一的标识,我们需要利用他们的唯一标识符来引用某个元素。标识符由一个GUID和一个32位无符号整数组成。GUID代表一个逻辑上包含对象的容器,32位无符号整数代表这个对象在逻辑容器内的id。(也有一些对象只用GUID来标识,稍后我会介绍它们)。

在vsct文件里,如果直接用这些GUID和ID的话,代码的可读性就太差了,幸好vsct文件里有Symbols节点。该节点用于给这些GUID或者ID起个可读性较好的名字,其中:GuidSysmbol子节点用来给逻辑容器GUID起别名,嵌套的IDSymbol节点用来给32位无符号数起别名。

在上面的代码段中,定义了三个GUID容器。第一个是一个空的容器(别名是guidSimpleCommandPkg),另外两个则包含若干个ID。定义好了symbols之后,就可以引用它们了:

代码语言:javascript
复制
<Commands package="guidSimpleCommandPkg">    <Groups>      <Group guid="guidSimpleCommandCmdSet" id="MyMenuGroup" priority="0x0600">        <!-- ... -->       </Group>    </Groups>      <Buttons>      <Button guid="guidSimpleCommandCmdSet" id="cmdidMyFirstCommand"         priority="0x0100" type="Button">        <!-- ... -->      </Button>    </Buttons>        <Bitmaps>      <Bitmap guid="guidImages" href="Resources\Images_32bit.bmp" mce_href="Resources\Images_32bit.bmp"         usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>    </Bitmaps>  </Commands>

在定义命令的时候,我们经常需要引用VS IDE里已经定义好的菜单。例如,如果想在“工具”菜单下添加子菜单,我们必须引用已经定义在VS IDE里的“工具”这个菜单。当然, “工具”菜单和其他菜单(包括我们自己的菜单)的定义方式是一样的:

代码语言:javascript
复制
<Group guid="guidSimpleCommandCmdSet" id="MyMenuGroup" priority="0x0600">  <Parent guid="guidSHLMainMenu" id="IDM_VS_MENU_TOOLS"/></Group>

Parent子节点指定了由Group元素定义的逻辑容器应该被放在哪个位置。guidSHLMainMenu 代表VS IDE的主菜单的逻辑容器,IDM_VS_MENU_TOOLS 表示“工具”菜单项的ID。也许你已经猜到了,有上千个和VS IDE相关的GUID和ID。

可以用Extern节点来访问它们:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><CommandTable xmlns="..." xmlns:xs="...">  <Extern href="stdidcmd.h" mce_href="stdidcmd.h"/>  <Extern href="vsshlids.h" mce_href="vsshlids.h"/>  <Extern href="msobtnid.h" mce_href="msobtnid.h"/>  <!-- ... --></CommandTable>

Extern节点用于引用已经定义好的GUID和ID。.h文件是标准的c++头文件,里面定义了很多标识符和宏,把这些头文件引用进来之后,就可以在vsct文件的任何地方引用已经定义好的GUID和ID了,就像我们定义在Symbols节点里的一样。

这些头文件位于VS 2008 SDK根目录的VisualStudioIntegration\Common\Inc子目录下面:

文件

内容

stdidcmd.h

包含Visual Studio里公开的所有命令的ID。其中,用于菜单命令的ID用cmdid作为前缀,用于标准编辑器命令的ID用ECMD_prefix作为前缀,还包括一些其他的命令ID

vsshlids.h

包含Visual Studio Shell的菜单命令的ID

msobtnid.h

包含标准的Microsoft Office命令(其中很多命令用在VS IDE里,例如剪切、复制、粘贴)

如果你有耐心看一下这几个文件的话,你就会在vsshlids.h文件里找到guidSHLMainMenuIDM_VS_MENU_TOOLS的定义:

代码语言:javascript
复制
...DEFINE_GUID (guidSHLMainMenu,  0xd309f791, 0x903f, 0x11d0, 0x9e, 0xfc, 0x00, 0xa0, 0xc9, 0x11, 0x00, 0x4f);...#define IDM_VS_MENU_TOOLS 0x0085...

Commands

毫无疑问,vsct文件里最重要的节点就是Commands了。这个节点用来定义命令:

代码语言:javascript
复制
<Commands package="...">  <Groups/>  <Menus/>  <Buttons/>  <Combos/>  <Bitmaps/></Commands>

任何一个命令都必须从属于IDE本身或者从属于某个Package。一个程序集可以包括一个或多个Package,为了指定Command所在的Package,Commands节点的package属性必须是相应package的GUID。通常情况下,我们的程序集里只包含一个Package,所以我们通常在把VSPackage向导帮我们生成的Package的ID作为package属性的值:

代码语言:javascript
复制
<Commands package="guidSimpleCommandPkg">  <!-- ... --></Commands>

Commands节点下包含一些子节点,每一个都有自己的功能:

Groups

在Groups下,用子节点Group元素来定义所谓的命令组。一个命令组是一个逻辑容器,里面包含了功能相近的命令。例如,“生成解决方案”、“重新生成解决方案”和“清理解决方案”这几个菜单属于同一个组:它们位于VS主菜单的“生成”菜单下面,或者某个解决方案的右键菜单中:

image
image
image
image

我们并不是把单独的命令直接放到一个已经存在的菜单下面,而是把一个命令组放进去。属于这个组中的每个命令都会显示在相关的菜单下面,命令组可以看做是重用命令的一种方式。

Menus

在Menus下,用Menu子节点定义菜单,菜单有多种表现形式,最常用的有:

  1. 标准菜单:例如VS IDE中的文件、编辑、视图菜单。
  2. 上下文菜单:当在某些对象上点击鼠标右键时,弹出上下文菜单。
  3. 工具条:多个命令可以放在一行里。

Buttons

在Buttons节点里可以定义多个Button节点,一个Button代表用户可以交互的一个UI。不过,“Button”这个名字很容易让我们误解,因为我们通常所说的“Button”代表的是在表单上可以点击的按钮。但是在这里,“Button”的含义更像是一个菜单项。在vsct文件里,我们可以定义几种类型的Button:

  1. 标准按钮:用来执行命令的菜单项。
  2. 菜单按钮:用来显示子菜单。
  3. 下拉按钮:例如VS IDE里的Undo和Redo。
  4. “Swatch”按钮:用于显示像字体颜色选择器之类的按钮。

Combos

Combos节点下可以定义多个Combo节点。一个Combo节点用于显示在Combo box里的命令。我认为理解这个需要一定的vsx基础,所以我会在晚些时候再来说明这个概念。在我写这篇文章的时候,VSCT的文档里有一个小错误:它里面说到Combo节点是Commands节点的直接子节点,但实际上正确的结构是Commands、Combos和Combo。所幸,vsct的智能提示是正确的。

Bitmaps

工具条和菜单如果没有图标的话,对用户来说就太索然无味了。Bitmaps节点就是用来定义图标的。图片可以来自于外部文件或者package的资源文件。

可以用多种格式的图片,例如bmp、gif、png。但是对于这几种图片来说,不能用同一种使用方式。例如,我在用32位bmp图片的时候遇到了问题,如果在显示设置里用了120DPI的话,原本16*16像素的图片会被拉伸成20*20的,在拉伸后的图片里自动添加了一些带颜色的像素;但是如果用png图片的好,拉伸后的图片看起来就很圆滑。在某些情况下只有特定格式的图片才能被支持(我不清楚这到底是一个bug还是vs的特性):例如对于工具窗的图标来说,png图片是不支持的(如果用了png,并不会显示图标),只支持24位的以紫红色作为透明色的bmp图片。

所以,如果在用图标时遇到了问题了,不妨换几种图片格式试试看。

定义Command

为了成功的在VS IDE里添加命令,我们至少需要一个Group和一个Button节点,如果我们还想添加图标的话,我们还需要至少一个Bitmap节点。如果我们不想简单的把命令组添加到VS已经定义好的菜单下的话,我们还需要Menu节点。

MenuGroupButton节点有一些共有的属性和子节点。下表是这些属性:

属性

描述

guid

元素标识符的GUID部分,必填。

id

元素标识符的uint部分,必填。

priority

表示元素排列顺序的数字,可选项。数字越小,位置越靠前。但是我们并不知道所有元素的priority的值,所以用这个属性并不能保证可以精确的排列元素。

type

确定元素的外观和布局的可选项,但Group节点不包含这个属性。

除了Bitmap之外,Commands的其他子节点都有如下的子节点:

子节点

描述

Parent

该元素的上级。在第13篇文章里我提到过一个命令可以附加到一个或多个菜单项上。在这里你可以定义0个或1个Parent元素。如果想把一个命令附加到一个以上的菜单时,可以用 CommandPlacement元素(稍后我们会提到)。 Parent元素用guid和id属性来标识上级元素。对于Button来说,它的Parent必须是Group;对于Group来说,它的Parent必须是Menu。

Annotation

添加注释,可选项。注释可以是简单的文本,也可以是嵌套的结构。

MenuButtonCombo的子节点如下:

子节点

描述

CommandFlag

可以包含0个或多个该节点。某些标记只有和特定的标记联合起来使用时才有效,例如, DynamicVisibility和DefaultInvisible两个标记表示在vs启动的时候,对应的菜单项不显示。

Strings

这个节点包括几个子节点,表示对应元素的文本。至少需要包括一个ButtonText子节点,用于定义对应元素的文本标题。另外,还可以有ToolTipText、MenuText、CommandName以及其他子节点。更多细节可以参考vsct的schema。

Icon

只有Button元素才能包含该子节点,用于定义和Button相关的图标。

定义Bitmap

Commands节点下的Bitmaps节点用来定义菜单和工具条项中用到的图片。每一个图片用一个Bitmap元素定义。Bitmap元素里引用一个16*16像素的图片,或者一个16*N的bitmap strip,其中N是16的倍数。一个bitmap由一个GUID标识,但这个GUID并不是package的ID,也不是command set的ID。我们用基于1的数字来指定bitmap strip中的一个特定图片。

像command和menu的ID一样,我们也在Symbols里面定义bitmap的ID。例如,如果我们用VSPackage向导创建了一个带有工具窗的package的话,在vsct文件里我们可以看到如下定义:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><CommandTable xmlns="..." xmlns:xs="...">  <!-- Extern elements -->  <Commands package="...">    <!-- Menus, Groups and Buttons -->    <Bitmaps>      <Bitmap guid="guidImages" href="Resources\Images_32bit.bmp" mce_href="Resources\Images_32bit.bmp"        usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>    </Bitmaps>  </Commands>  <Symbols>    <GuidSymbol name="guidImages" value="{...}" >      <IDSymbol name="bmpPic1" value="1" />      <IDSymbol name="bmpPic2" value="2" />      <IDSymbol name="bmpPicSearch" value="3" />      <IDSymbol name="bmpPicX" value="4" />      <IDSymbol name="bmpPicArrows" value="5" />    </GuidSymbol>  </Symbols></CommandTable>

在Symbols节点下定义了Bitmap专用的GUID(guidImages),并且也用基于1的数字定义了图片在bitmap strip中的索引。在上面这个例子里,bmpPicSearch是strip中的第3个图片。

Bitmaphref属性指定了图片文件的位置,是相对于vsct文件的位置。usedList属性指定bitmap strip里可用的图片。如果我们想把一个Button的图标设置成第三个图片,我们可以用下面的代码:

代码语言:javascript
复制
<Button ...>  <Icon guid="guidImages" id="bmpPicSearch" > </Button>

创建菜单的一些例子

在讨论了vsct的Groups、Menus和Buttons之后,让我们来看一些例子。

创建一个主菜单级别的命令

VSPackage向导可以帮我们把菜单放到如下位置:如果我们创建一个简单的命令的话,向导会把菜单放到“工具”菜单下;如果我们创建一个简单的工具窗的话,向导会把菜单放到“视图”菜单下。然而,在很多情况下我们需要把菜单放到VS的主菜单里。该怎么做呢?

现在我们要在vs的主菜单上添加一个“HowToPackage”的菜单,并且包含两个菜单命令。我们需要按照下面的步骤来做:

  1. 第一步:在Symbols节点下,添加一个GuidSymbol节点,在这里定义我们需要用到的符号。
  2. 第二步:在Menus节点下,添加一个Menu节点,用来定义显示在主菜单里的菜单,并把它的Parent设置成一个主菜单级别的Group。
  3. 第三步:在Groups节点下,添加一个Group节点,用来定义我们的两个菜单命令的组。并把Parent设置成第二步里添加的Menu的id。
  4. 第四步:在Buttons节点下,添加两个Button节点,用于定义这两个命令。并且把Parent设置成第三步里添加的Group的id。

对应的vsct文件的内容如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><CommandTable xmlns="..." xmlns:xs="...">  <Extern href="stdidcmd.h" mce_href="stdidcmd.h"/>  <Extern href="vsshlids.h" mce_href="vsshlids.h"/>  <Extern href="msobtnid.h" mce_href="msobtnid.h"/>  <Commands package="...">    <Menus>      <Menu guid="guidHowToPackageCmdSet" id="TopLevelMenu" priority="0x100"         type="Menu">        <Parent guid="guidSHLMainMenu" id="IDG_VS_MM_BUILDDEBUGRUN" />        <Strings>          <ButtonText>HowToPackage</ButtonText>          <CommandName>HowToPackage</CommandName>        </Strings>      </Menu>    </Menus>      <Groups>      <Group guid="guidHowToPackageCmdSet" id="TopLevelMenuGroup"         priority="0x0600">        <Parent guid="guidHowToPackageCmdSet" id="TopLevelMenu"/>      </Group>    </Groups>         <Buttons>      <Button guid="guidHowToPackageCmdSet" id="cmdFirstCommand" priority="0x0100"         type="Button">        <Parent guid="guidHowToPackageCmdSet" id="TopLevelMenuGroup" />        <Strings>          <CommandName>cmdidFirstCommand</CommandName>          <ButtonText>First Command</ButtonText>        </Strings>      </Button>      <Button guid="guidHowToPackageCmdSet" id="cmdSecondCommand"         priority="0x0101" type="Button">        <Parent guid="guidHowToPackageCmdSet" id="TopLevelMenuGroup" />        <Strings>          <CommandName>cmdidSecondCommand</CommandName>          <ButtonText>Second Command</ButtonText>        </Strings>      </Button>    </Buttons>    </Commands>    <Symbols>    <GuidSymbol name="guidHowToPackageCmdSet"       value="{8D7B9CB3-3591-47f9-B104-B7EB173E0F03}" >      <IDSymbol name="TopLevelMenu" value="0x0100" />      <IDSymbol name="TopLevelMenuGroup" value="0x0200" />      <IDSymbol name="cmdFirstCommand" value="0x0300" />      <IDSymbol name="cmdSecondCommand" value="0x0301" />    </GuidSymbol>    <!-- Other Guids for the package -->  </Symbols>  </CommandTable>

正如你看到的那样,为了实现这个简单的功能,我们写了好多代码。在菜单的定义那里,我把Parent里用到的ID高亮显示了。如果运行起这个Package,会看到在“生成”和“调试”菜单中间,多了一个新的菜单:

image
image

这是由Menu的Parent属性和priority属性决定的:

代码语言:javascript
复制
<Menu guid="guidHowToPackageCmdSet" id="TopLevelMenu" priority="0x100"     type="Menu">  <Parent guid="guidSHLMainMenu" id="IDG_VS_MM_BUILDDEBUGRUN" />  <!-- ... --></Menu>

IDG_VS_MM_BUILDDEBUGRUN是包含“生成”和“调试”菜单的逻辑组,priority属性值0x100使我们的菜单显示在“调试”之前。如果把priority的值改成0x700的话,我们的菜单就会移到“调试”菜单的后面:

image
image

在看到Button定义的代码之后,你也许会觉得Group的存在并不必要:为什么不把Button的Parent直接设置成Menu呢:

代码语言:javascript
复制
<Button ...>  <Parent guid="guidHowToPackageCmdSet" id="TopLevelMenu" />  <!-- ... --></Button>

把Button的定义改了以后,会发现HowToPackage菜单消失了。这是因为button的parent不能直接是menu,它的parent必须是group才行。正是由于HowToPackage菜单没有任何子菜单,所以它不显示了。

在一个菜单里分隔菜单命令

如果我们在一个菜单下放一个以上的group,vs会在group直接插入一个分隔符。现在让我们在上面已经创建的vsct文件里再添加一个含有两个命令的group:

  1. 第一步:为新的group和button添加新的Symbols。
  2. 第二步:添加一个新的Group。
  3. 第三步:添加两个新的Button。

修改后的vsct文件如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><CommandTable xmlns="..." xmlns:xs="...">  <!-- Extern elements -->  <Commands package="...">    <!-- Menus section unchanged -->      <Groups>      <!-- New group added -->      <Group guid="guidHowToPackageCmdSet" id="TopLevelMenuGroup2"         priority="0x0600">        <Parent guid="guidHowToPackageCmdSet" id="TopLevelMenu"/>      </Group>    </Groups>       <Buttons>      <!-- New buttons added -->      <Button guid="guidHowToPackageCmdSet" id="cmdThirdCommand" priority="0x0102"        type="Button">        <Parent guid="guidHowToPackageCmdSet" id="TopLevelMenuGroup2" />        <Strings>          <CommandName>cmdidThirdCommand</CommandName>          <ButtonText>Third Command</ButtonText>        </Strings>      </Button>      <Button guid="guidHowToPackageCmdSet" id="cmdFourthCommand"         priority="0x0102" type="Button">        <Parent guid="guidHowToPackageCmdSet" id="TopLevelMenuGroup2" />        <Strings>          <CommandName>cmdidFourthCommand</CommandName>          <ButtonText>Fourth Command</ButtonText>        </Strings>      </Button>    </Buttons>  </Commands>    <Symbols>     <GuidSymbol name="guidHowToPackageCmdSet" value="{...}" >      <!-- New IDSymbols added -->      <IDSymbol name="TopLevelMenuGroup2" value="0x0201" />      <IDSymbol name="cmdThirdCommand" value="0x0302" />      <IDSymbol name="cmdFourthCommand" value="0x0303" />    </GuidSymbol>    <!-- Other Guids for the package -->  </Symbols>  </CommandTable>

运行起来后的效果如下图:

image
image

为菜单添加图标

如果我们想给菜单添加图标,我们需要定义个Bitmap节点,并且给Button节点添加相应的Icon属性:

  1. 第一步:为Bitmap strip添加一个ID。
  2. 第二步:添加Bitmap节点,并且设置可用的图片。
  3. 第三步:为Button添加Icon属性。

修改后的vsct文件如下:

代码语言:javascript
复制
<?xml version="1.0" encoding="utf-8"?><CommandTable xmlns="..." xmlns:xs="...">  <!-- Extern elements -->  <Commands package="...">    <!-- Menus section unchanged -->    <!-- Groups section unchanged -->    <Buttons>      <Button guid="guidHowToPackageCmdSet" id="cmdFirstCommand" priority="0x0100"         type="Button">        <!-- Icon added, other children unchanged -->        <Icon guid="guidImages" id="bmpPic1" />      </Button>      <Button guid="guidHowToPackageCmdSet" id="cmdSecondCommand"         priority="0x0101" type="Button">        <!-- Icon added, other children unchanged -->        <Icon guid="guidImages" id="bmpPic2" />      </Button>      <Button guid="guidHowToPackageCmdSet" id="cmdThirdCommand" priority="0x0102"         type="Button">        <!-- Icon added, other children unchanged -->        <Icon guid="guidImages" id="bmpPicX" />      </Button>      <Button guid="guidHowToPackageCmdSet" id="cmdFourthCommand"         priority="0x0102" type="Button">        <!-- Icon added, other children unchanged -->        <Icon guid="guidImages" id="bmpPicArrows" />      </Button>    </Buttons>      <Bitmaps>       <!-- A new Bitmap added -->      <Bitmap guid="guidImages" href="Resources\Images_24bit.bmp"         usedList="bmpPic1, bmpPic2, bmpPicSearch, bmpPicX, bmpPicArrows"/>    </Bitmaps>  </Commands>    <Symbols>    <!-- New GuidSymbol section added -->    <GuidSymbol name="guidImages" value="{...}" >      <IDSymbol name="bmpPic1" value="1" />      <IDSymbol name="bmpPic2" value="2" />      <IDSymbol name="bmpPicSearch" value="3" />      <IDSymbol name="bmpPicX" value="4" />      <IDSymbol name="bmpPicArrows" value="5" />    </GuidSymbol>    <!-- Other Guids for the package -->  </Symbols>  </CommandTable>

运行后的效果如下图:

image
image

试一下CommandFlag

CommandFlag节点可以定义命令的一些行为。让我们看一个简单的例子:为第一个命令添加TextOnly标记,为第三个命令添加DefaultDisabled 标记:

代码语言:javascript
复制
<Buttons>  <Button guid="guidHowToPackageCmdSet" id="cmdFirstCommand" priority="0x0100"     type="Button">    <!-- CommandFlag added, other children unchanged -->    <CommandFlag>TextOnly</CommandFlag>  </Button>  <Button guid="guidHowToPackageCmdSet" id="cmdThirdCommand" priority="0x0102"     type="Button">    <!-- CommandFlag added, other children unchanged -->    <CommandFlag>DefaultDisabled</CommandFlag>  </Button>

运行后的效果如下图:

image
image

小结

在这篇文章里,我们围绕着vsct文件谈论了Visual Studio的Command table。在生成VSPackage时,vsct文件被编译到cto文件里,并且作为嵌入的资源添加到Package程序集里。通过regpkg.exe注册到VS里之后,VS就知道在启动时应该加载哪些菜单项了。

vsct文件是旧版的ctc文件的替代品,在这个文件里,最重要的部分是Commands节点,在这个节点里可以定义命令以及相关的Menu、Group、Button、Combo和Bitmap元素。IDs定义在Symbols节点里。利用Extern元素,我们可以引用VS预定义的头文件。

在这篇文章的第二部分,我们用几个例子来说明如何定义vsct文件。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2010-06-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • VSCT文件的结构
  • 创建菜单的一些例子
  • 小结
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档