9

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

prevInstance 根据 MSDN 始终为空,既然始终为空,那它为什么存在(因为顺理成章地认为创作者不会给出一个无用的参数)。并且(引自书中),

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

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

4

2 回答 2

17

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

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

...

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

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

设计 Win32 的人发现自己在移植 WinMain 时遇到了一些问题:为 hPrevInstance 传递什么?毕竟,整个模块/实例的东西在 Win32 中并不存在,单独的地址空间意味着在第二个实例中跳过重新初始化的程序将不再工作。所以Win32总是传NULL,让所有程序都认为自己是第一个。

当然,现在这hPrevInstance与今天的 Windows API 无关,除非出于兼容性原因,MSDN 建议您使用互斥锁来检测应用程序的先前实例。

互斥体代表“互斥”。您可以参考MSDN 文档了解CreateMutex(). 有很多使用互斥锁来检测以前的应用程序实例的例子,比如这个。基本思想是创建一个具有您想出的唯一名称的互斥体,然后尝试创建该命名的互斥体。如果CreateMutex()失败ERROR_ALREADY_EXISTS,您知道您的应用程序的一个实例已经启动。

于 2011-09-17T23:13:38.603 回答
1

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

于 2011-09-17T23:14:07.520 回答