在Outlook 2007/2010中的“待办事项”栏中添加一个部分?

我想在Outlook 2010(或2007)的待办事项栏中添加一个新部分。 我找到了一些代码来创建一个新的可折叠任务窗格,有人声称你无法修改待办事项栏,但我还发现了一款​​名为Add-In Express的产品,声称它可以做到这一点(虽然售价349美元,但不值得。一次性项目)。

有可能这样做吗?

经过一些研究(以及看过Add-in Express的产品文档后),我认为可以在Outlook 2007中自定义待办事项栏。

CodeProject上有一个certificate – poof-concept,它将一个“自定义”(读取自写)窗格嵌入到Outlook主窗口中。 这篇文章由Lukas Neumann撰写,可在此处获取:

Microsoft Outlook中的其他自定义面板

原则如下:

  1. 在Outlook窗口中搜索要放置自己窗口的子窗口(即待办事项栏窗口)
  2. 调整该窗口的内容大小,为控件腾出一些空间
  3. 作为孩子添加自己的窗口
  4. 将To-Do Bar窗口子类化为挂钩到该窗口的消息循环

调整示例代码基本上只需要进行两处修改:

  1. 获取正确的子窗口句柄:待办事项栏的窗口类称为“WUNDERBAR”。 此类用于多个子窗口,因此请确保还检查正确的窗口标题(“ToDoBar”)或仅按窗口标题搜索。
  2. 正确调整面板大小(简单但不总是容易;-)。

(如果找不到待办事项栏,则添加一些正确的error handling等)。

如果你熟悉Spy ++,这是一个很好的加分,因为需要找出Outlook的子窗口的类名和窗口标题。

我建议您下载示例代码并应用以下修改:

在Connect.cs中:

private const string SIBLING_WINDOW_CLASS = "NetUINativeHWNDHost"; public delegate bool EnumChildCallback(IntPtr hwnd, ref IntPtr lParam); [DllImport("User32.dll")] public static extern bool EnumChildWindows(IntPtr hWndParent, EnumChildCallback lpEnumFunc, ref IntPtr lParam); [DllImport("User32.dll")] public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] static extern int GetWindowTextLength(IntPtr hWnd); public static bool EnumChildProc(IntPtr hwndChild, ref IntPtr lParam) { StringBuilder className = new StringBuilder(128); GetClassName(hwndChild, className, 128); int length = GetWindowTextLength(hwndChild); StringBuilder windowText = new StringBuilder(length + 1); GetWindowText(hwndChild, windowText, windowText.Capacity); if (className.ToString() == "WUNDERBAR" && windowText.ToString() == "ToDoBar") { lParam = hwndChild; return false; } return true; } public void OnStartupComplete(ref System.Array custom) { if (_outlookApplication == null) return; //We were not loaded into Outlook, so do nothing //Get the instance of Outlook active explorer (= the main window) and start capturing selection changes _outlookExplorer = _outlookApplication.ActiveExplorer(); _outlookExplorer.SelectionChange += new ExplorerEvents_10_SelectionChangeEventHandler(outlookExplorer_SelectionChange); //Find Outlook window handle (HWND) IntPtr outlookWindow = FindOutlookWindow(); if (outlookWindow == IntPtr.Zero) return; // Find ToDoBar window handle IntPtr todoBarWindow = IntPtr.Zero; EnumChildCallback cb = new EnumChildCallback(EnumChildProc); EnumChildWindows(outlookWindow, cb, ref todoBarWindow); if (todoBarWindow == IntPtr.Zero) return; //Find sibling window handle (HWND) //Sibling window is the window which we are going to "cut" to make space for our own window IntPtr siblingWindow = SafeNativeMethods.FindWindowEx(todoBarWindow, IntPtr.Zero, SIBLING_WINDOW_CLASS, null); if (siblingWindow == IntPtr.Zero) return; //Initialise PanelManager and assign own panel to it _panelManager = new PanelManager(outlookWindow, siblingWindow); _customPanel = new MyPanel(); _panelManager.ShowBarControl(_customPanel); } 

在PanelManager.cs中:

 private void ResizePanels() { if (_changingSize) return; //Prevent infinite loops _changingSize = true; try { //Get size of the sibling window and main parent window Rectangle siblingRect = SafeNativeMethods.GetWindowRectangle(this.SiblingWindow); Rectangle parentRect = SafeNativeMethods.GetWindowRectangle(this.ParentWindow); //Calculate position of sibling window in screen coordinates SafeNativeMethods.POINT topLeft = new SafeNativeMethods.POINT(siblingRect.Left, siblingRect.Top); SafeNativeMethods.ScreenToClient(this.ParentWindow, ref topLeft); //Decrease size of the sibling window int newHeight = parentRect.Height - topLeft.Y - _panelContainer.Height; SafeNativeMethods.SetWindowPos(this.SiblingWindow, IntPtr.Zero, 0, 0, siblingRect.Width, newHeight, SafeNativeMethods.SWP_NOMOVE | SafeNativeMethods.SWP_NOZORDER); //Move the bar to correct position _panelContainer.Left = topLeft.X; _panelContainer.Top = topLeft.Y + newHeight; //Set correct height of the panel container _panelContainer.Width = siblingRect.Width; } finally { _changingSize = false; } } 

概念validation是一个托管的COM加载项,而不是使用VSTO,但是一种非常类似的方法也适用于VSTO。 如果您需要任何进一步的帮助,请告诉我,因为概念validation已经需要一些有关子类化和Office加载项体系结构(IDTExtensibility2)的知识。

另请注意,这只是一个概念validation,展示了如何自定义Outlook UI的基本技术。 我的编辑远非美丽的代码;-)

您正在寻找的是一个TaskPane,而不是一个Form Region。 TaskPanes的工作方式与表单区域略有不同,它们仅在Office 2007及更高版本中可用(由于您需要2007-2010版本,因此它看起来不像是一个问题)。 如果没有其他事情,至少知道正确的术语可能会使谷歌搜索更容易一点。

这是MSDN上的自定义任务窗格概述 。

现在,至于在现有的TaskPane中添加一个部分,我不确定。 但希望这会让你更接近。

顺便提一下,顺便提一下,Add-in Express库非常棒。 让这类事情成为一项2分钟的任务。 强烈推荐 – 这可能会再次使用,因为它们使工作变得如此简单。

迈克尔,

看看Outlook表单区域。 http://msdn.microsoft.com/en-us/library/bb386301.aspx您可以使用VSTO插件添加它们。 虽然Add-in express还有一些选项可以添加它们。 网上也有不少教程。

马库斯