sharepoint给ribbon添加按钮并提供截图功能

给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/

原文地址:https://www.cnblogs.com/lucky_dai/p/1921716.html