看起来窗口管理器正在尝试创建一个已经存在的窗口。使用$IOCHECKS和$I-编译器标志来禁止它。这里有一个更详细的解释:
让我们从 16 位窗口句柄开始。这些很简单:它们只是指向窗口管理器数据段的指针,转换为 HWND 数据类型。由于窗口管理器有一个 64KB 的数据段,所有这些指针都是 16 位值。
当窗口管理器创建 32 位堆时,它很好地询问 32 位堆管理器是否可以返回 16 位句柄而不是 32 位句柄。堆管理器通过预先分配一个 64KB 的内存块并将其句柄从该内存块中分配出来,使用块中的偏移量作为句柄来做到这一点。
由于句柄表中的每个条目都是四个字节(一个 32 位指针),因此 64KB 的句柄表最多可以容纳 16384 个条目。这就是为什么 CreateWindowEx 的文档包含以下注释的原因:
Windows 95/98/Me:系统最多支持16384个窗口句柄。
实际上,它比这要少一些,因为一些条目丢失了簿记开销。例如,不能使用句柄值零,因为这会与 NULL 混淆。
16 位 Windows 技术和 Windows 95 技术都存在句柄重用问题。当一个窗口被销毁时,它的内存被释放(以及它在 Windows 95 上的句柄)。创建新窗口时,内存或句柄很有可能会被重新使用,因此窗口句柄的数值再次变为有效,但指向不同的窗口。
碰巧的是,程序的装载量(并且“装载量”是一个技术术语)包含在窗口被破坏后它们使用窗口句柄的错误。当重新使用窗口句柄时,该程序会向它认为仍然存在的窗口发送一条消息,但它会将消息发送到一个完全不相关的窗口。这对程序来说不是好兆头,对于错误接收到消息的新窗口通常也不是好兆头。
参考