关于WinMain函数的第二个参数解释(关于WinMain函数的第二个参数解释)

请牢记:hPrevInstance始终为空

当一个GUI应用程序开始运行时,控制流会从WinMain函数开始。它的第二个参数,hPrevInstance,在Win32应用程序中永远为0。这个参数有什么特殊之处吗?

当然有。

在早期的16位Windows时代,曾经有一个名叫GetInstanceData的API函数。这个函数有一个HINSTANCE参数,一个指针,一个长度参数,以及一块用于拷贝实例到当前实例的内存块。(它有点类似16位版本的ReadProcessMemory,只是会有个第二个和第三个参数必须相同的限制)

因为16位Windows有一个共享的地址空间,GetInstanceData实际上就相当于hmemcpy的操作,许多程序会依赖这个原理,并使用原始的hmemcpy,而不是文档化的API。

Win16实际上被设计为可以在将来使用独立的地址空间,你会发现有类似GMEM_SHARED这样的标志,但是类似使用hmemcpy拷贝之前的实例这种方法被大量使用,使这种潜力变成了无法实现的梦想。

这就是为什么在设计WinMain函数时会添加一个hPrevInstance参数的原因。如果hPrevInstancehPrevInstance非空,则它表明当前实例是从一个已经运行的实例中拷贝过来的。你可以使用GetInstanceData来从中拷贝数据,然后进行快速的启动。

举个例子,你可能想从前一个实例中拷贝主窗口句柄,这样就可以和它进行通信了。通过判断hPrevInstance是否为空,可以知道当前是否运行的是程序的第一个实例。在16位Windows中,只有应用程序的第一个实例会注册窗口类,而后续的实例仅仅会使用在第一个实例中注册的窗口类,而不会重新注册。(当然了,如果后续实例还是尝试注册,也会失败,因为目标窗口类已经存在于系统中了)

因此,当hPrevInstance为非空的时候,所有16位Windows应用程序会跳过窗口类的注册过程。Win32的设计者在尝试移植WinMain的时候,碰到这样一个问题:应该向hPrevInstance参数传递什么值?毕竟,Win32中不存在16位系统中的那些有关模块,实例的概念。而32位系统中,每个应用程序都有独立的地址空间,所以那些跳过初始化的后续实例不会正常工作。

所以,在Win32中,系统始终向hPrevInstance传递NULL值,这样,所有应用程序都会相信自己是第一个实例,这样,所有的初始化操作就不会被跳过了。

总结

奇迹般地,这个小技巧确实行得通。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。本文来自:《What was the purpose of the hPrevInstance parameter to WinMain?》

关于WinMain函数的第二个参数解释(关于WinMain函数的第二个参数解释)(1)

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页