4

I have this compile error that I dont understand what is wrong. My Microsoft Visual Studio project is a Win32 Project (not console):

1>MSVCRT.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
1>C:\Users\Soribo\Desktop\C++ Programming\Visual C++ Programming\KeyboardHook\Release\KeyboardHook.exe : fatal error LNK1120: 1 unresolved externals

EDIT: After making #include "stdafx.h" as the 1st line the compile error is:

1>MSVCRT.lib(crtexew.obj) : error LNK2001: unresolved external symbol _WinMain@16
1>C:\Users\Soribo\Desktop\C++ Programming\Visual C++ Programming\KeyboardHook\Release\KeyboardHook.exe : fatal error LNK1120: 1 unresolved externals

EDIT: hmm, I have defined WinMain function haven't I? see below code:

/*
  Application: 
*/

#include <windows.h>
#include <cstdlib>
#include "stdafx.h"

using namespace std;

static HHOOK     keyboardHook;
static HINSTANCE gInstance;


// Functions List //
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam );
HHook ActivateKeyboardHook( HookProc hookProc, HINSTANCE hInstance );
bool DeactivateKeyboardHook( HHook keyboardHook );


int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
//int WINAPI WinMain( HINSTANCE gInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = gInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(DKGRAY_BRUSH);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = L"Custom Class";
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // if registration of main class fails
    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"Window Registration Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        L"Custom Class",
        L"App Name",
        WS_CAPTION|WS_MINIMIZEBOX|WS_VISIBLE|WS_OVERLAPPED|WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT, 600, 500,
        NULL, NULL, gInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, L"Window Creation Failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

LRESULT CALLBACK LowLevelKeyboardProc( int nCode, WPARAM wParam, LPARAM lParam )
{
    /*if ( code < 0 )
    {
        return CallNextHookEx( NULL, code, wParam, lParam );
    }*/  

    switch ( wParam )
    {
        case WM_KEYDOWN:
        {
            MessageBox( NULL, L"Notify", L"Key Down", MB_OK );        
        }
        break;
        case WM_KEYUP:
        {
            MessageBox( NULL, L"Notify", L"Key Up", MB_OK );                        
        }
        break;
        case WM_SYSKEYDOWN:
        {
            MessageBox( NULL, L"Notify", L"Sys Key Down", MB_OK );                        
        }
        break;
        case WM_SYSKEYUP:
        {
            MessageBox( NULL, L"Notify", L"Sys Key Up", MB_OK );                        
        }
        break;
        default:
        {
        } 
        break;
    }

    return CallNextHookEx( NULL, nCode, wParam, lParam );
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

    switch(msg)
    {
        case WM_CREATE:
        {                  
             keyboardHook = ActivateKeyboardHook( &LowLevelKeyboardProc, gInstance );
        }    
        break;
        case WM_COMMAND:
        {
             switch(LOWORD(wParam)) 
             {

                  default:
                  break;
             }
        }
        break;
        case WM_CLOSE:
        {
            DeactivateKeyboardHook( keyboardHook );
            DestroyWindow(hwnd);
        }
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default: 
        break;
    }

    return DefWindowProc(hwnd, msg, wParam, lParam);
}

HHOOK ActivateKeyboardHook( HookProc hookProc, HINSTANCE hInstance )
{
     return SetWindowsHookEx( WH_KEYBOARD_LL, hookProc, hInstance, 0 );
}

bool DeactivateKeyboardHook( HHook keyboardHook )
{
     return UnhookWindowsHookEx( keyboardHook );
}
Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
user593747
  • 1,484
  • 4
  • 32
  • 52

2 Answers2

6

That is not compilation error, that is linker error, and it means your program doesn't define WinMain function, which is entry point of the program.

Make sure your program has this function:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);

See this MSDN documentation:


#include <windows.h>
#include <cstdlib>
#include "stdafx.h"

If you've chosen precompiled header file, then the above is wrong, stdafx.h should be included at the beginning of the file. So change the order as:

#include "stdafx.h"  //this should be first line of the program!
#include <windows.h>
#include <cstdlib>

And I think you don't need to include <windows.h> as most likely stdafx.h have included it already. Check it out.

Now why should it be included first? Because precompiled header, as the name suggests, is a precompiled header. The compiler doesn't compile it everytime. Instead, it compiles all the content in it once. If you don't include it first, the compiler will not know that whether to compile the files included before it or not, because it may be that those files are already included in stdafx.h and so has already be compiled. See this topic:

Community
  • 1
  • 1
Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • @Nawaz Thanks very much for your help. Why does it need to be 1st in MVS? EDIT: After doing those changes it still gives the same compiler error? – user593747 Jun 12 '11 at 06:10
  • @user593747: Did you include it first? Did it solve it? If not, post all the error messages! – Nawaz Jun 12 '11 at 06:12
  • 2
    If you include other headers before StdAfx.h, then that could change the meaning of StdAfx.h. That would make it impossible to precompile the header. – Johan Råde Jun 12 '11 at 06:13
  • @user: 1. Generally it's referred to as MSVC++, because the IDE is not what compiles for you, the compiler is. :) 2. Because that's just how precompiled headers work. – Billy ONeal Jun 12 '11 at 06:14
  • @user: because when precompiled headers are enabled (as by default), the compiler first searches for `#include "stdafx.h"` ignoring everything on the way. – Yakov Galka Jun 12 '11 at 06:15
  • I'm surprised to see that anyone writes "raw" Win32 applications nowadays. It is not the easiest way to build a GUI program. – Johan Råde Jun 12 '11 at 06:17
  • @Nawaz: See the edit for the current compiler error but it hasnt changed & @user763305 win32 is AWESOME it makes you understand what the windows system is doing & makes you feel powerful, .NET makes me feel impotent. – user593747 Jun 12 '11 at 06:19
  • @user593747: Recall that did you change the project settings manually? – Nawaz Jun 12 '11 at 06:34
  • @user593747: Do one experiment. Create another separate `Win32 Project` with default files, and program. DO NOT EDIT or CHANGE ANYTHING. Try building it. See if it builds successfully or not. – Nawaz Jun 12 '11 at 06:36
  • @Nawaz: I created a default Win32 program & built it successfully & ran it successfully. I have made many win32 C++ programs on DevC++ but never on MSVC++ 2010, this is a nightmare! Do you know how to get to the project settings dialog, I can get to Project Properties but not Project Settings – user593747 Jun 12 '11 at 06:41
  • @user593747: Yes. I meant Project Properties. Did you change it manually? – Nawaz Jun 12 '11 at 06:43
  • @Nawaz No I dont think so, I have had MSVC++ for a while so I dont remember – user593747 Jun 12 '11 at 06:45
  • @user593747: I think you did some mistake while creating the project. Anyway, one simple solution is: Just create another project and copy all files from this project to the new one. And build the new one. That will make sure that you're building it with default settings. Use the new project and delete the old one. – Nawaz Jun 12 '11 at 06:47
0

It's not a compile error, it's a link error. Basically, you're using a function that you declared somewhere, but never defined in any translation unit.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552