设为首页收藏本站Access中国

Office中国论坛/Access中国论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

1234下一页
返回列表 发新帖
查看: 9039|回复: 33
打印 上一主题 下一主题

【示例】WORD下实现多窗口TASKPAN

[复制链接]
跳转到指定楼层
1#
发表于 2014-3-22 16:08:57 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
  示例代码包含一个应用程序WordDocEditTimer,它维护着Word文档的一个编辑次数列表。本节将详细解释这个应用程序的代码,因为该应用程序演示了前面介绍的所有内容,还包含一些有益的提示。
  这个应用程序的一般操作是只要创建或加载了文档,就启动一个链接到文档名称上的计时器。如果关闭文档,该文档的计时器就暂停。如果打开了以前计时的文档,计时器就恢复。另外,如果使用Save As把文档保存为另一个文件名,计时器就更新为使用新文件名。
这个应用程序是一个Word应用程序级的插件,使用一个定制任务面板和一个ribbon菜单。
ribbon菜单包含一个按钮和一个复选框,按钮用于开关任务面板,复选框用于暂停当前活动的文档的计时器。包含这些控件的组添加到Home ribbon选项卡的最后。任务面板显示一组活动的计时器。

效果如下:



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享分享 分享淘帖 订阅订阅
推荐
 楼主| 发表于 2014-3-22 16:17:36 | 只看该作者
  因此,每个计时器都可以通过文档引用或文档名来定位。这是必要的,因为文档引用可以跟踪文档名的变化(这里没有可用于监控文档名变化的事件),文档名允许跟踪关闭、再次打开的文档。
  ThisAddIn类还维护一个CustomTaskPane对象列表(如前所述,Word中的每个窗口都需要一个CustomTaskPane对象):
  1. private List < Tools.CustomTaskPane > timerDisplayPanes;
复制代码
  插件启动时,ThisAddIn_Startup()方法执行了几个任务。首先它初始化两个集合:
  1. private void ThisAddIn_Startup(object sender, System.EventArgs e)
  2. {
  3. // Initialize timers and display panels
  4. documentEditTimes = new Dictionary < string, DocumentTimer > ();
  5. timerDisplayPanes = new
  6. List < Microsoft.Office.Tools.CustomTaskPane > ();
复制代码





回复 支持 1 反对 0

使用道具 举报

34#
 楼主| 发表于 2014-3-23 16:22:55 | 只看该作者
Amas 发表于 2014-3-22 22:32
自己试了试,基本成功。
环境:Win8.1 + VS2013 + Office2013
可能是代码版本问题,我在VS2013稍许 ...

做得非常之好,写个教程吧..
33#
发表于 2014-3-22 22:32:50 | 只看该作者



自己试了试,基本成功。
环境:Win8.1 + VS2013 + Office2013
可能是代码版本问题,我在VS2013稍许修改了几处,基本能运行。因水平有限,只有理解到这个程度,所以出现莫名其妙错误时不要骂我哟。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

评分

参与人数 1V币 +5 收起 理由
faunus + 5 (V币)优秀原创教程、管理建议(1-5分)

查看全部评分

32#
 楼主| 发表于 2014-3-22 17:33:09 | 只看该作者
这就完成了这个例子中的代码。这个例子说明了如何使用ribbon和任务面板控件,如何维护多个Word文档中的任务面板。
31#
 楼主| 发表于 2014-3-22 17:32:50 | 只看该作者
对于每个监控器,把一个列表项添加到列表框中,其中包含了文档名和总编辑时间:
  1. // Add item
  2. this.timerList.Items.Add(string.Format("{0}: {1}", documentName,
  3. documentEditTimes[documentName].EditTime +
  4. (documentEditTimes[documentName].IsActive ?
  5. (DateTime.Now - documentEditTimes[documentName].LastActive) :
  6. new TimeSpan(0))));
  7. }
  8. }
  9. }
复制代码
30#
 楼主| 发表于 2014-3-22 17:32:29 | 只看该作者
调整了文档编辑计时器后,生成一个列表。代码还会检测引用的文档是否加载了,对于没有加载的文档,把IsActive属性设置为false,暂停该文档的计时器。这也是防御性编程方式:
  1. // Create new list
  2. foreach (string documentName in documentEditTimes.Keys)
  3. {
  4. // Check to see if doc is still loaded
  5. bool isLoaded = false;
  6. foreach (Word.Document doc in
  7. Globals.ThisAddIn.Application.Documents)
  8. {
  9. if (doc.Name == documentName)
  10. {
  11. isLoaded = true;
  12. break;
  13. }
  14. }
  15. if (!isLoaded)
  16. {
  17. documentEditTimes[documentName].IsActive = false;
  18. documentEditTimes[documentName].Document = null;
  19. }
复制代码
29#
 楼主| 发表于 2014-3-22 17:32:09 | 只看该作者
对于未监控的文档,需要创建一个新的监控器:
  1. // Add monitor if not monitored
  2. if (!isMonitored)
  3. {
  4. Globals.ThisAddIn.MonitorDocument(doc);
  5. }
  6. 名称改变的文档需要通过用于旧文档的监控器重新关联起来:
  7. // Rename if necessary
  8. if (requiresNameChange)
  9. {
  10. documentEditTimes.Remove(oldName);
  11. documentEditTimes.Add(doc.Name, oldNameTimer);
  12. }
  13. }
复制代码
28#
 楼主| 发表于 2014-3-22 17:31:50 | 只看该作者
如果文档名不匹配,就比较文档引用,以检测对文档名的修改,如下面的代码所示:
  1. else
  2. {
  3. if (documentEditTimes[documentName].Document == doc)
  4. {
  5. // Monitored, but name changed!
  6. oldName = documentName;
  7. oldNameTimer = documentEditTimes[documentName];
  8. isMonitored = true;
  9. requiresNameChange = true;
  10. break;
  11. }
  12. }
  13. }
复制代码
27#
 楼主| 发表于 2014-3-22 17:31:30 | 只看该作者
接着检查监控器。这个方法迭代Globals.ThisAddIn.Application.Documents集合中的每个文档,确定文档是被监控、未被监控、或被监控了但在上次刷新时改变了文件名。
要找出被监控的文档,只需比较当前的文档名和键的documentEditTimes集合中的文档名:
  1. // Ensure all docs are monitored
  2. foreach (Word.Document doc in Globals.ThisAddIn.Application.Documents)
  3. {
  4. bool isMonitored = false;
  5. bool requiresNameChange = false;
  6. DocumentTimer oldNameTimer = null;
  7. string oldName = null;
  8. foreach (string documentName in documentEditTimes.Keys)
  9. {
  10. if (doc.Name == documentName)
  11. {
  12. isMonitored = true;
  13. break;
  14. }
复制代码
26#
 楼主| 发表于 2014-3-22 17:31:13 | 只看该作者
RefreshDisplay()方法也从ThisAddIn中调用,如前所述。考虑到该方法的任务,这是一个相当复杂的方法,它还检查被监控文档的列表,与已加载文档的列表比较,并解决出现的问题。这段代码在VSTO应用程序中常常是必不可少的,因为COM Office对象模型的接口偶尔不能像期望的那样工作。这里的规则是防御式编码。
该方法首先清除timerList列表框中的当前计时器列表:
  1. internal void RefreshDisplay()
  2. {
  3. // Clear existing list
  4. this.timerList.Items.Clear();
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|站长邮箱|小黑屋|手机版|Office中国/Access中国 ( 粤ICP备10043721号-1 )  

GMT+8, 2024-11-29 04:33 , Processed in 0.085126 second(s), 38 queries .

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表