如果prevInstance始终为NULL,为什么它还存在于WinMain和wWinMain中

问题描述 投票:0回答:2

由于我是初学者,这可能是一个非常基本的问题。我正在启动 DirectX 11,在创建第一个应用程序时,使用了 wWinMain,在寻找 WinMain 和 wWinMain 之间的差异时,我遇到了这个参数 prevInstance。

prevInstance 根据 MSDN 始终为 null,既然它始终为 null,那它为什么存在(因为按逻辑认为创建者不会给出无用的参数)。并且(引自书中),

如果您需要一种方法来确定先前的实例是否 应用程序已经在运行,文档建议创建 使用 CreateMutex 的唯一命名的互斥体。虽然互斥体将是 创建后,CreateMutex 函数将返回 ERROR_ALREADY_EXISTS。

什么是互斥体,以及如何使用它(一个好的链接就足够了)。看起来需要一个方法来查找应用程序的另一个实例是否存在, prevInstance 应该有一个指向它的指针或引用,但显然情况并非如此,因为它为 null。为什么会这样,prevInstance 的作用是什么?

c++ winapi parameters winmain
2个回答
21
投票

Raymond Chen 的博客 几乎完全致力于讨论对我们今天来说“奇怪”的 Windows API 的各个方面。幸运的是,他有一篇博客文章回答了这个确切的问题:

在 16 位 Windows 中,有一个名为 GetInstanceData 的函数。这 函数接受一个 HINSTANCE、一个指针和一个长度,并复制内存 从该实例到您当前的实例。 (这有点像 16 位相当于 ReadProcessMemory,但限制是 第二个和第三个参数必须相同。)

...

这就是 WinMain 的 hPrevInstance 参数的原因。如果 hPrevInstance 为非 NULL,则它是副本的实例句柄 已经运行的程序。您可以使用 GetInstanceData 来 从中复制数据,让自己更快地起步。例如, 您可能想从以前的窗口句柄中复制主窗口句柄 实例,以便您可以与其通信。

hPrevInstance是否为NULL告诉你是否是 程序的第一个副本。在16位Windows下,只有第一个 程序的实例注册了它的类;第二次及后续 实例继续使用由 一审。 (事实上,如果他们尝试的话,注册就会失败 因为该类已经存在。)因此,所有 16 位 Windows 如果 hPrevInstance 是,程序会跳过类注册 非 NULL。

设计 Win32 的人们发现自己陷入了困境 是时候移植 WinMain 了:为 hPrevInstance 传递什么?这 毕竟,整个模块/实例在 Win32 中并不存在,并且 单独的地址空间意味着跳过的程序 第二次重新初始化将不再起作用。所以Win32 总是传递 NULL,使所有程序都相信它们是 第一个。

当然,现在除了兼容性原因之外,

hPrevInstance
与 Windows API 无关,MSDN 建议您使用互斥体来检测应用程序的先前实例。

互斥锁代表“互斥”。您可以参考MSDN 文档了解

CreateMutex()
。有很多使用互斥体来检测应用程序的先前实例的示例,例如这个。基本思想是创建一个具有您想出的唯一名称的互斥体,然后尝试创建该命名的互斥体。如果
CreateMutex()
失败并显示
ERROR_ALREADY_EXISTS
,则您知道应用程序的实例已启动。


2
投票

prev 实例参数用于 16 位 Windows 兼容性。我认为 WinMain 的 MSDN 参考文献中已经说明了这一点,至少以前是这样。

© www.soinside.com 2019 - 2024. All rights reserved.