34

I searched a little bit on StackOverflow and Google but couldn't get the idea. I want to start my application with this type of user programming:

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

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

But this isn't possible because I should pass the hInstance and hPrevInstance and other parameters to a WinMain function. Actually there is a Window class which I designed to make the window creation a little bit easier. I saw this implementation on SFML but I don't know how it did come to this.

Right now I'm using the usual way:

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

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

Thanks.

MahanGM
  • 2,352
  • 5
  • 32
  • 45

4 Answers4

48

You can use standard main in a "windows" app (that is, a GUI subsystem Windows application) even with the Microsoft tools, if you add the following to the Microsoft linker options:

/subsystem:windows /ENTRY:mainCRTStartup

Note that this is not necessary for the GNU toolchain.

Still for the Microsoft tools you can alternatively add this to your main file:

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

James McNellis tells you how to get the hInstance.

yoozer8
  • 7,361
  • 7
  • 58
  • 93
jcoder
  • 29,554
  • 19
  • 87
  • 130
  • 2
    Edit: instead of whining about the misleading answer I just corrected it. – Cheers and hth. - Alf Aug 03 '12 at 20:30
  • 1
    I originally rolled this edit back because I think the answer at it stood was clearer for the large majority of people trying to make this work on a windows platform, there is no need to talk about gnu because 1) most people don't use it on windows,and 2) they wouldn't have had this issue anyway.... But I don't want to get into an argument so I've put your edit back anyway :) – jcoder Aug 03 '12 at 21:16
23

GetModuleHandle(NULL) will give you hInstance. hPrevInstance is always NULL.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
14

First, GetModuleHandle(0) provides the executable's module handle, which is the same as the hInstance argument of WinMain.

With the GNU toolchaing (g++ compiler), the standard-conforming code is OK.

The Microsoft toolchain, however, only accepts the standard-conforming code by default for a console subsystem executable. To create a GUI subsystem executable with this non-conforming toolchain, using a standard main, you have to specify a Microsoft runtime library entry point that calls the standard main, namely mainCRTStartup. For a command line invocation that means…

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

As a practical matter, for working in the command line you can simply specify the entry point in the LINK environment variable:

set LINK=/entry:mainCRTStartup

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

Creating a similar standard-conforming setup for Visual Studio is perhaps not desirable, since some Visual Studio project types (mainly MFC) requires use of Microsoft's non-standard WinMain or wWinMain.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
5

hInstance is one exception to the "never use global variables" rule-of-thumb. Normally no variable actually logically has scope that's module-wide. hInstance, however, has by definition exactly module-wide scope, so actually the most logical solution is to make a global variable for it and initialize it in WinMain.

As others have suggested, you can also use GetModuleHandle(NULL).

tenfour
  • 36,141
  • 15
  • 83
  • 142
  • That's not actually true. Consider, for example, compiling a static lib. There is only one `HINSTANCE` per PE file. – Puppy Aug 03 '12 at 05:43
  • Yes but to the code using the global variable, there is no difference. The maximum scope a variable can have is module-wide. Less scope than that cannot hurt. – tenfour Aug 03 '12 at 07:32
  • But there is still no need for it to have more scope. – Puppy Aug 03 '12 at 23:43
  • its ok to use global variables as long as you treat them as part of the global state and don't try to hide them. global variables are evil when they are in global scope rather than anonymous/named struct, and when multiple worlds try to interact with them. that is, adding a global variable to you code is like extending the runtime; it's ok to do but you have to bundle them together to limit global scope pollution, preferably make them static. Good use of global variables makes it clear what resources your program is holding at the moment, bad use turns your code into a global cesspool. – Dmytro Jul 05 '17 at 17:22