如何在不使用 WinMain 的情况下编写 Windows 应用程序?

发布于 2024-07-13 16:49:25 字数 385 浏览 6 评论 0原文

用 C/C++ 编写的 Windows GUI 应用程序将“WinMain”作为入口点(而不是“main”)。 我对此的理解是编译器生成一个由 C 运行时调用的“main”函数。 这个“main”函数为 GUI 设置必要的环境并调用“WinMain”(指定实例句柄等)。

简而言之,我认为控制台和 GUI 应用程序启动存在以下差异:

控制台应用程序: C 运行时 --> “main”函数(手动编码)

GUI 应用程序: C 运行时 --> 'main' 函数(编译器生成)--> “WinMain”函数(手动编码)

我想验证这种理解,并了解如何仅使用“main”函数(即无需编写“WinMain”)来手动编码 Windows GUI。

Windows GUI applications written in C/C++ have 'WinMain' as an entry point (rather than 'main'). My understanding of this is that the compiler generates a 'main' function to be called by the C Runtime. This 'main' function sets up the necessary environment for the GUI and calls into 'WinMain' (specifying the instance handles etc.).

In short, I believe console and GUI application startup to differ in the following way:

Console application:
C Runtime --> 'main' function (hand-coded)

GUI application:
C Runtime --> 'main' function (compiler-generated) --> 'WinMain' function (hand-coded)

I would like to both validate this understanding and find out how I can hand-code a Windows GUI with just a 'main' function (i.e. without having to write 'WinMain').

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

紫瑟鸿黎 2024-07-20 16:49:25

你的理解不正确。 main 和 WinMain 之间的区别除了一些不同的初始化代码之外,还在于传递给它的参数。

main 看起来像这样:

int main(int argc, char* argv[]);

而 WinMain 看起来像这样:

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
);

必须设置这些参数并进行调用,这就是启动代码。 当您编译和链接程序时,链接器参数之一是入口点,根据控制台或 GUI 应用程序,这将是不同的启动代码位。

你当然可以编写自己的启动代码,只需进入你的 Visual C++ 源目录,你就可以找到启动代码,它名为 crt0.c,位于 VC\crt\src 目录中。

You have an incorrect understanding. The difference between main and WinMain, apart from some differet initialization code, is the parameters passed to it.

main looks like this:

int main(int argc, char* argv[]);

While WinMain looks like this:

int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow
);

Something has to setup those parameters and make the call, and that's the startup code. When you compile and link a program, one of the linker parameters is the entry point, and that will be, depending on a console or GUI app, a different bit of startup code.

You can certainly write your own startup code, just go into your visual c++ source directory and you can find the startup code, it's called crt0.c and it's in the VC\crt\src directory.

淡淡離愁欲言轉身 2024-07-20 16:49:25

使用 Just main,您无法编写 Winmain 代码。 为了说明理由,以下声明摘自
http://blogs.msdn.com/oldnewthing/archive/ 2007/12/03/6644060.aspx

[在 Windows 编程中,]为什么不调用应用程序入口点
主要的? 嗯,一方面,名称 main 已被占用,并且
Windows 无权保留备用定义。
那时还没有C语言标准化委员会; C 是
丹尼斯说的是什么,很难保证丹尼斯
会采取任何特殊步骤来保留 Windows 源代码
任何未来版本的 C 语言的兼容性。 自从K&R
没有指定实现可以扩展可接受的形式
对于主要功能,完全有可能存在合法的
C 编译器拒绝错误声明 main 的程序。 这
当前的 C 语言标准明确允许特定于实现的
main 的替代定义,但要求所有编译器都支持
这个新的 Windows 特定版本,用于编译 Windows 程序
会无缘无故地限制您可以使用的编译器集
编写 Windows 程序。

如果你设法克服这个障碍,你就会遇到这样的问题:
Windows 版本的 main 必须是这样的:

int main(int argc, char *argv[], HINSTANCE hinst, 
           HINSTANCE hinstPrev, int nCmdShow); 
  

由于 C 链接的执行方式,函数的所有变体都必须就以下内容达成一致:
他们有共同的参数。 这意味着 Windows 版本
必须将其参数添加到最长的现有的末尾
main 的版本,然后你就得祈祷
C 语言从未添加 main 的另一个替代版本。 如果
你走了这条路,你交叉的手指失败了,因为它转向
一段时间后,第三个参数被添加到 main 中,并且它
与您的 Windows 友好版本冲突。

假设你设法说服丹尼斯不允许这样做
main 的三参数版本。 你还得想出那些
前两个参数,表示每个程序的启动代码
需要包含命令行解析器。 回到 16 位时代,
人们精打细算以节省每一个字节。 告诉他们,“哦,还有你们所有的
程序将会变大 2KB”可能不会让你有很多
的朋友。 我的意思是,这是软盘 I/O 的四个扇区!

但这可能是 Windows 入口点被赋予的原因
不同的名称是为了强调这是不同的执行方式
环境。 如果它被称为 main,人们就会采用 C 程序
专为控制台环境设计,将它们放入 Windows 中
编译器,然后运行它们,结果是灾难性的。

希望这能消除您的疑虑。

With Just main, you can not code Winmain. For justifications, Following statements were taken from
http://blogs.msdn.com/oldnewthing/archive/2007/12/03/6644060.aspx

[In Windows Programming,] Why wasn't the application entry point called
main? Well, for one thing, the name main was already taken, and
Windows didn't have the authority to reserve an alternate definition.
There was no C language standardization committee back then; C was
what Dennis said it was, and it was hardly guaranteed that Dennis
would take any special steps to preserve Windows source code
compatibility in any future version of the C language. Since K&R
didn't specify that implementations could extend the acceptable forms
of the main function, it was entirely possible that there was a legal
C compiler that rejected programs that declared main incorrectly. The
current C language standard explicitly permits implementation-specific
alternate definitions for main, but requiring all compilers to support
this new Windows-specific version in order to compile Windows programs
would gratuitously restrict the set of compilers you could use for
writing Windows programs.

If you managed to overcome that obstacle, you'd have the problem that
the Windows version of main would have to be something like this:

int main(int argc, char *argv[], HINSTANCE hinst,
         HINSTANCE hinstPrev, int nCmdShow);

Due to the way C linkage was performed, all variations of a function had to agree on the
parameters they had in common. This means that the Windows version
would have to add its parameters onto the end of the longest existing
version of main, and then you'd have to cross your fingers and hope
that the C language never added another alternate version of main. If
you went this route, your crossed fingers failed you, because it turns
out that a third parameter was added to main some time later, and it
conflicted with your Windows-friendly version.

Suppose you managed to convince Dennis not to allow that
three-parameter version of main. You still have to come up with those
first two parameters, which means that every program's startup code
needs to contain a command line parser. Back in the 16-bit days,
people scrimped to save every byte. Telling them, "Oh, and all your
programs are going to be 2KB bigger" probably wouldn't make you a lot
of friends. I mean, that's four sectors of I/O off a floppy disk!

But probably the reason why the Windows entry point was given a
different name is to emphasize that it's a different execution
environment. If it were called main, people would take C programs
designed for a console environment, throw them into their Windows
compiler, and then run them, with disastrous results.

Hope this clears your doubts.

断舍离 2024-07-20 16:49:25

反之亦然。 编译器附带一个静态链接的目标文件,它保存实际的入口点。 该入口点进行初始化,然后调用您的入口点(即 WinMain)。

该静态部分期望调用的内容可能是可调整的。 例如,在 Visual Studio 中,链接器设置中有一个入口点名称字段。

It works the other way. There's a statically linked object file which comes with the compiler that holds the actual entry point. That entry point does initialization and then calls your entry point (i.e. WinMain).

What that static part expects to call may be tweakable. For example, in Visual Studio there's a field for the entry point name in the linker settings.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文