给ribbon添加按钮是一项比较繁琐的工作,其中需要涉及大量sharepoint内部的东西:
1.首先添加一个Empty Element文件,sharepoint默认的ribbon按钮都是在C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\GLOBAL\XML\CMDUI.XML定义的,我们可以参照系统的定义来做我们的自定义按钮,参照http://msdn.microsoft.com/en-us/library/ee537543(office.14).aspx。
2.这里分两种情况,一种是直接给ribbon里添加没有的按钮,这种情况请参照网址:http://www.cnblogs.com/greeny/archive/2010/09/15/1827104.html,
还有一种就是要修改原有的Button,这是我们现在的情况:想在Editing Tool的Insert项的Picture按钮里添加一个名叫FromCapture的按钮,
这个Picture按钮其实是一个SplitButton按钮,下属的项目都是从属于这个按钮,
所以要修改它就有别于上面网址提到的方法,这里我们需要把整个Picture SplitButton用我们自己的覆盖。
3.我们只要新增一个Button,所以系统量来的两个Button都需要重用,用firebug分析后我们在CMDUI.XML里查找Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromAddress,把其所在的SplitButton复制下来:
<SplitButton
Id="Ribbon.EditingTools.CPInsert.Media.Image"
Alt="$Resources:core,ButInsertImageAlt;"
Command="InsertImage"
CommandMenuOpen="InsertImageMenuOpen"
CommandMenuClose="InsertImageMenuClose"
Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-176" Image16by16Left="-224"
Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-192" Image32by32Left="-448"
LabelText="$Resources:core,cui_ButInsertImage;"
MenuAlt="$Resources:core,ButInsertImageMenuAlt;"
Sequence="10"
TemplateAlias="o1"
ToolTipTitle="$Resources:core,cui_ButInsertImage;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImage;">
<Menu Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu">
<MenuSection
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image"
DisplayMode="Menu"
Sequence="10">
<Controls Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.Controls">
<Button
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromComputer"
Sequence="10"
Alt="$Resources:core,ButFromComputerAlt;"
Command="InsertImageUpload"
LabelText="$Resources:core,ButFromComputer;"
ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromComputer;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromComputer;"/>
<Button
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromAddress"
Sequence="20"
Alt="$Resources:core,ButFromAddressAlt;"
Command="InsertImageWeb"
LabelText="$Resources:core,ButFromAddress;"
ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromAddress;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromAddress;"/>
</Controls>
</MenuSection>
</Menu>
</SplitButton>
4.编辑Elements.xml文件,在<Elements节点内写:
<CustomAction Id="Ribbon.Image.Image.Edit.ReplacementButton" Location="CommandUI.Ribbon">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location="Ribbon.EditingTools.CPInsert.Media.Image">
</CommandUIDefinition>
</CommandUIDefinitions>
</CommandUIExtension>
</CustomAction>
其中<CommandUIDefinition 结点的Location是指向要覆盖的控件,所以填写上述3.里SplitButton的ID,表示<CommandUIDefinition 里定义的位置是覆盖同名控件。
这个CustomAction将完成我们工作:覆盖系统的SplitButton。
5.在<CommandUIDefinition 结点内部输入第3点里的代码,更改控件ID,并添加一个我们自己的按钮代码,类似的:
<SplitButton
Id="Ribbon.EditingTools.CPInsert.Media.Image.ReplacementButton"
Alt="$Resources:core,ButInsertImageAlt;"
Command="InsertImage"
CommandMenuOpen="InsertImageMenuOpen"
CommandMenuClose="InsertImageMenuClose"
Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-176" Image16by16Left="-224"
Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-192" Image32by32Left="-448"
LabelText="$Resources:core,cui_ButInsertImage;"
MenuAlt="$Resources:core,ButInsertImageMenuAlt;"
Sequence="10"
TemplateAlias="o1"
ToolTipTitle="$Resources:core,cui_ButInsertImage;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImage;">
<Menu Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Replacement">
<MenuSection
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.Replacement"
DisplayMode="Menu"
Sequence="10">
<Controls Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.Controls.Replacement">
<Button
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromComputer.Replacement"
Sequence="10"
Alt="$Resources:core,ButFromComputerAlt;"
Command="InsertImageUpload"
LabelText="$Resources:core,ButFromComputer;"
ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromComputer;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromComputer;"/>
<Button
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromAddress.Replacement"
Sequence="20"
Alt="$Resources:core,ButFromAddressAlt;"
Command="InsertImageWeb"
LabelText="$Resources:core,ButFromAddress;"
ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromAddress;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromAddress;"/>
<Button Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.CaptureButton"
Sequence="30"
Command="ScreenshotImageUpload"
Alt="Insert Picture From Screenshot"
LabelText="From Capture"
ToolTipTitle="Insert Picture From Screenshot"
ToolTipDescription="Use a useable URL to Screenshot a Picture to Upload."
/>
</Controls>
</MenuSection>
</Menu>
</SplitButton>
这里我们的控件ID都比以前多了.ReplacementButton和旧的区分。
我们还加入了一个<Button Sequence=30表示他处于FromAdress下方,LabelText就是按钮显示的名称,这里特别要关注的属性是command属性,他表示这个按钮点击时会触发的命令。
6.定义点击FromCapture按钮会触发的命令:在</CommandUIDefinnitions>后输入:
<CommandUIHandlers>
<CommandUIHandler
Command="ScreenshotImageUpload"
CommandAction="javascript:SP.SOD.executeOrDelayUntilScriptLoaded(initialize, 'SP.js');"></CommandUIHandler>
</CommandUIHandlers>
这句话表示我们定义了一个命令,名叫ScreenshotImageUpload,这个命令会触发一个方法,名叫:initialize,这是一个我自定义的js方法,等下将会有这个方法的详细说明。
这里我解析下为说明CommandAction里要这么写,如果按钮的功能较简单,不会用到大量的js,可以直接在CommandAction=""里写入js方法,比如CommandAction="javascript:alert('Hello world!')",但是考虑到我们的功能比较复杂,需要编写大量的js,我们就可以直接写
CommandAction="javascript:方法名"这个方法名需要引用一个外部的javascript文件,这就代表我们需要引用这个文件,所以我们在<Element里还需定义一个<CustomAction来引用这个外部javascript文件,具体例如:
<CustomAction Id="fromScreenshotJS"
Location="ScriptLink"
ScriptSrc="/_layouts/ScreenshotProject/scripts/FromScreenshot.js"></CustomAction>
这里引用了FromScreenshot.js文件来调用这个点击按钮要触发的方法。
我还要解析下SP.SOD.executeOrDelayUntilScriptLoaded(initialize, 'SP.js');这句话的意思,他表示,initialize这个方法在网站下载完sp.js文件后才会被执行,为什么要这样做呢?因为这里我们的功能需要引用网站的站点名称SP.ClientContext.get_current().get_site(),而要获得这个名称就必须等网站下载完SP.js才行,所以这里进行了相应处理。
这个Elements.xml文件现在看起来像:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="Ribbon.Image.Image.Edit.ReplacementButton"
Location="CommandUI.Ribbon">
<CommandUIExtension>
<CommandUIDefinitions>
<CommandUIDefinition Location="Ribbon.EditingTools.CPInsert.Media.Image">
<SplitButton
Id="Ribbon.EditingTools.CPInsert.Media.Image.ReplacementButton"
Alt="$Resources:core,ButInsertImageAlt;"
Command="InsertImage"
CommandMenuOpen="InsertImageMenuOpen"
CommandMenuClose="InsertImageMenuClose"
Image16by16="/_layouts/$Resources:core,Language;/images/formatmap16x16.png" Image16by16Top="-176" Image16by16Left="-224"
Image32by32="/_layouts/$Resources:core,Language;/images/formatmap32x32.png" Image32by32Top="-192" Image32by32Left="-448"
LabelText="$Resources:core,cui_ButInsertImage;"
MenuAlt="$Resources:core,ButInsertImageMenuAlt;"
Sequence="10"
TemplateAlias="o1"
ToolTipTitle="$Resources:core,cui_ButInsertImage;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImage;">
<Menu Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Replacement">
<MenuSection
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.Replacement"
DisplayMode="Menu"
Sequence="10">
<Controls Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.Controls.Replacement">
<Button
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromComputer.Replacement"
Sequence="10"
Alt="$Resources:core,ButFromComputerAlt;"
Command="InsertImageUpload"
LabelText="$Resources:core,ButFromComputer;"
ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromComputer;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromComputer;"/>
<Button
Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.FromAddress.Replacement"
Sequence="20"
Alt="$Resources:core,ButFromAddressAlt;"
Command="InsertImageWeb"
LabelText="$Resources:core,ButFromAddress;"
ToolTipTitle="$Resources:core,cui_STT_title_ButInsertImageFromAddress;"
ToolTipDescription="$Resources:core,cui_STT_ButInsertImageFromAddress;"/>
<Button Id="Ribbon.EditingTools.CPInsert.Media.Image.Menu.Image.ScreenshotButton"
Sequence="30"
Command="ScreenshotImageUpload"
Alt="Insert Picture From Screenshot"
LabelText="From Screenshot"
ToolTipTitle="Insert Picture From Screenshot"
ToolTipDescription="Use a useable URL to Screenshot a Picture to Upload."
/>
</Controls>
</MenuSection>
</Menu>
</SplitButton>
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler
Command="ScreenshotImageUpload"
CommandAction="javascript:SP.SOD.executeOrDelayUntilScriptLoaded(initialize, 'SP.js');"></CommandUIHandler>
</CommandUIHandlers>
</CommandUIExtension>
</CustomAction>
<CustomAction Id="fromScreenshotJS"
Location="ScriptLink"
ScriptSrc="/_layouts/ScreenshotProject/scripts/FromScreenshot.js"></CustomAction>
</Elements>
这时如果我们部署已经可以看到按钮的效果了,但是点击没反应,因为我们还没编写initialize方法。
7.右击自动生成项目的Layouts文件夹,在Layouts文件夹下新建scripts文件夹,在scripts文件夹里新建FromScreenshot.js文件,编辑这个文件:
function ScreenshotCallback(dialogResult, returnValue) {
if (dialogResult == "1") {
RTE.Cursor.get_range().deleteContent();
var rng = RTE.Cursor.get_range().$3_0;
var doc = rng.ownerDocument;
var imgContent = doc.createElement("img");
imgContent.setAttribute("src", returnValue);
SP.UI.UIUtility.insertAfter(imgContent, rng);
}
else
{ }
}
var ctx;
var site;
var screenshotUrl = 'http://win2008web:2013/_layouts/ScreenshotProject/ScreenShotion.aspx';
function initialize() {
ctx = new SP.ClientContext.get_current();
site = ctx.get_site();
ctx.load(site);
ctx.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}
function InsertFromScreenshot() {
var options = {
url: screenshotUrl,
tite: 'Screenshot',
allowMaximize: true,
showClose: true,
900,
height: 600,
dialogReturnValueCallback: ScreenshotCallback
};
SP.UI.ModalDialog.showModalDialog(options);
}
function onQuerySucceeded(sender, args) {
screenshotUrl = site.get_url() + '/_layouts/ScreenshotProject/ScreenShotion.aspx' + '?Url=' + window.location;
InsertFromScreenshot();
}
function onQueryFailed(sender, args) {
alert('Request filed. Janq ' + args.get_message() + '\n' + args.get_stackTrace());
}
这段代码核心思想是:初始化成功后,调用InsertFromScreenshot方法,打开一个模态窗口,这个窗口指向一个叫ScreenShotion.aspx的页面,当这个页面回调时,调用ScreenshotCallback方法,
if (dialogResult == "1") {
RTE.Cursor.get_range().deleteContent();
var rng = RTE.Cursor.get_range().$3_0;
var doc = rng.ownerDocument;
var imgContent = doc.createElement("img");
imgContent.setAttribute("src", returnValue);
SP.UI.UIUtility.insertAfter(imgContent, rng);
}
else
{ }
dialogResult是回调参数,当回调参数是“1”时,在编辑器目前鼠标停留处插入returnValue参数。
至此,我们的按钮已经完成,部署后点击按钮,已经可以跳出模态窗口,下面我们来编写这个叫ScreenShotion.aspx的Application页面。
下面涉及的就是于截图功能相关的内容:
8.在Layouts的项目文件夹下新建一个ApplicationPage名叫:ScreenShotion.aspx,参考项目编写这个ApplicationPage
最重要的是截图完成后要做回调:
this.Page.Response.Clear();
this.Page.Response.Write("<script>window.frameElement.commonModalDialogClose(1,'" + destUrl + "')</script>");//SP.UI.DialogResult.OK
this.Page.Response.End();
http://odyniec.net/projects/imgareaselect/