WinMain vs Main

Started by
5 comments, last by SiCrane 15 years, 3 months ago
In this thread we see how to invoke the WinMain-method manually. http://www.gamedev.net/community/forums/topic.asp?topic_id=375803 What I wonder is, what is major the diffrence between actually using the WinMain-method and creating a window from a simple main-method? Since it's working by passing NULL to all WinMain's parameters, aren't those parameters obsolete? Are there any functionality of concern that uses any of those parameters?
Advertisement
WinMain() is the entry point for an application compiled for the Windows subsystem. main() is the entry point for an application compiled for the console subsystem. When an application is started in the console subsystem you automatically get a console window. If your application runs in the Windows subsystem if you want a console window you need to allocate or attach it yourself.
The names of the start up function are set by convention not by necessity. You could name the function "sweetness" if you wanted to, so long as you configured your compiler to use the function named "sweetness" as the start up function. Microsoft chose the name "WinMain" to convey that the resulting program would execute within the GUI subsystem, leaving the more traditionally named "main" start function to convey that the resulting program would execute within the console subsystem (aka CUI).

You could write a console program with the start function WinMain if you wanted. To produce a console window you would have to use AllocConsole and then redirect stdout,stdin,stderr to use console io (eg. printf, scanf, cin, cout). If you didn't want to add that extra code, you could configure the project so that the resulting program ran in the console subsystem. I haven't tried it, but I presume that would result in the console window manifesting when the program was executed, just the same as what happens with ordinary console programs.

If you wanted to launch a window from "main" within a console program, just plug in the appropriate window set up code. The functions involved in setting up a message loop invoke the GUI subsystem automatically. You'll still have to contend with the console window, which can get messy.

Yes, the WinMain parameters are pretty much obsolete. The instance argument can be obtained using GetModuleHandle(NULL). The previous instance argument is a throwback to 16 bit windows. It's always null. And there are API functions for retrieving the command line.

It seems to me that the only reason the WinMain parameters remain is to prevent compiler complaints about missing prototypes etc.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
Quote:Original post by LessBread
You could write a console program with the start function WinMain if you wanted. To produce a console window you would have to use AllocConsole and then redirect stdout,stdin,stderr to use console io (eg. printf, scanf, cin, cout). If you didn't want to add that extra code, you could configure the project so that the resulting program ran in the console subsystem. I haven't tried it, but I presume that would result in the console window manifesting when the program was executed, just the same as what happens with ordinary console programs.
It would, but it wouldn't be quite the same as a real console program. Most tellingly, it would create a new console window even if run from a command interpreter window.
If you want to more closely emulate a console subsystem process, you could first attempt to attach to the parent process' console window. Without error handling, it'd look something like:
  BOOL b = AttachConsole(ATTACH_PARENT_PROCESS);  if (!b) {    AllocConsole();  }  freopen("conin$","r",stdin);  freopen("conout$","w",stdout);  freopen("conout$","w",stderr);

Unfortunately, this still wouldn't be exactly the same as an application run in the console subsystem. In particular, it wouldn't play nicely with pipes. Off the top of my head, I can't think of a way to cleanly emulate that.

In any case, just switching the subsystem to console wouldn't allow you to use a program with WinMain() in the console subsystem. The linker will get pissy if it doesn't find main() or wmain(); you'll also need to change the /ENTRY linker option (for MSVC anyways).
If for some reason you really needed to do that, you could simply consult the C++ runtime startup code for console applications and emulate what it does. Of course, by the time you do that, you've re-implemented everything they're doing so you might as well just code your application as a console subsystem application. Console apps can call everything in the Win32 API, so there's nothing preventing you from doing GUI stuff in a "console" application.

My free book on Direct3D: "The Direct3D Graphics Pipeline"
My blog on programming, vintage computing, music, politics, etc.: Legalize Adulthood!

I'm looking at the CRT startup code right now for MSVC 2008 and I don't see anything about allocating the console. Which source files are you referring to? Are you sure that stuff is handled by the CRT and not Windows itself?

This topic is closed to new replies.

Advertisement