MinGW,使用控制台构建GUI应用程序

7

我正在使用MinGW在Windows上构建我的应用程序。在编译和链接时,命令行中加入选项"-mwindows"可以调用Win32 API函数。

更具体地说,在不加"-mwindows"的情况下调用MinGW的GCC:

c:\>g++ -c main.cpp 
c:\>g++ -o main.exe main.o

上述两个命令行后的“main.exe”将在控制台中运行,Win32 API函数将无法使用。

当使用以下命令调用MinGW的GCC时带上“-mwindows”:

c:\>g++ -c main.cpp
c:\>g++ -o main.exe main.o -mwindows

现在使用“-mwindows”链接后,'main.exe'可以使用Win32 API,但当应用程序运行时,它不会启动控制台。
这个“-mwindows”选项禁用了控制台,这使我无法打印调试信息。有没有方法能够同时保留控制台和“-mwindows”选项?

@rubenvb,不不,这与Visual Studio无关。 - jondinham
2
这不一样。这里我们不谈论调试输出。部分答案可能会重叠,但并非完全重复。而且那里的一些答案是针对VS特定的。 - Jarekczek
是的,我从命令行构建和运行,没有调试器。 - jondinham
4个回答

19

-mconsole开关用于指定目标控制台子系统。确保您的进程从控制台应用程序启动时连接到现有控制台,您确实需要这样做。例如,假设您选择以目标GUI子系统并调用AllocConsole()的方式进行,就像您自己的答案一样。然后,当从另一个控制台应用程序(例如cmd.exe)启动时,您会发现您的应用程序显示一个全新的控制台,而不是使用现有的控制台。

如果您需要使用其他库,则可以使用-l命令行添加它们。控制台应用程序并不意味着它不能链接任何Win32 API函数。只是与-mconsole关联的默认库集缺少您所需的某些库。

另一方面,当构建应用程序时,您可以同时使用-mconsole-mwindows。它们不是相互排斥的。

gcc -mconsole -mwindows main.c

这将生成一个面向控制台子系统的应用程序。并自动链接标准的-mwindowsWin32库集合。这可能是实现目标最简单的方法。


我尝试在链接时添加“-mconsole”,但控制台没有出现。 - jondinham
@PaulDinh 嗯,对我来说是可以的。我按照我的更新答案所述,精确地编译了 @Jarekczek 的程序。这将输出一个控制台子系统。你真的不想使用 AllocConsole 来做这件事。除非你想要两个控制台窗口!! - David Heffernan
我从未想过将这两个“-m”开关组合在一起。如果可能的话,确实是最好的选择。 - Jarekczek
谢谢您。我不知道您可以同时使用这两个选项。 - Alex

7

我没有证据支持这个答案,只有一些成功的实验。如果我有一个类似这样的 Hello 应用:

#include <stdio.h>
#include <windows.h>

int main(void)
{
    puts("hi");
    MessageBox(NULL, "test", "test", NULL);
    GetStockObject(0);
    return 0;
}

我不能使用-mconsole编译它,因为链接器会抱怨GetStockObject。但是当我在命令行中添加了必要的库和-lgdi32开关后,该应用程序可以编译并执行得很好。也许这是保持控制台和gdi的方法。这是命令行:

gcc -mconsole test_gdi.c -lgdi32

3

2
如果您的应用程序是从已经附加了控制台的命令提示符启动的,那么这将无法实现您想要的功能。 - David Heffernan
你尝试过了吗?这种方法会导致两个控制台。 - David Heffernan
打字错误,我想回复的是-mconsole,-mwindows选项似乎使-mconsole在我的mingw上不再有效。 - jondinham
1
你使用的是哪个版本的mingw?无论如何,我已经表达了我的观点。你需要生成一个针对控制台子系统的exe文件。我可以使用-mconsole和-mwindows两种方式来实现。如果你不能,那么请使用-mconsole并用-l添加其他库。 - David Heffernan
1
我使用的是4.6.3版本。我正在使用微软工具dumpbin /headers来检查输出exe文件的子系统。 - David Heffernan
显示剩余4条评论

0
你需要手动获取 hInstance 和 nCmdShow(WinMain 参数)。您可以使用以下 C 函数来实现:
HINSTANCE GetHInstance( ) {
   return (HINSTANCE) GetModuleHandleW(NULL);
}
    
int GetNCmdShow() {
   STARTUPINFOW startupInfo;
   GetStartupInfoW(&startupInfo);
   if ((startupInfo.dwFlags & STARTF_USESHOWWINDOW) != 0) {
      return startupInfo.wShowWindow;
   }
   return SW_SHOWDEFAULT;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接