0

I am fairly new to Windows Desktop programming and am having trouble figuring out how to setup a linker in VS Code to use the Win32 API, or if that is even in fact my issue. Namely my code seems to compile fine but I receive but I get linker errors of unresolved external symbols to basic Windows functions like CreateWindowExW and DispatchMessage.

Executing task: Build with Microsoft (R) MSVC C/C++ Version 19.35.32217.1 for x86 

Starting build...
cl.exe /Zi /MT /MTd /O2 /EHsc /nologo /std:c++20 /FeC:\source\StarTrekArmada\src/Output/NewArmada.exe C:\source\StarTrekArmada/src/*.cpp
cl : Command line warning D9025 : overriding '/MT' with '/MTd'
WinMain.cpp
WinMain.obj : error LNK2019: unresolved external symbol __imp__TranslateMessage@4 referenced in function _WinMain@16
WinMain.obj : error LNK2019: unresolved external symbol __imp__DispatchMessageW@4 referenced in function _WinMain@16
WinMain.obj : error LNK2019: unresolved external symbol __imp__PeekMessageW@20 referenced in function _WinMain@16
WinMain.obj : error LNK2019: unresolved external symbol __imp__DefWindowProcA@16 referenced in function "long __stdcall MainWndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?MainWndProc@@YGJPAUHWND__@@IIJ@Z)
WinMain.obj : error LNK2019: unresolved external symbol __imp__PostQuitMessage@4 referenced in function "long __stdcall MainWndProc(struct HWND__ *,unsigned int,unsigned int,long)" (?MainWndProc@@YGJPAUHWND__@@IIJ@Z)
WinMain.obj : error LNK2019: unresolved external symbol __imp__RegisterClassExW@4 referenced in function _WinMain@16
WinMain.obj : error LNK2019: unresolved external symbol __imp__CreateWindowExW@48 referenced in function _WinMain@16
WinMain.obj : error LNK2019: unresolved external symbol __imp__ShowWindow@8 referenced in function _WinMain@16
C:\source\StarTrekArmada\src\Output\NewArmada.exe : fatal error LNK1120: 8 unresolved externals

Build finished with error(s).

The program in question is just the basics to open a blank window, a Hello World in WinMain() so to speak. I can run The Code fine in Visual Studio 2022, and it does exactly what I expect, opens a blank window that I can move around and close. I note in VS I have go into the Project Properties, Linker options and set the Subsystem to Windows (/SUBSYSTEM:WINDOWS) for this, and I am assuming that connects the project to the Win32 APIs, however I can't seem to figure out how to manually do this via Command Line in VS Code, and I can't find any relevant answers anywhere online.

My Configuration for VS is fairly simple:

Tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "cppbuild",
            "label": "Build with Microsoft (R) MSVC C/C++ Version 19.35.32217.1 for x86",
            "command": "cl.exe",
            "args": [
                "/Zi",
                "/MT",
                "/MTd",
                "/O2",
                "/EHsc",
                "/nologo",
                "/std:c++20",
                "/Fe${fileDirname}/Output/NewArmada.exe",
                "${workspaceFolder}/src/*.cpp"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$msCompile"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "compiler: cl.exe"
        }
    ]
}

c_cpp_properties.json

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/src/include/**"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "windowsSdkVersion": "10.0.22000.0",
            "compilerPath": "cl.exe",
            "cStandard": "c17",
            "cppStandard": "c++20",
            "intelliSenseMode": "windows-msvc-x64"
        }
    ],
    "version": 4
}

I am using Microsoft's MSVC toolchain and the cl compiler. Is my issue actually the link settings and if it is, what commands do I need to set it correctly for Windows Desktop Development? I am Developing on Windows 11 Pro 64-bit I have VS 2022 Installed with the Desktop C++ Development Workload installed (Including Windows 11 SDK)

The Code:

//
// Main entry point to the program.
//
#include <windows.h>

LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

int APIENTRY WinMain(
    _In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPSTR cmdLine,
    _In_ int cmdShow
)
{
    const wchar_t* pClassName = L"Test Class Name";

    WNDCLASSEXW wc = { 0 };
    wc.cbSize = sizeof(wc);
    wc.style = CS_OWNDC;
    wc.lpfnWndProc = MainWndProc;  // WindProc Not Yet Define
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = nullptr;
    wc.hCursor = nullptr;
    wc.hbrBackground = nullptr;
    wc.lpszMenuName = nullptr;
    wc.lpszClassName = pClassName; // Must be prefixed with "L" because Microsoft
    wc.hIconSm = nullptr;

    // Register Window Class
    RegisterClassExW(&wc);
    HWND hwnd = CreateWindowExW(
        0,
        pClassName,
        L"Test Window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        nullptr,
        nullptr,
        hInstance,
        nullptr
    );

    if(hwnd == NULL)
    {
        return 0;
    }
    ShowWindow(hwnd, SW_SHOW);

    while(true)
    {
        MSG msg;
        if (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
        {
            if (msg.message == WM_QUIT)
            {
                break;
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessageW(&msg);
            }
        }
    }
    
    return 1;
}
 
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
    }

    // If we reach here, we have nothing left we wish to do, so let 
    // Windows handle it. 
    return  DefWindowProc(hWnd, msg, wParam, lParam);
}
  • If you're using MSVC the easiest is to have the compiler dump linker input into the .obj files. The [`comment` pragma](https://learn.microsoft.com/en-us/cpp/preprocessor/comment-c-cpp) allows you to do that. You can add `pragma comment(lib, "user32")` somewhere in your source code to instruct the linker to (later) look for imports in *user32.lib*. – IInspectable May 11 '23 at 15:20
  • Thank you very much! That seems to have done the trick. I am now getting the same result as I do in vs 2022. – NeonHelium May 11 '23 at 15:24
  • If you Google `TranslateMessage` to find the msdn documentation and check the Requirements section it tells you the library to link: [https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage#requirements](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-translatemessage#requirements) I mention this because you will have the same problem in the future with a different library and this way you will know how to quickly find the solution. – drescherjm May 11 '23 at 15:37

0 Answers0