资源 ID 在我的共享 MFC DLL 中是不是应该是唯一的
Posted
技术标签:
【中文标题】资源 ID 在我的共享 MFC DLL 中是不是应该是唯一的【英文标题】:Should Resource IDs be unique in my shared MFC DLLs资源 ID 在我的共享 MFC DLL 中是否应该是唯一的 【发布时间】:2015-05-23 12:11:09 【问题描述】:示例:第一个 MFC DLL 在 resource.h 中有一个 ID 值为 4711 的菜单 ID_MENU_FOO。第二个 MFC DLL 也有另一个菜单 ID_MENU_BAR,其 ID 值为 4711。 应用程序 (exe) 使用 DLL 并调用 LoadMenu。如果我想验证要加载的所需菜单,我需要调用 API 方法LoadMenu 将模块句柄提供给所需的 dll。还是我错了?
在我自己的项目中处理资源 ID 及其唯一性的最佳做法是什么?
提前致谢!
【问题讨论】:
当然,它们应该是唯一的 但是为什么呢?通常我不关心值,只是添加资源。但是有时当某个库或应用程序本身获得新资源时,应用程序会加载错误的菜单或图像或其他任何内容,因为新 ID 使另一个库的现有资源 ID 不再唯一。 这个问题没有任何意义,图书馆不能有任何资源。 IDE 不会阻止您创建它们,但它们需要链接到 DLL 或 EXE 中才能使用。 抱歉,我的意思是共享 MFC DLL,我已解决问题 LoadMenu 需要模块句柄。那必须是DLL之一。存储在不同模块中的资源可以有相同的ID,模块句柄避免了歧义。 【参考方案1】:这仅取决于您拥有的模块类型。加载资源总是需要一个从哪里加载它的句柄。
如果您使用扩展模块 DLL,EXE 和 DLL 中的所有资源 ID 在 MFC 中必须是唯一的。所以对于扩展模块来说,资源的位置并不重要。 MFC 加载器将遍历所有扩展模块。
如果您只在 MFC 中使用标准 DLL,则所有资源都是分开的。 DLL 和 EXE 中的每个 CWinApp 模块都是分开的,都有自己的搜索路径和 Afx 资源句柄。资源处理也是调用 AFX_MANAGA_STATE 的一个原因。它保存当前资源句柄并设置一个新的,并在离开函数后恢复旧的。
所以这取决于你有什么以及你想如何设计你的程序。因为我有一堆扩展 DLL,所以我有特定的范围用于每个模块中的 ID。在不触及现有扩展 DLL 范围的情况下进行标准维护,因为它们也可以在标准 DLL 搜索路径中找到。
我忘了说:这一切只有在您将 MFC 用作共享 DLL 时才重要。否则每个模块都有自己的资源句柄...
可以以其他方式共享资源。你可能有自己的 Loader 例程来获取它们...
【讨论】:
术语已经差不多了。没有 “当前资源句柄” 这样的东西,AFX_MANAGE_STATE
也不管理资源句柄。它管理 module 句柄。至于 ID 的唯一性:资源 ID 对于每个模块和资源类型必须是唯一的。一个模块可以包含具有相同 ID 的不同类型的资源。
在使用AFX_MANAGE_STATE的时候,不是MFC的当前资源句柄被保存和恢复吗?实际上,当前状态已切换……因此行为发生了变化。这就是我的意思:对于当前的资源句柄,你怎么称呼它是用 AfxSetResourceHandle 设置的?我们不是在谈论 MFC。这里没有询问资源绑定到模块的基本事实。问题是:你什么时候需要自己的资源 ID,什么时候可以重用...
@xMRi 我们正在使用一个扩展 dll 链,每个都提供资源。在一个 dll 中,每种类型的 ID 都是唯一的。 xMRi 你适合我的问题。一个 dll 不小心重用了一个已由 delendent 扩展 dll 使用的 ID,这导致上面的另一个扩展 dll 加载错误的资源。
我的解决方案与 HansPassant 提到的一样,我们必须考虑消除过去 15 年中增长的大量 dll。如果有理由保留更多 dll,我们将重新组织代码以使其有意义,而不是开发人员在添加代码或资源时正在处理的位置,目前这对于许多类来说是随机的。如有必要,我们还将考虑最终 dll 链的 ID 范围。我还发现一些资源被重用以强制交换特定资源。我不喜欢隐式覆盖资源的这种隐藏“功能”。
我们必须(重新)设计一些东西 :) 感谢大家的时间和帮助 cmets。【参考方案2】:
Hans Passant 给出了答案
跨模块使用资源不是“最佳实践”。正确划分代码,窗口使用菜单,因此只需确保所有窗口的实现细节都在同一个模块中。
【讨论】:
以上是关于资源 ID 在我的共享 MFC DLL 中是不是应该是唯一的的主要内容,如果未能解决你的问题,请参考以下文章