Currently I'm having issues with WinMain in C (specifically in Visual Studio).
For instance...
#include <stdio.h>
#include <Windows.h>
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpCmdLine, INT nCmdShow)
{
return(0);
}
1>------ Build started: Project: GameB, Configuration: Debug x64 ------
1>LIBCMTD.lib(exe_main.obj) : error LNK2019: unresolved external symbol main referenced in function "int __cdecl invoke_main(void)" (?invoke_main##YAHXZ)
1>E:\James\VisualStudio\CProjects\GameB\x64\Debug\GameB.exe : fatal error LNK1120: 1 unresolved externals
1>Done building project "GameB.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Just this basic set-up gives me an "inconsistent annotation for WinMain" warning. I have been searching for any help for 2 days and the the closest I come to an answer is people talking about WinMain in the context of C++. I have a feeling this is a problem with Visual Studio as I was originally just using VS Code and managed to get an app (one that generated a pop-up window) to compile and run.
You just set up your winmain wrong. This should work:
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
or
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR lpCmdLine, INT nCmdShow)
{
return 0;
}
Don't forget to #include <Windows.h> and change subsystem to windows.
To use the WinMain program entry point, you need to tell the linker to target the "Windows" subsystem, rather than building a console application. Otherwise, the linker will look for (and fail to find) the standard main entry point for C programs.
In the Solution Explorer, right-click on your project and select "Properties". Then navigate to the "Linker -> System" page and select "Windows (/SUBSYSTEM:WINDOWS)" as the target:
On your "inconsistent annotation" warning, see this Q/A: Inconsistent annotation for 'WinMain'
Also, as noted in the answer by SNO, you should add the WINAPI attribute to your WinMain function.
You need to set subsystem from Console to Windows in settings, by right clicking your project in the solution explorer, selecting properties, and going to Linker->System and setting SubSystem to Windows(/SUBSYSTEM:WINDOWS).
Related
I am working on a legacy program, the executable is coded in C using just the Windows API, with Visual C++ 6.0.
Since all default libraries are removed, I cannot use WinMain() as normal. How can I specify a new entry point, I cannot find the option anywhere. I know this is possible as I have done it on Visual Studio C++ 2010.
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MessageBoxA(NULL,"Hello World!","info",0);
return 0;
}
Error.
LINK : error LNK2001: unresolved external symbol _WinMainCRTStartup
Release/calcy.exe : fatal error LNK1120: 1 unresolved externals
I found it just after posting the question. Add this below header files.
#pragma comment(linker, "/ENTRY:main")
Just working on a small project using SDL2...
System info: Windows
App info: using C (pure C, no c++), mingw-x64 & SDL2.
Now;
Firstly, SDL.h requires the main function to be renamed as WinMain.
On the other hand, when getting the screen resolution, I tended to use the GetSystemMetrics function, which requires windows.h to be included in the pre-processor section and at this point, WinMain in my code conflicts with WinMain declared previously in winbase.h. When I'm using both (SDL.h and windows.h), compiler responds:
previous declaration of 'WinMain' was here: int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd);
That's because, WinMain is declared somewhere in the winbase.h, which is auto-included via windows.h.
Is there a way to get the screen resolution w/o using GetSystemMetrics / windows.h? Any other ideas?
Ok! I've realized what I was doing wrong...
For the linking phase, I was using the following libraries and the linker was complaining about the WinMain function not to be found.
-lSDL2main
-lSDL2
Then I added the mingw32 library as shown below and the problem got solved (the order of the libraries does matter I think).
-lmingw32
-lSDL2main
-lSDL2
When I compile
#include<windows.h>
#include <commctrl.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
INITCOMMONCONTROLSEX ex;
return 0;
}
with
g++ 1.cpp -w -g -lgdi32 -lcomctl32 -o 1.exe
I get the error
1.cpp: In function 'int WinMain(HINSTANCE, HINSTANCE, LPSTR, int)':
1.cpp:8:2: error: 'INITCOMMONCONTROLSEX' was not declared in this scope
INITCOMMONCONTROLSEX ex;
^.
I suspect I am getting this error because in commctrl.h, following #if condition is not true.
#if (_WIN32_IE >= 0x0300)
typedef struct tagINITCOMMONCONTROLSEX {
DWORD dwSize;
DWORD dwICC;
} INITCOMMONCONTROLSEX,*LPINITCOMMONCONTROLSEX;
#endif
I tried compiling
#define _WIN32_IE 0x0300
#include<windows.h>
#include <commctrl.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
INITCOMMONCONTROLSEX ex;
return 0;
}
and this works fine, I don't get any errors. I looked up MSDN but there's nothing written about adding #define _WIN32_IE 0x0300 there.
Questions :
What is the purpose of _WIN32_IE ?
Do I really need to hardcode its value when MSDN writes nothing about doing so ?
The initial version of comctl32 shipped with Windows 95/Windows NT. From then on each release up to Windows 7 got a new updated version but these new versions first shipped as part of Internet Explorer. Internet Explorer 3, 4, 5, 6 and 7 usually included new versions of comctl32, shlwapi and shell32.
This is mostly ancient history these days but you still need to declare which version of Windows and IE you are targeting to unlock certain features.
Adding #define _WIN32_IE 0x0300 to your code unlocks the features introduced in IE 3.0 and your program will only run on Windows 95 ORS 2 or later, Windows 95 RTM will need IE3 or 4 to be installed.
You don't care about Windows 95 (hopefully) but the same type of #if check applies to many other newer features as well and not all of them are correctly documented on MSDN because they probably assume that you are using a Visual Studio project that is less than 20 years old.
Unfortunately the minimum OS version listed on MSDN is wrong and cannot be trusted. Microsoft has removed 99% of the information about versions before 2000 and they seem to ignore anything before 2003/Vista these days.
What is the purpose of _WIN32_IE?
The extended common controls library shipped with Internet Explorer before it became a standard part of Windows. If you set the macros to tell the SDK which version of Windows you're targeting, then the SDK will probably set the IE version for you.
The fact that you had to do this for functionality this old suggests that you're using an old version of Visual Studio and/or the SDK. You might want to consider updating.
Note that, for these common controls, you probably also want to make sure you enable Windows Visual Styles.
Do I really need to hardcode its value when MSDN writes nothing about doing so?
You should set WINVER and _WIN32_WINNT per the MSDN guidelines. Depending on the version of Visual Studio you have, you might be able to set it with a project property. You can also do it with the /D option on the compiler command line, or in a header file that's included before any Windows headers. If you use a pre-compiled header, you could do it at the top of that file.
Okay this is the sample code
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, "A threat has been detected by Windows!!", "Warning!!", MB_OK);
return 0;
}
But whenever I compile this. It gives me a Message Box as ecpected but what I get more is the Command Prompt with it. I just don't want that ugly thing how can I modify or compile my code to get only the GUI ? I am using Code::Blocks IDE.
This is related to Code Blocks IDE, you have to change the type application in your project.
From the project properties, tab Build Targets, change the type console application to GUI application.
Check: http://forums.codeblocks.org/index.php?topic=12007.0
****C newbie alert**** How do I compile a C app so that it runs without showing a console window on Windows? I'm using Windows XP and GCC 3.4.5 (mingw-vista special r3). I've googled this exhaustively and I've come up with the following which, according to what I've read, sounds like it's supposed to do the trick, but doesn't on my system:
#include <windows.h>
#include <stdlib.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
system("start notepad.exe");
}
I've also tried passing the "-mwindows" argument to GCC to no avail. The code sample launches Notepad but still flashes up a command prompt.
EDIT: FWIW I have also tried ShellExecute as an alernative to system(), although I would be happy to even get an app with an empty main() or WinMain() working at this point.
Retain the -mwindows flag and use this:
#include <windows.h>
#include <process.h>
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
execl("c:\\winnt\\system32\\notepad.exe", 0);
// or: execlp("notepad.exe", 0);
}
Note: you need the full path for the execl() call but not the execlp() one.
Edit: a brief explanation of why this works - using system() starts a shell (like cmd.exe) to exec the command which produces a console window. Using execl doesn't.