65.9K
CodeProject 正在变化。 阅读更多。
Home

将 Outlook 表单模板 (OFT) 转换为 Visual Studio 中的 .NET Windows 窗体

2023年5月7日

CPOL

5分钟阅读

viewsIcon

2748

如何在 VS 中将 OFT 转换为 .NET Windows 窗体

在我的一项工作项目中,我被 assigned 了开发一个独立的 Windows 窗体应用程序的任务,以取代最初使用 Visual Basic for Application (VBA) 作为数据处理的 Outlook 表单模板 (OFT) 文件。目标是为用户提供一个界面来填写所需数据,并在提交前检查其有效性。

由于原始表单有超过 500 个字段,包括文本框、下拉列表、单选按钮和复选框,因此从头开始使用 Visual Studio 窗体设计器设计新窗体会是一场噩梦。我的第一个尝试是尝试在 Outlook 中以设计模式打开原始表单,复制字段并粘贴到 Visual Studio 窗体设计器中。这不起作用 - 可能是因为剪贴板格式不同。我决定寻找一种方法来复制原始 Outlook 表单中的字段,以节省时间。

在 Visual Studio 中导入表单

我偶然发现了 这篇 MSDN 文章,它指出了在 Visual Studio 中导入 Outlook 表单的可能性,并决定尝试一下。

首先,在 Outlook 中以设计模式打开表单

添加一个新的 Outlook 表单区域,并将所有控件从原始表单粘贴到该区域

之后,将 Outlook 表单区域保存到硬盘上的一个 .OFS (Outlook Form Storage) 文件。

最后,在 Visual Studio Outlook 加载项项目中,添加一个新的 Outlook 表单区域,并选择从现有的 Outlook 表单存储文件导入

大多数向导设置都可以保留为默认值,除了 **“选择要创建的表单区域类型”** 页面和 **“哪些自定义消息类将显示此表单区域”** 选项,它们应该分别是 **Replace-all** 和 **IPM.Task.XXXX**,其中 XXXX 是你的表单区域的任何有效名称。

完成向导后,一组表单区域文件,包括 .designer.cs 文件,被添加到项目中。

导入的表单区域的设计器支持

然而,令我失望的是,尽管存在设计器类,Visual Studio 并没有在设计器中打开这个表单区域,而是直接打开了设计器类文件的代码编辑器。但是,如果在向导中,我选择了设计一个新的表单区域,Visual Studio 会允许我设计表单区域用户界面。区别体现在 **Solution Explorer** 中表单区域的图标上。

尽管这似乎是一个常见问题,并且通常可以通过重新打开 Visual Studio、清理和重新生成解决方案来修复,但在这种情况下,我无法让 FormRegion1 在设计器中打开,尽管尝试了各种变通方法。

区别似乎在于两个窗体的基类。FormRegion2 继承自 Microsoft.Office.Tools.Outlook.FormRegionBase,而 FormRegion1 继承自 Microsoft.Office.Tools.Outlook.ImportedFormRegionBase,无法在设计器中打开。实际上,虽然为 FormRegion2 生成的代码包含运行时渲染表单字段所需的所有信息,但 FormRegion1 的代码仅包含表单控件的最少类型声明,其他大部分信息在运行时从 .OFS 文件中检索。这解释了为什么设计器无法打开 FormRegion1 - 它根本无法以这种方式轻松操作。

partial class FormRegion1 : Microsoft.Office.Tools.Outlook.ImportedFormRegionBase
{
private Microsoft.Office.Interop.Outlook._DRecipientControl to;
….
        protected override void InitializeControls()
{
        this.to = (Microsoft.Office.Interop.Outlook._DRecipientControl)_
                   GetFormRegionControl(“To”);
….
        } 
….
        [System.Diagnostics.DebuggerNonUserCodeAttribute()]
byte[] Microsoft.Office.Tools.Outlook.IFormRegionFactory._
GetFormRegionStorage(object outlookItem, Microsoft.Office._
Interop.Outlook.OlFormRegionMode formRegionMode, _
Microsoft.Office.Interop.Outlook.OlFormRegionSize formRegionSize)
{
System.Resources.ResourceManager resources = _
new System.Resources.ResourceManager(typeof(FormRegion1));
return (byte[])resources.GetObject(“Survey”);
}
….
}

此时,我清楚地认识到导入的 FormRegion1 无法在设计器中打开,我必须想出一种不同的方法来复制表单字段。

导出表单控件

然后我想到一个主意,在运行时枚举表单控件,并将它们输出为 Visual Studio 可读的格式。文件格式的最佳选择是 VB6 窗体 (.frm) 文件。这种格式是人类可读的,可以很容易地从代码构建,并且可以使用 Visual Studio 2008 及更早版本中的 VB6 升级向导升级到 .NET Windows 窗体。

执行此操作的最佳位置是 FormRegionShowing 事件

private void FormRegion1_FormRegionShowing(object sender, System.EventArgs e)
{
UserForm oForm = this.OutlookFormRegion.Form;
foreach (Control ctl in oForm.Controls)
{
            if (ctl is Outlook.OlkCommandButton)
{
Outlook.OlkCommandButton cmdButton = (Outlook.OlkCommandButton)ctl;

string buttonTemplate = String.Format(@”
Begin VB.CommandButton {0}
Caption         =   “”{1}””
Height          =   {2}
Left            =   {3}
TabIndex        =   {4}
Top             =   {5}
Width           =   {6}
End”,
ctl.Name.Replace(” “, “”), escapeString(cmdButton.Caption), 
    (int)(ctl.Height * 20), (int)(ctl.Left * 20), count, (int)(ctl.Top * 20),
(int)(ctl.Width * 20));
………….
            } 
}
}

生成的按钮的 .frm 代码看起来像这样

   Begin VB.CommandButton Command1
Caption         =   “Command1″
Height          =   855
Left            =   480
TabIndex        =   3
Top             =   3480
Width           =   2175
End 

使用此方法,我最终能够生成所有原始 Outlook 模板中窗体的 VB6 等效版本,并将它们升级为 .NET 窗体。经过一些修改,升级后的窗体就可以进行进一步的开发工作了。窗体的 VBA 后置代码可以使用 Telerik 唯一的 代码转换器 工具进行升级。

转换过程中可能遇到的问题

尽管这种方法对我来说足够好用,但它远非完美。Outlook 和 VB6 为表单字段使用的可能测量单位(像素、点、twips)的差异导致生成的 VB6 表单与原始表单看起来略有不同。此外,一些导入的控件属于 Microsoft.Vbe.Interop.Forms 命名空间,而另一些则属于 Microsoft.Office.Interop.Outlook 命名空间。这导致需要在代码中使用 **dynamic** 数据类型来避免不必要的类型转换。最后,组合框中的项目不包含在 .frm 文件中,而是存储在单独的 .frx 文件中。

   Begin VB.ComboBox Combo1
Height          =   315
      ItemData        =   “Form1.frx”:0000
Left            =   3960
      List            =   “Form1.frx”:0010
TabIndex        =   5
Text            =   “Combo1″
Top             =   480
Width           =   1215
End

由于 frx 文件是二进制的,我没有尝试生成它,而是手动复制了组合框中的项目。为了简单起见,其他几个不太常见的表单控件属性也没有迁移,并在转换过程后手动设置。

有兴趣的人可以 在这里 下载用于生成 VB6 表单的原型代码。

© . All rights reserved.