【问题标题】:Replacing WinMain() with main() function in Win32 programs在 Win32 程序中用 main() 函数替换 WinMain()
【发布时间】:2012-07-31 21:05:09
【问题描述】:

我在 StackOverflow 和 Google 上进行了一些搜索,但无法理解。我想用这种类型的用户编程来启动我的应用程序:

int main()
{
  Window App("Test", 640, 480);

  while(App.IsOpen())
  {
    // Do the stuff
  }
}

但这是不可能的,因为我应该将hInstancehPrevInstance 以及其他参数传递给WinMain 函数。实际上,我设计了一个 Window 类,以使创建窗口更容易一些。我在 SFML 上看到了这个实现,但我不知道它是怎么做到的。

现在我正在使用通常的方式:

int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR, int)
{
  Window App(hInst, hPrevInst, "Test", 640, 480);

  while(App.IsOpen())
  {
    // Do the stuff
  }
}

谢谢。

【问题讨论】:

    标签: c++ winapi


    【解决方案1】:

    如果您将以下内容添加到 Microsoft 链接器选项中,即使使用 Microsoft 工具,您也可以在“windows”应用程序(即 GUI 子系统 Windows 应用程序)中使用标准 main

    /subsystem:windows /ENTRY:mainCRTStartup
    

    请注意,这对于 GNU 工具链不是必需的。

    对于 Microsoft 工具,您也可以将其添加到主文件中:

    #ifdef _MSC_VER
    #    pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
    #endif
    

    James McNellis tells you如何获取hInstance。

    【讨论】:

    • 编辑:我没有抱怨误导性的答案,而是纠正了它。
    • 我最初回滚了这个编辑,因为我认为对于试图在 Windows 平台上进行这项工作的大多数人来说,它的答案更清楚,没有必要谈论 gnu,因为 1 ) 大多数人不在 Windows 上使用它,并且 2) 他们无论如何都不会遇到这个问题....但我不想争论所以我还是把你的编辑放回去了:)
    【解决方案2】:

    GetModuleHandle(NULL) 会给你hInstancehPrevInstance 始终是 NULL

    【讨论】:

    【解决方案3】:

    首先,GetModuleHandle(0) 提供可执行文件的模块句柄,与WinMainhInstance 参数相同。

    使用 GNU 工具链(g++ 编译器),符合标准的代码是可以的。

    但是,Microsoft 工具链默认情况下只接受符合标准的代码,用于控制台子系统可执行文件。要使用标准 main 创建带有此不符合标准的工具链的 GUI 子系统可执行文件,您必须指定调用标准 main 的 Microsoft 运行时库入口点,即 mainCRTStartup。对于命令行调用,这意味着……

    cl myApp.cpp /link /entry:mainCRTStartup /subsystem:windows user32.lib
    

    实际上,对于在命令行中工作,您可以简单地在LINK 环境变量中指定入口点:

    set LINK=/entry:mainCRTStartup
    

    cl myApp.cpp /link /subsystem:windows user32.lib
    

    为 Visual Studio 创建一个类似的符合标准的设置可能是不可取的,因为某些 Visual Studio 项目类型(主要是 MFC)需要使用 Microsoft 的非标准 WinMainwWinMain

    【讨论】:

      【解决方案4】:

      hInstance 是“从不使用全局变量”经验法则的一个例外。通常没有变量实际上在逻辑上具有模块范围的范围。然而,hInstance 根据定义恰好具有模块范围的范围,因此实际上最合乎逻辑的解决方案是为其创建一个全局变量并在 WinMain 中对其进行初始化。

      按照其他人的建议,您也可以使用GetModuleHandle(NULL)

      【讨论】:

      • 这不是真的。例如,考虑编译一个静态库。每个 PE 文件只有一个HINSTANCE
      • 是的,但是对于使用全局变量的代码,没有区别。变量可以具有的最大范围是模块范围的。比这更小的范围不会受到伤害。
      • 但是仍然没有必要让它有更多的范围。
      • 可以使用全局变量,只要您将它们视为全局状态的一部分并且不要试图隐藏它们。全局变量在全局范围内而不是匿名/命名结构时是邪恶的,并且当多个世界试图与它们交互时。也就是说,向代码中添加全局变量就像扩展运行时一样;可以这样做,但是您必须将它们捆绑在一起以限制全局范围污染,最好使它们成为静态的。善用全局变量可以明确你的程序目前持有哪些资源,使用不当会将你的代码变成一个全局污水池。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 2011-04-22
      • 2020-07-19
      • 2013-09-13
      • 1970-01-01
      相关资源
      最近更新 更多