科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件VC++中IRegistrar、查找子菜单及其他

VC++中IRegistrar、查找子菜单及其他

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

使用 Visual C++ 6.0 生成具有自动化支持的 DLL 时,生成了一些注册函数,而不是取消注册我的 DLL 的函数。我编写了 DllUnregisterServer.

作者:Paul DiLascia 来源:msdn中国 2007年11月19日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
问: 我的主应用程序具有一个常规菜单,它具有一个“编辑”命令(“剪切”、“复制”、“粘贴”等)子菜单。我希望当用户在主窗口中用鼠标执行右键单击操作时,“编辑”子菜单会以上下文菜单的形式进行显示。问题是如何从主菜单中获取此子菜单。似乎没有与子菜单关联的任何命令 ID。我可以使用基于零的索引,但由于自定义,“编辑”菜单可能不总为第二个菜单。我不能搜索文本“Edit”,因为我们支持多语言,且实际的词语可能会发生改变。在所有这些情况下,我如何才能找到“编辑”子菜单呢?

  Brian Manlin

  答:  是这样,需要指出的是,如果您有的话,则“编辑”菜单应该是第二个子菜单。正式的 Windows® GUI 指南要求前三个菜单项依次为“文件”、“编辑”、“视图”- 如果您支持它们。请参阅《The Windows Interface Guidelines for Software Design》(软件设计 Windows 界面指南)(Microsoft Press®, 1995)。书中提到,对于该问题,我可以帮助您找到“编辑”子菜单或任何其他子菜单。

  您确实是正确的,没有用于子菜单的命令 ID。那是因为,如果菜单项为子菜单,则 Windows 将在内部使用命令 ID 字段来包含子菜单的 HMENU。不过不必担忧,假定子菜单始终包含某个特定命令(例如,编辑 | 剪切),且该命令始终具有相同的 ID(例如 ID_EDIT_CUT),则很容易编写一个用来查找包含给定命令的子菜单的函数。图 2 显示了代码。CSubmenuFinder 实际上充当了一个命名空间以包含静态函数 FindCommandID,该函数递归调用其自身以深度搜索菜单和所有子菜单,查找其命令 ID 与搜索到的命令 ID 匹配的菜单项。

  此代码段将搜索主菜单,查找包含其命令 ID 为 ID_EDIT_CUT 的菜单项的子菜单,如果能找到这样一个子菜单,则返回该子菜单。我写了一个名为 EdMenu 的小程序来测试 CSubmenuFinder。当用户在主窗口中用鼠标执行右键单击操作时,EdMenu 将使用前面的代码处理 WM_CONTEXTMENU 以显示与主菜单中的内容完全相同的编辑子菜单。您一定会相信我,不论编辑菜单出现在主菜单中的什么位置,CSubmenuFinder 都会找到它。事实上,在其中一次编译中,我确实曾通过将“编辑”菜单暂时移动到“视图”菜单之前来对其进行过测试。要亲自尝试一下,请下载源代码。

  问: 如何将 MFC CString 转换为托管 C++ 中的 String?例如,我有以下 C++ 代码:

以下是引用片段:
  void GetString(CString& msg)
  {
  msg = // 构建一个字符串
  }

  如何使用托管 C++ 重新编写此函数并用托管 String 替换 CString 参数?问题是 GetString 更改了调用程序的 CString,并且我想使用托管 String 来执行同样的操作。

  Sumit Prakash

  答: 是这样,答案取决于您使用的是新 C++/CLI 语法还是旧的托管扩展。两种语法类型可能都令人困惑,但不要担心,在此我将澄清您的编码困惑。

  由于现在是 2006 年,因此,让我们先来讨论新语法。使语法正确的诀窍是记住两件事情。首先,在 C++/CLI 中,托管对象具有尖角符号。所以,CString 将变为 String^。其次,记住引用 (&) 的托管等价物为跟踪引用,在 C++/CLI 中其为 %。我知道,您很难理解 ^,但经过充分的练习,不久即会对 % 习以为常的。这样,新函数将如下所示:

以下是引用片段:
  // 使用 C++/CLI
  void GetString(String^% msg)
  {
  msg = // 构建一个字符串
  }

  这有意义吗?为了说明其确实起作用了,我编写了一个小程序 strnet.cpp(请参见图 3)。它实现两个类,CFoo1 和 CFoo2,每个类都有一个成员 GetName。第一个类使用 CString&,而第二个类使用 String^%。当您编译并运行此程序(当然要使用 /clr)时,您将看到在两种情况下 - 使用 Cstring 的类和使用 String 的类—传递对象(本机或托管)被成员函数修改了。

  顺便指出,您始终希望为托管对象使用跟踪引用 (%) 而不是使用本机引用(&,它也将编译),因为即使垃圾收集器将对象移动到其托管堆内,跟踪引用也会对引用进行跟踪。

  如果您使用的是旧式语法 (/clr:oldSyntax),则您该如何才能走出您所生活的黑暗年代呢?不要害怕,即使您念旧,您还是可以使用引用的。如果您使用的是托管扩展,则只需记住托管对象是 __gc 指针即可,所以 CString 将变为 String __gc *。而且,由于编译器已经知道 String 为托管类型,您甚至不需要 __gc;一个简单的指针 (*) 就够了。引用是相同的。所以,旧式语法转换如下所示:

以下是引用片段:
  // 省略了 __gc
  void GetString(String*& msg)
  {
  msg = // 构建一个字符串
  }

  明白了吗?这样才合理。每当您理解 C++ 语法遇到麻烦时,您所要做的事情就是返回到基本内容。

  问:我最近使用 Visual Studio® 2005 生成了一个 CLR 控制台应用程序。我注意到 Visual Studio 创建了一个主函数,如下所示:

以下是引用片段:
  int main(array ^args)
  {
  ...
  return 0;
  }

  这看起来好像是对我所熟悉的 C/C++ 中的旧 argc/argv 的更改。当我认为 args[0] 是文件名(在 C/C++ 中就如此)并尝试对其进行访问时,我却发现 args[0] 不是文件名,而是第一个命令行参数。文件名发生什么变化了?您能解释一下这种更改的原因吗?

  Jason Landrew

  答:  哦,我们正生活在现代世界中。所有事情都与以前不同了,不是吗?自从 1972 年开发出 C 以来,我们就一直与 argc/argv 生活在一起,而现在,Redmondtonians 已经一去不复返了,并已对其进行了更改。也许他们想确保每个人都知道如何使用新数组语法。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章