Windows API main functions
last modified October 18, 2023
In this part of the Windows API tutorial, we talk about main functions.
The main function prototypes
The main
function is an entry point to a C program.
However, it is not the first program to run. When the entry point
is main
, the program execution actually begins in a
function called mainCRTStartup
. This function is located
in the C runtime library. It initialises things like the memory manager,
file I/O support, and the argv
parameter. After that,
the mainCRTStartup
function will call the main
function.
int main(void); int main(int argc, char **argv); int main(int argc, char *argv[]);
These are the function prototypes for the main
function for
the classic console program.
#include <stdio.h> int main(void) { puts("This is a classic C program."); return 0; }
The above source code presents an example of a classic console C program.
C:\Users\Jano\Documents\WinApi\ClassicConsole>ClassicConsole.exe This is a classic C program.
This is the output of the ClassicConsole.exe
program.
The wmain function prototypes
The previous main function prototypes could receive only ASCII characters.
If we want a program that could receive wide characters from the command line,
we use the wmain
function prototypes.
int wmain(void); int wmain(int argc, wchar_t **argv); int wmain(int argc, wchar_t *argv[]);
The above wmain
function prototypes receive wchar_t
characters on the command line. When we use these prototypes, the execution
begins in a function called wmainCRTStartup
which will later
call the wmain
function.
#include <windows.h> #include <wchar.h> int wmain(int argc, wchar_t **argv) { PDWORD cChars = NULL; HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE); if (std == INVALID_HANDLE_VALUE) { wprintf(L"Cannot retrieve standard output handle\n (%d)", GetLastError()); } if (argv[1]) { WriteConsoleW(std, argv[1], wcslen(argv[1]), cChars, NULL); } CloseHandle(std); return 0; }
We have a wmain
function which can receive wide characters.
The example prints the first argument of the console program. To insert command
line arguments in Pelles C, we go to Project options and select the General tab.
There is an edit box called Command line arguments.
int wmain(int argc, wchar_t **argv) {
The wchar_t
type of the second parameter of the wmain
function tells us that the program input is in wide characters.
HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE);
The GetStdHandle
function returns a handle to the standard output.
if (std == INVALID_HANDLE_VALUE) { wprintf(L"Cannot retrieve standard output handle\n (%d)", GetLastError()); }
In case of an error, we receive the INVALID_HANDLE_VALUE
return code. For this situation we print an error message. The GetLastError
function retrieves last error code value.
WriteConsoleW(std, argv[1], wcslen(argv[1]), cChars, NULL);
We use the WriteConsoleW
function to write to the console
in wide characters.
CloseHandle(std);
The CloseHandle
function closes the opened handle
to the standard output.
C:\Users\Jano\Documents\WinApi\WindowsConsole>WindowsConsole.exe компилятор компилятор
We pass a Russian word (compiler) as a parameter to our program. The program simply prints the parameter back to the console. Note that in order to see correct characters, we need to change the default font of the console to Lucida Console. We need a true type font to display wide characters correctly.
The _tmain function prototypes
The _tmain
function is a Microsoft extension. It enables
programmers to easily create both ANSI and UNICODE builds of their programs.
It is a C macro that translates to wmain
or main
functions, depending whether the _UNICODE
constant is defined or
not.
In the past it was common to create both ANSI and UNICODE builds. Nowadays, it is recommended to create Unicode programs, unless we have a specific reason to create an ANSI build.
int _tmain(void); int _tmain(int argc, TCHAR **argv); int _tmain(int argc, TCHAR *argv[]);
These are the _tmain
function prototypes. The TCHAR
macro translates either to char
or to wchar_t
. It is
controlled by the UNICODE
constant.
#define _UNICODE #define UNICODE #ifndef UNICODE #include <stdio.h> #endif #include <windows.h> #include <tchar.h> int _tmain(int argc, TCHAR **argv) { PDWORD cChars = NULL; HANDLE std = GetStdHandle(STD_OUTPUT_HANDLE); if (std == INVALID_HANDLE_VALUE) { _tprintf(_T("Cannon retrieve standard output handle\n (%d)"), GetLastError()); } if (argv[1]) { WriteConsole(std, argv[1], _tcslen(argv[1]), cChars, NULL); } CloseHandle(std); return 0; }
The example prints its first argument if available.
#define _UNICODE #define UNICODE
Here we define two constants. These definitions mean that we are going to
build a Unicode program. They translate C macros in C runtime and
Windows header files. The _UNICODE
constant translates macros
in the C runtime. (These macros start with an underscore.)
The UNICODE
constant translates macros in the Windows header files.
#ifndef UNICODE #include <stdio.h> #endif
If the build is ANSI, we include the <stdio.h>
header.
#include <windows.h>
We include the definition of the TCHAR
macro. The macro is affected
by the UNICODE
constant.
#include <tchar.h>
We must include this header file for the _tmain
and
_tcslen
macros. They are translated depending on the
_UNICODE
constant.
int _tmain(int argc, TCHAR *argv[]) {
The _tmain
function translates in our case to wmain
and the TCHAR
macro to wchar_t
.
WriteConsole(std, argv[1], _tcslen(argv[1]), cChars, NULL);
The WriteConsole
macro is transleted to the WriteConsoleW
function. The WriteConsoleW
writes output to the console.
The _tcslen
macro is translated to wcslen
function; it
returns the lenght of the wide string.
C:\Users\Jano\Documents\WinApi\TMainEx>TMainEx.exe "операционная система" операционная система
The program takes another Russian word (operating system) as a parameter and prints it to the console.
The WinMain function prototypes
So far we had console main functions. For graphical user interface development,
we use one of the WinMain
function prototypes.
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow);
These three function prototypes are used for entry points for Windows GUI
applications. The wWinMain
function's pCmdLine
parameter contains the command-line arguments as a Unicode string. The
WinMain
function's pCmdLine
parameter contains the
command-line arguments as an ANSI string. The _tWinMain
is a C
macro that translates to other two function prototypes, depending whether the
_UNICODE
constant is defined.
When the entry point is WinMain
, the execution of the program
begins in WinMainCRTStartup
. In case of wWinMain
, the
execution begins in wWinMainCRTStartup
.
#include <windows.h> int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmdLine, int CmdShow) { MessageBoxW(NULL, szCmdLine, L"Title", MB_OK); return 0; }
This code shows a small message box on the screen. It displays the first command line argument.
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR szCmdLine, int CmdShow)
The third parameter of the wWinMain
function is a
PWSTR
(pointer to wide string). It accepts wide characters.
In this part of the Windows API tutorial, we have mentioned main functions.