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

将 VB6 gdiplus 项目转换为 .net

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.08/5 (5投票s)

2007年1月15日

13分钟阅读

viewsIcon

30217

Designer(c)2006广泛使用了GDIPLUS,以及一个免费的GDIPLUS类型库。我对GDIPLUS的能力印象深刻,但我的程序需要大位图,并且在这方面遇到了困难。根据具体尺寸,我最多可以达到17-20兆字节。该程序的目标是面料设计。

引言

我有点担心将VB6图形项目转换为.NET。老实说,这是有道理的。这相当于要进行一次彻底的重写。

BASIC程序员的好消息

我几乎写过现存的所有语言,甚至包括一些现在已经很奇怪的语言,比如PASCAL、Forth等等。我一直喜欢BASIC的简单性,但当然,它一直存在性能问题。我写了大量的汇编代码,并喜欢那种“接近”处理器的感觉。但在当今世界,你永远无法接近了。在你和最终执行之间有大量的代码。很少有操作可以在不使用框架的情况下完成。**终于,BASIC没有性能问题了**,它与C++或任何其他使用.Net框架的语言性能相同。不确定C++或C#与前几代相比表现如何。**现在每个人都面临相同的性能问题**。但是程序员只编写执行代码的**0.1%**。当你调用OpenFileDialog时,用哪种语言调用它并不重要。所以这在过去十年里基本上是一种“势利”的行为。框架和操作系统的性能比代码是用哪种语言编写的更重要。

今天,BASIC程序员可以认为他们写出的代码与任何人都一样好。顺便说一句,这是1000倍,我不确定执行的代码中有多少不是你的。这可能是10万倍。

转换向导

转换向导礼貌地提供了转换项目。在处理完每个对象后,它告诉我已成功转换项目。转换完成后,构建生成了100个错误的列表。在进行了数百次修正后,它仍然停留在100个错误。我以为我永远无法完成它。这是默认的最大值。它还在你的代码中以“注释格式”发布了大量警告。数千个警告。我的代码列表是实心绿色的。如果有一种方法可以消除它们,那将很有帮助。有一个“编译无警告”的选项,但我认为没有转换选项。警告是否足够有用以抵消删除它们的任务,这是一个问题。

'UPGRADE_ISSUE: PictureBox 属性 TheHDC.hDC 未升级。点击查看更多: 'ms-help://MS.VSExpressCC.v80/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'

'UPGRADE_ISSUE: Form 属性 THEHDC2.hDC 未升级。点击查看更多: 'ms-help://MS.VSExpressCC.v80/dv_commoner/local/redirect.htm?keyword="CC4C7EC0-C903-48FC-ACCC-81861D12DA4A"'

一些困惑?

删除所有注释的精力与修正代码的精力差不多。有些转换没有成功。例如,像“LEFT”这样的简单字符串操作现在位于不同的命名空间中,例如Microsoft.visualbasic.left,数学运算如ABS位于Math命名空间中。在上下文中转换的操作不起作用,仍然产生编译错误,但这可以通过简单的“替换”来解决。然而,Left会默认到窗体的命名空间,作为窗体的左侧位置,因此执行可能会出现故障。相同的“WORD”在窗体和模块中可能根据代码当前上下文中的命名空间默认为不同的编译器引用。

异常执行

我遇到过一个情况,例如一个语句

代码有效:
for each item in collection
dim name="XXX"
ITEM.name=whatever
end for

代码无效

dim name as string
for each item in "collection"
name="XXX"
ITEM.name=whatever
end for

如果我在循环内声明了name,代码就可以工作,因为我可能作用域在命名空间之外。我假设在循环内命名空间变成了“collection”,并且没有name属性。当我将dim移到循环外部以优化执行时,代码就失败了。这有点令人困惑,因为这段代码已经运行了很长时间。

使用“NAME”作为变量名是一个糟糕的选择,但是命名空间中有太多的名称,可能采用“MY”或“A”的约定来选择变量,例如MyName、Mywidth、Mysize或AName、AWidth、ASize,可以确保没有混淆。命名空间如此广泛,以至于跟踪起来可能会让人不知所措。

我确信其他人对此情况比我更有见解。

GDIPLUS 类型库

转换未能正确处理GDIPLUS类型库,这不是微软提供的产品,所以我从未尝试将其添加到项目中。我反正目标是实现一个标准的.Net产品。使用类型库让我熟悉了GDIPLUS的大部分内容,但其使用格式和上下文差异很大。

重载

重载对我来说是一种新的体验。GDIPLUS库设置了数十个类似的调用,如果你用浮点结构绘制一个矩形,你会有一个调用,例如RectangleF;如果你用长整型,你会有一个调用,例如RectangleL。我最初认为这是遵循.net结构,并且觉得它非常繁琐。.Net使用重载,也就是说,同一个调用接受不同类型的参数。.NET有一个非常有用的提示,可以让你逐步浏览每个“重载”,有些图形调用有30个重载。因此,与GDIPLUS库相比,你的初步困惑要少得多。尽管最终的困惑程度可能相同。在.NET命名空间中工作肯定更容易。

命名空间

任何仍然对命名空间感到困惑的人,这只是一个现代的引用,类似于类型库。输入“Application.”会带你到Application命名空间,然后它会带你浏览该“命名空间”下可用的各种类型、方法和函数。把它想象成一个巨大的搜索引擎,格式是“关键字.关键字.关键字”,关键字字符串的末尾是你选择的属性或方法。如果你能确定第一个关键字,你可能就能找到。在每个关键字处,都会列出该空间内下一个可能的选择。

通常问题更多的是“这个关键字是什么意思”。微软为每个关键字提供了工具提示。这确实相当令人印象深刻,而且大部分都相当有用。但一如既往,当你真正不理解时,你可以选择试验或研究, whichever suits you。

没有索引对象

我最终丢弃了向导转换的大部分内容。我创建了新的窗体,并将对象从旧窗体(来自转换)复制粘贴过来(我同时打开了两个项目)。这样我想确保我没有保留太多不真正属于.NET的东西,并且是向后兼容的。

我发现VB6中非常有用的“收集”索引到一组代码(如button_click(Index))的能力不再被支持。我曾广泛使用这个功能。向导将其转换为_button_1、_button_2等,但代码完全不起作用。这需要一种不同的方法。每个按钮都可以将其索引传递给一个例程,这需要为每个按钮编写代码。关键是,你必须用某种代码来处理每个项目。.Net可能有一些方法可以将事件从多个对象捕获到同一段代码,但我还没有研究过。我用我认为是“低劣”的方式编写了代码,并在每个以前索引的对象后面放置了一些代码。

警告

VB .NET增加了一些功能来帮助你保持代码的整洁。它会警告你一个声明的变量未被使用,这确实有助于你保持代码的整洁。通常当你改变代码时,清理是一个任务,我觉得这很有用。它还试图警告你一个变量在使用前未被初始化,它担心你最终会得到NULL或数据异常。它在这方面经常出错,但我倾向于初始化,这样编译器就会满意。它在某些情况下还担心它无法确定会发生什么,所以这段代码

ColorWheel.Top =.PictureBox1.MousePosition.Y - 100
ColorWheel.Left =
.PictureBox1.MousePosition.X - 100

会收到这个错误

警告 1 通过实例访问共享成员、常量成员、枚举成员或嵌套类型;将不计算限定表达式。 C:\Documents and Settings\guest1\My Documents\Visual Studio 2005\Projects\designer2007\WindowsApplication2\WindowsApplication2\ColorPick.vb 23 53 Designer2007

这段代码总是能工作,所以你最终不得不忍受这些警告。我还没有花时间去弄清楚是否可以“让它满意”。

代码

我的很多代码因为GDIPLUS类型库而损坏,我不想重新实现那部分代码,但想转向绘图命名空间。虽然这很繁琐,但并不难。GDIPLUS类型库毕竟调用了GDIPLUS(一个.NET组件),而且大部分格式的更改只是调用例程名称的直接更改。就像我说的,一旦你做到了,你就会更喜欢.NET的上下文。

一件事 “无法缩小参数”。 

.NET中的类型转换通常不像我们过去在BASIC中期望的那样积极。你可能会收到诸如“无法缩小参数”之类的错误消息。通常你只需要检查你的语句, wherever it seems complex cast the parameter yourself。当函数嵌入在参数中时,尤其会发生这种情况。我最初并没有理解这一点,而是不断地重写似乎是正确的代码。最终,你就会“明白”了,这些问题也就消失了。我遇到了类型库中的一些问题,并编写了一些奇怪的代码来强制参数正确转换。这对BASIC程序员来说已经很奇怪了,他们往往对数据类型不敏感。

VISUAL STUDIO 2005

有一些问题,它会在某些组合下挂起,我还没有确切弄清楚。有时当你在调试模式下编辑时,它会变得混乱并挂起。大多数时候它会超时并返回。总的来说,我只经历了一次致命崩溃,导致我丢失了代码,我不得不回滚到3天前的恢复点才恢复。当时我运行的是512MGB,并且进行了大量的页面交换,这可能会以不同的方式给XP带来压力。我升级到了1.5(后来升级到2.5,看看它如何影响我的位图大小),并且自那以后没有再出现崩溃。我区分崩溃和异常。在开发和执行过程中,未处理的异常都会被.Net引擎相对优雅地处理。我指的是旧意义上的崩溃,即你被致命地卡住了。

它在每次编译前都会保存代码,我还没有找到覆盖此选项的选项,这最初很恼人,因为我习惯于在实验时不对代码进行保存,并返回到以前的代码。但大多数时候,你仍然可以撤销回到原始代码。鉴于我从未丢失代码的整体经验,我将接受这种方法。

工具箱,是程序员的乐趣……你说什么呢,大部分是Windows程序员想要的东西。有几件事,没有更多的形状了。你可以用标签作为框,但仅此而已。你需要在onPaint时绘制,否则就没有。而且组合框的工作方式与Access中的应用程序基本不同。在那里,组合框是受管理的,也就是说,如果有一个在,其他的就关闭了,我还没有在.NET中找到这种技术……这并不意味着它不存在。几行代码可以达到相同的目的。菜单和快速菜单易于实现,尽管为什么它们遵循不同的模型令人困惑。快速菜单你直接管理一个集合,菜单有一个不同的“自展开”界面。

可执行文件

我还没有研究过.NET可执行文件的内部工作原理。但从外部来看,它无疑是简单的。第一次执行时,它会进行一个简单的安装。之后,它似乎会检查资源是否仍然可用,然后加载。这有一个新的“应用程序”模型,似乎避免了以前模型的过度复杂性。我知道其中一个承诺是避免所有DLL等版本混乱。我还没有完全掌握这一点。

总结

我的目标是让我的程序迁移到新的框架,为Vista做好准备,并且我在处理位图大小时遇到了一些问题,最大达到15-20兆字节,并且出现随机异常。然后我不得不仔细管理位图大小和缩放来实现这一点。(一些较小的位图,具有特定的缩放和尺寸,也会失败)我曾一度想责怪图片框周围的代码以及旧Windows世界中复杂的“TWIP”和缩放模型。.NET有一个更简单的模型。你调整Picturebox的大小,然后调整位图的大小。其他一切都消失了。

事实上,我的直觉是正确的,我可以处理高达80兆字节。对于大于此的位图,我仍然会遇到“内存不足”异常。我升级到了2.5GB和RADEON显卡,以确保不是我的资源问题。我从未超过1.5GB的使用量,所以这可能还在XP范围内。我猜他们无法正确管理2.5GB,或者一些指针还没有扩展到处理这些大小。也许VISTA会克服这一点。.NET框架对错误的容忍度要高得多,在大多数情况下,你可以恢复到优雅地退出程序。我在60到80兆字节的图形文件内发现它是完全稳定的。

注意: Designlab(C)2007 位图 11700x3400 有17种基本的内置形状和数百种附加形状在形状库中,还有一个用于组合形状的工具。工作缓冲区有可见的图片框,位图在转换、旋转和构建组合时可能在内存中有3-4个副本。形状是2D结构而不是位图。Designlab用一个按键就能创建如下面的设计。要查看更多输出,请访问 Http://www.usanetinc.com

Sample screenshot

80兆字节的图形,你问

我读过一个博客,有人评论说“为什么你需要更大的位图?”DesignLab是一款面料和美术设计软件,我曾经在EPSON7800打印机上将输出打印到面料上,例如作为桌布的尺寸为84英寸乘以17英寸。以每英寸200像素计算,就是16800x3400。对于每英寸720像素的打印来说,这可能几乎是准确的。每英寸100像素和200像素之间有巨大的区别。

结论

转换向导=坏消息
完全重写=好消息

但由于我不得不重新编写,我修复了我认为可以改进的所有地方,我将代码结构得更像一个类库,可以重写为.DLL图形引擎,并且总体设计和结构更加清晰和有条理,这将对未来的开发带来回报。

对于图形,如果你有一个想要继续开发的aabbcc项目,你就必须做出改变。 但任何能完成工作的代码,它就能完成工作……希望MS能继续支持它。美国公司会运行代码30年,而且他们必须这样做,开发成本是惊人的。处理你的支票簿,可能不值得付出努力。

但是,请务必用.NET框架编写你所有的代码。

 

 

© . All rights reserved.