多年前,我正在使用Visual Basic,我发现了MsgBox
函数的错误。我试着寻找它,但没有人曾经说过这件事。它不仅仅是Visual Basic;它与使用标准Windows MessageBox
API调用的任何内容一起使用。
当标题文本有多个字符时触发错误,第一个字符是带有变音符号('ÿ')的小写“y”。这个角色有什么特别之处?它几乎绝对不是角色本身,而是它的特殊ASCII值。 'ÿ'是字符255(0xFF),意味着它是可以存储在无符号字节中的最高值,并且其所有位都设置为1.
这个bug有什么作用?嗯,有两种不同的可能性,这取决于标题文本中的字符数。如果标题文本中有偶数个字符(除非它是2),则不会出现任何消息框,您只是听到警报声。如果标题文本中有两个字符,或者除了1之外的任何奇数(在这种情况下不会触发错误)......那么这个会发生:
并非全部 - 消息也将被截断为一行。考虑到使用此API调用的频率,这似乎是至少在一个半高调事件中会发生的那种错误。互联网上有没有这方面的报道,或者有什么可能导致它的原因?也许这是一个与Unicode相关的故障,就像记事本中的“布什隐藏事实”故障一样?
我做了一个程序,以防你想玩这个; download it here
或者,将以下内容复制到记事本中,使用.vbs
扩展名保存,然后双击它以显示上面显示的对话框:
MsgBox "Windows 3.1 font, anyone?", 0, "ÿ ODD NUMBER!"
或者换一种不同的字体:
MsgBox "I CAN HAS CHEEZBURGER?", 0, "ÿ HImpact"
编辑:似乎如果第一个四个字符是ÿ
的,它就不会显示消息,即使有一个奇怪的字符数。
答案 0 :(得分:5)
这通常是对话框模板的错误。这不是消息框错误。
例如,在Visual Studio中创建默认的win32应用程序。在.rc文件中,从
更改about框的模板中的标题CAPTION "About sampleapp"
到
CAPTION "ÿT"
当您显示about框时,错误将自动显示。
在DLGTEMPLATEEX documentation注意,菜单和类名称的类型为sz_Or_Ord
,这意味着以空字符结尾的字符串或0xFFFF
后跟单个字资源标识符。
Windows错误地将相似的方案应用于对话框标题:如果第一个字符是0xFF
,则它将标题视为两个WORD长,但仅在它尝试查找字体信息时。当它显示标题时,它会正确地将标题视为字符串。
换句话说,Windows正在寻找标题字符串中的字体信息。在大多数情况下,这不会指定有效字体,因此Windows默认使用系统字体。
为了证明这一点,我在内存中构建了一个对话框模板(based on this)。一旦这个工作,我删除了将字体信息写入模板的代码,并使用对话框标题“ÿa\ xd \ x200 \ x21SimSun”。这会以斜体SimSun显示对话框,因为Windows正在从标题字符串中读取字体信息。
这个bug可能是16位Windows的宿醉,其中(我猜)0xFF被用作资源ID标记。
答案 1 :(得分:3)
一个奇怪的错误。我怀疑这些症状是MessageBox()
实际显示对话框的方式的结果。
内部MessageBox()
builds a dialog template dynamically。如果你看一下DLGTEMPLATE
结构的描述,你会发现以下信息:
在对话框的标准模板中,DLGTEMPLATE结构是 总是紧跟三个可变长度数组 指定对话框的菜单,类和标题。当。。。的时候 指定了DS_SETFONT样式,这些数组后面跟着一个 指定点大小的16位值和另一个可变长度数组 指定字体名称。
因此,对话框模板的内存中布局在对话框标题后紧跟字体规范。
Visual Basic不使用Unicode,因此您调用的函数实际上是MessageBoxA()
。这只是一个thunk,它将传入的字符串从多字节转换为Unicode,然后调用MessageBoxW()
。
我相信正在发生的事情是,由于某种原因,将该字符串从多字节转换为Unicode要么出错,要么返回虚假长度值。当对话框模板在内存中构建时,这会产生连锁效应,在标题字符串后面立即破坏内存 - 正如我们所知,这是字体规范。