c# - 64 位 Windows 上的气球工具提示

标签 c# .net winforms 64-bit

在我自己的程序中,我尝试在此处使用此代码将工具提示气球窗口添加到我的应用程序:http://www.codeproject.com/Articles/4991/Balloon-Tips-Galore (此处提供源代码)

我尝试编译演示程序,它在 32 位 Windows 7 上运行良好,但当我尝试在 64 位 Windows 7 上使用它时,程序崩溃了。如果我尝试调试 VS2010 中的崩溃,我会收到此消息:

enter image description here

调试器位于源代码不可用的某些区域,它显示 Call stack location: ntdll.dll!0000000076fe40f2()

如何解决此问题,使其不会在 64 位上崩溃?

最佳答案

我无法让 C# 演示在 Windows Server 2003 x64(这是我目前唯一可用的 64 位环境)上崩溃,但代码有问题,所以你看到意外行为是有道理的.

编辑:使用原始代码重现了 Windows Server 2008 R2 x64 中的崩溃,并验证了修复的有效性。

As Christian.K points out , 问题has been noted before .当调用Marshal.StructureToPtr 方法时,您应该为第三个fDeleteOld 参数传递true only 当指定的内存块不包含有效数据。这在 the documentation 中非常明确地指出了。 , 所以我不确定原作者是怎么弄错的。

在这种情况下,由于数据刚刚通过调用 Marshal.AllocHGlobal 分配给行,因此它不包含有效数据,不应删除/释放。改动很简单:将第三个参数true改为false。不幸的是,由于互操作代码分散在示例项目中的三个不同类中,因此您必须在多个地方进行更改。您正在寻找的模式是这样的:

IntPtr ptrStruct = Marshal.AllocHGlobal(Marshal.SizeOf(ti));
Marshal.StructureToPtr(ti, ptrStruct, false /* <-- change this from true to false */);

正如一般观察:代码尝试手动处理大量互操作内容(通过使用 Marshal 类的方法),而不是让 CLR 自动处理。我非常更喜欢后一种方法。尽管我完全理解如何手动执行所有互操作,但让系统为我管理它可以减少我犯的错误数量和导致的堆损坏。

RhysW说他以前从未遇到过堆损坏,但是当您开始在 .NET 代码和 Win32 API 之间进行互操作时,这种情况就变得非常普遍。 .NET Framework 不再保护您。

举例说明我的意思,请注意 FMSBalloonTip.SetToolTip 方法使用 Marshal.StringToHGlobalAuto 方法将包含工具提示标题的字符串编码为指针。虽然这确实有效(值得庆幸的是,作者在完成后小心地释放了指针),但声明 SendMessage string 对象作为第四个参数。这样,该框架将透明地为您处理所有必要的互操作内容。

当然,真正的问题是您为什么需要这段代码。 使用内置的 ToolTip class 更容易 ,从一开始就可用。我不确定您是否只是没有提到 ToolTip 没有提供的某些您需要的功能,或者您只是不知道,但我强烈建议您重新考虑您的设计,以便您可以利用内置类,让 Microsoft 程序员处理所有互操作性内容。

如果您要查找的是气球部分,请确保设置IsBalloon property ToolTip 类。直到 .NET 2.0 才引入它,但它与示例项目所针对的版本相同。

关于c# - 64 位 Windows 上的气球工具提示,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14879568/

相关文章:

c# - 使用 IDisposable C# 连接 MySQL

c# - 使用正则表达式分组结构匹配字符串的各个部分

c# - 在 C# 中使用 fitnesse、fitsharp 和 slim

javascript - 将数组从代码隐藏例程传递到 javascript

c# - PushButtonState.Default 和 PushButtonState.Normal 之间的逻辑区别是什么?

c# - DataGridView "Enter"按键事件处理

c# - 是否可以为 List<double> 预分配内存?

C# ThreadPool 等待结果

c# - 基于模板打开 Excel 副本

c# - DataGridView Winform 中的文本框自动完成