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

如何为图片使用单一资源组件,以及在同一 .NETCF 解决方案中混合 C# 和 VB

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2009年6月4日

GPL3

6分钟阅读

viewsIcon

16052

代码片段展示了实现此功能时的步骤和问题解决方法

引言

将应用程序使用的图像和/或文本打包到单个资源组件中,并将其包含到主程序集中,这对应用程序来说非常有吸引力,因为它使部署集更加紧凑。此外,从代码中加载这些图像出错的可能性要小得多,因为否则会有大量图像散落在某个文件夹中。

此外,在处理完整应用程序时,有时有必要混合使用 C# 和 VB,这可能是由于最终用户的要求,或者需要与 API 和/或旧版库调用进行接口,而其中一些参数对特定语言来说是特定的,找到等效项非常麻烦,或者转换根本不起作用。

本文涵盖了这两个主题,因为我遇到了这个问题,不得不深入研究才能找到一个实际可行的解决方案。基础知识很简单,但细节方面需要一些研究和额外的工具/步骤,因为 Microsoft 的文档有点含糊不清,这并不新鲜。

1. 单个资源组件作为主程序集的一部分

1.1 创建资源组件

首先,我们创建一个资源组件:右键单击解决方案,然后在弹出菜单中选择“添加组件”。这将显示不同的模板,选择一个资源文件。

您的解决方案中将列出一个额外的“资源”项,现在单击新添加的资源项。您将可以选择添加资源,请添加您的图像,在本例中,我们选择了一些预先准备好的图像。完成后,您还会看到一个 `resources` 文件夹已在您的解决方案下创建,并且您的图像将列在那里。对于此处显示的方法,请确保每个图像都设置为“**嵌入的资源**”。

1.2 从资源组件检索图像

好的,现在调用代码如下所示。高亮显示的部分显示了从资源中提取特定图像的语法。此处需要的命名空间是 `System.Reflection`(用于 Assembly 接口)和 `System.IO`(用于 Streaming)。

private void btnLoad_Click(object sender, EventArgs e)
{
    //load the images from the resource
     string start_name = "resource_sample"; // the target EXE (or DLL if mixed code mode)
     //set the basic drawing
     displayBuffy = new Bitmap(200,200);
     //set ip the screen canvas
    Graphics displayCanvas = Graphics.FromImage(displayBuffy);
     Bitmap bmp;
     // Now grab the image from the resource as a stream
    Assembly assembly = Assembly.GetExecutingAssembly();
    string strRes = start_name + ".Resources.bandera_checker.gif";
    Stream stream = assembly.GetManifestResourceStream(strRes);
    bmp = null;
    try
    {
        bmp = new Bitmap(stream);
    }
    catch { }
    stream.Close();
     //displayCanvas.DrawImage(bmp, 10, 10);
    displayCanvas.DrawImage(bmp, new Rectangle(5, 5, bmp.Width / 3, bmp.Height / 3),
        new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
     //show on the form
    Invalidate();
}  // --- end of btnLoad_Click --
private void Form1_Paint(object sender, PaintEventArgs e)
{
    if (displayBuffy != null)
    {
        Graphics g = e.Graphics;
        g.DrawImage(displayBuffy, 0, 0);
    }
}  // --- end of  Form1_Paint ---

1.3 警告和解决方法

到目前为止,没有什么令人兴奋的。当然,如果您只有一两个图像,一切都会顺利进行,但在构建大型应用程序时,需要相当多的图像,而且它们通常会随着开发过程的进行而进行修改。但在执行此操作时,代码最终将无法加载特定图像,无论您调试多深入。为了解决这个问题,我们首先需要仔细检查 EXE 中的图像名称和路径,由于进行了许多更改,有时它会被移动或未包含。名为 `ILDASM.exe` 的 Visual Studio 工具在这里非常有用,加载您的 EXE(或混合语言解决方案的 DLL)将允许您查看包含的资源的实际路径,只需单击下面的图片所示的 MANIFEST,您就会看到特定图像的实际详细信息,或者它是否实际上包含在资源组件中。`ILDASM.exe` 是框架 SDK 的一部分。如果您没有它,可以从此处下载。

fig3.jpg

有了这个,就可以轻松地仔细检查特定图像是否确实包含在资源中。我们都知道,当代码规模增长并且有大量图像正在修改时,很快就会出现它们放错位置或遇到 VS 的一个故障,导致它最终跳过它们。

2. 在同一个解决方案中混合 C# 和 VB

如开头所述,由于多种原因,可能需要混合代码,有时最终用户有一些旧代码(通常是 VB)并希望继续使用和维护它,或者出于其他类似原因。为此,我们可以轻松地将 VB 部分添加为一个 DLL,这样一切都会顺利。它可以是任何一种方式,例如,主代码在 VB 中,而伴随代码在 C# 中,反之亦然。在示例中,C# 将是主代码,伴随代码将是 VB。

本质上,我们需要做的就是向当前解决方案添加另一个使用其他语言(示例中为 VB)的项目,添加对伴随代码的引用,并使用正确的语法。

2.1 创建 VB 部分

第一步是向我们当前解决方案添加另一个项目。如果您安装了默认的 VS,您将看不到添加另一个项目的选项。要启用它,请转到“工具”->“选项”->“项目和解决方案”,并确保选中“**始终显示解决方案**”,如下图所示。

fig4.jpg

现在您将看到解决方案视图,突出显示解决方案,然后在弹出菜单中单击“添加新项目”,选择 VB smart_device 类型,如下图所示。

fig5.jpg

在下一屏幕上,我们选择类型为“**类库**”,然后就可以开始了。这将使 VB 部分成为包含所需 VB 例程的 DLL。

我们的项目现在将在新添加的 VB 项目下列出一个 `class vb` 文件。在此文件中,我们可以放置我们的 VB 例程库。在实际应用中,如果我们有很多例程,将具有一些共同行为和/或处理的例程分组到相应的命名空间中是有意义的。此类代码如下所示:

' All we need is to define our little home-brewed namespace and
' we are good to go with the mix

Namespace resource_sample_VB
    Public Class VB_Class_1
        Public Sub My_add_date(ByRef this_date As Date, ByVal days_2_add As Integer)
            Dim tmp_date As Date
            tmp_date = this_date
            Try
                tmp_date = tmp_date.AddDays(days_2_add)
            Catch
                tmp_date = this_date
            End Try
            this_date = tmp_date
        End Sub
    End Class
End Namespace

2.2 从 C# 代码调用 VB

最后,我们需要从主项目(C#)调用此 VB 代码。由于我们将 VB 代码制作为类库,因此代码将被编译成 DLL。我们需要此 DLL 可供主项目使用。为此,需要添加对 VB DLL 的引用,如下图所示:

fig7.jpg

这里有一个小问题,即在浏览添加 VB DLL 的引用时,起初不会有这样的 DLL,因为 VB 项目尚未构建。一个快速的解决方法是突出显示 `vb` 项目,并在“生成”菜单中“**生成**”它,之后您可以转到引用并浏览 DLL。

最后,从 C# 调用它的语法如下:

.
.
.
using System.Reflection; // Needed for Assembly
using System.IO;         // Needed for Stream
using resource_sample_VB_pieces.resource_sample_VB; // from our VB section
.
.
.
        private void btn_Add2Date_Click(object sender, EventArgs e)
        {
           // instantiate the VB class
           VB_Class_1 vb_tools = new VB_Class_1();

           DateTime thisDate = DateTime.Parse (textDate.Text);

           //call the VB method
           vb_tools.My_add_date(ref thisDate, Int32.Parse( textDays.Text ));
           //print out the result carried out by VB
           LblResult.Text = thisDate.ToString("d");


        } // --- end of btn_Add2Date_Click ---

2.3 代码的简单输出

在我们的示例代码中,`btnLoad_Click` 从资源组件加载图像,而 `btn_Add2Date_Click` 按钮将 `textbox` 中的值传递给 VB,然后打印出简单的日期计算结果。

fig6.jpg

最后的思考 

从统计学上讲,旧的 VB 代码通常用于遗留代码和/或最终用户希望维护它。上面所示的混合代码允许涵盖这种情况,即首选的 C# 与 VB 代码一起运行。此外,资源组件或其他一组资源也可以放在 DLL 中,以提高内存效率。

当然,这并不是完成此任务的唯一方法,但它是经过测试且有效的。

历史

  • 2009 年 6 月 4 日:初次发布
© . All rights reserved.