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

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

简而言之,我认为控制台和GUI应用程序的启动方式有以下不同之处:

控制台应用程序:C运行时 – >’主’function(手动编码)

GUI应用程序:C运行时 – >’main’函数(编译生成) – >’WinMain’函数(手工编码)

我想validation这种理解,并找出如何只使用’main’函数手动编写Windows GUI(即无需编写’WinMain’)。

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

主要看起来像这样:

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目录中。

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

[在Windows编程中,]为什么应用程序入口点不是main? 好吧,首先,名称main已经被采用,Windows没有权限保留备用定义。 当时没有C语言标准化委员会; C就是Dennis所说的,并且几乎不能保证Dennis会采取任何特殊措施来保留未来C语言版本中的Windows源代码兼容性。 由于K&R未指定实现可以扩展主函数的可接受forms,因此完全有可能存在合法的C编译器拒绝声明主要错误的程序。 当前的C语言标准明确允许main的特定于实现的备用定义,但要求所有编译器支持这个新的Windows特定版本,以便编译Windows程序将无条件地限制可用于编写Windows程序的编译器集。

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

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

由于C链接的执行方式,函数的所有变体必须在它们共有的参数上达成一致。 这意味着Windows版本必须将其参数添加到main的最长现有版本的末尾,然后您必须指责并希望C语言从未添加另一个备用版本的main。 如果你走这条路线,你的交叉手指就会失败,因为事实certificate第三个参数在一段时间后被添加到main中,并且它与你友好的Windows版本相冲突。

假设你设法说服Dennis不要允许那个三参数版本的main。 您仍然必须提出前两个参数,这意味着每个程序的启动代码都需要包含命令行解析器。 在16位的日子里,人们吝啬地保存每一个字节。 告诉他们,“哦,你所有的节目都要大2KB”可能不会让你成为很多朋友。 我的意思是,这是软盘上I / O的四个扇区!

但是,为什么Windows入口点被赋予了不同的名称可能是为了强调它是一个不同的执行环境。 如果它被称为main,人们将采用专为控制台环境设计的C程序,将它们放入Windows编译器,然后运行它们,带来灾难性的结果。

希望这能清除你的疑虑。

它以另一种方式工作。 有一个静态链接的目标文件,它带有保存实际入口点的编译器。 该入口点进行初始化,然后调用您的入口点(即WinMain)。

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