c++winapivisual-studio-2012winmain

WinMain/Win32 Window not displaying, but shows up in Processes tab of Task Manager


I'm a newbie to c++, and I'm stuck on displaying the window. I'm not getting any errors, but my Window is not displaying on the desktop. When I open the task manager, it appears under the 'Proccesses' tab. I haven't been finding any solutions to this problem, so any help is appreciated. Thanks! :)

**Note: I'm using Microsoft Visual Studio 2012 **Note: Not exactly a newbie to c++, but more to creating a win32 application

#include <Windows.h>
#include <stdlib.h>
#include <string.h>
#include <tchar.h>

static TCHAR WindowClass[] = L"Window";

LRESULT CALLBACK WindowProc(
    HWND   WinH,
    UINT   Msg,
    WPARAM wParam,
    LPARAM lParam
    )
{
    switch (Msg)
    {
        PAINTSTRUCT pntStruct;
        static HDC hdc;

        case WM_PAINT:
        {
            BeginPaint(
                WinH,
                &pntStruct
            );
            TextOut(hdc,
                5, 5,
                L"Hello, World!", _tcslen(L"Hello, World!"));
            //pntStruct.rcPaint
            EndPaint(
                WinH,
                &pntStruct
            );

        } break;

        case WM_SIZE:
        {

        } break;

        case WM_MOVE:
        {

        } break;

        case WM_DESTROY:
        {

        } break;

        case WM_CLOSE:
        {

        } break;

        default:
        {
            return DefWindowProc(WinH, Msg, wParam, lParam);
        } break;

        case WM_ACTIVATEAPP:
        {
            if (WM_ACTIVATEAPP)
            {
                OutputDebugStringA("WM_ACTIVEAPP->TRUE");
            }
            else
            {
                OutputDebugStringA("WM_ACTIVEAPP->FALSE");
            }
        } break;

    }

    return 0;
};


int WINAPI WinMain(
    HINSTANCE Window,
    HINSTANCE PrevInstance,
    LPSTR     Cmd,
    int       CmdShow
    )
{

    WNDCLASSEX wclass;
        //wclass.cbSize =  sizeof(WNDCLASS);
        wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        wclass.lpfnWndProc = WindowProc;
        wclass.cbClsExtra = 0;
        wclass.cbWndExtra = 0;
        wclass.hInstance = Window;
        //wclass.hIcon; TODO: CREATE ICON
        //wclass.hCursor;
        //wclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
        wclass.lpszMenuName = NULL;
        wclass.lpszClassName = (LPCTSTR)WindowClass;
//      HICON     hIconSm;
        RegisterClassEx(&wclass);

    HWND CreateWin = CreateWindow(
        WindowClass,
        L"NAME OF WINDOW",
        WS_VISIBLE | WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,//WIDTH:[TODO]->Make custom width to fit window
        CW_USEDEFAULT,//HEIGHT:[TODO]->Make custom width to fit window
        0,
        0,
        Window,
        0
    );

    ShowWindow(CreateWin, CmdShow);
    UpdateWindow(CreateWin);

    MSG message;

    while (GetMessage(&message, NULL, 0, 0) > 0)
    {
        TranslateMessage(&message);
        DispatchMessage(&message);
    };

    return 0;
};

Solution

  • There are lots of things wrong with this code.

    You are declaring WindowClass as a TCHAR[], but initializing it with a wchar_t[]. Same thing with the lpString parameter of TextOut(). That will only work if UNICODE is defined for the project, otherwise you will get a compiler error. When you use TCHAR, you need to wrap string literals with the TEXT() macro so they use the correct character type. Otherwise, stop using TCHAR and just use Unicode APIs for everything. You only need to use TCHAR if your code needs to support both ANSI (Win9x/ME) and Unicode (NT4+) compilations. Nobody really supports Win9x/Me anymore, so new code should focus on just Unicode APIs.

    You are not zeroing the contents of the WNDCLASSEX structure, so all of the fields that you have intentionally commented out and not assigned values to (most importantly, the cbSize field) will contain random values from the stack. That is likely to cause RegisterClassEx() to fail, which you are not checking for. To avoid this problem, ALWAYS zero out API structures before using them. This is especially important for structures that grow in size over time (when newer Windows releases introduce new structure fields). Such structures typically have a cbSize field so the API knows which version of the structure you are using, so you must provide an accurate value. And you need to zero out any unused fields so you do not get unexpected behavior from the API.

    You are not checking if CreateWindow() fails, such as a side effect of RegisterClassEx() failing.

    Your WindowProc() is supposed to pass unhandled messages to DefWindowProc(), but you are not doing that. Most of your case blocks are simply discarding messages so Windows cannot process them. Is that what you really want? I doubt it. In particular, the default behavior of DefWindowProc() for WM_CLOSE is to destroy the window, triggering the WM_DESTROY message.

    Your WM_DESTROY handler is not calling PostQuitMessage() to put a WM_QUIT message into the calling thread's message queue so GetMessage() can return 0 to break your message loop and let the app exit.

    Your WM_PAINT handler is not using the HDC that BeginPaint() provides to you, you are drawing using an uninitialized HDC variable.

    With all of that said, try something more like this:

    #include <Windows.h>
    #include <stdlib.h>
    #include <string.h>
    #include <tchar.h> // Or: remove this
    
    static TCHAR WindowClass[] = TEXT("Window");
    // or: static WCHAR WindowClass[] = L"Window";
    
    LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
    {
        switch (uMsg)
        {
            case WM_PAINT:
            {
                static const TCHAR* HelloWorld = TEXT("Hello, World!");
                // or: const WCHAR* HelloWorld = L"Hello, World!";
    
                PAINTSTRUCT pntStruct = {0};
                HDC hdc = BeginPaint(hWnd, &pntStruct);
    
                TextOut(hdc, 5, 5, HelloWorld, _tcslen(HelloWorld));
                // or: TextOutW(hdc, 5, 5, HelloWorld, lstrlenW(HelloWorld));
    
                EndPaint(hWnd, &pntStruct);
                break;
            }
    
            case WM_SIZE:
            {
                //...
                break;
            }
    
            case WM_MOVE:
            {
                //...
                break;
            }
    
            case WM_DESTROY:
            {
                PostQuitMessage(0);
                break;
            }
    
            case WM_CLOSE:
            {
                //...
                break;
            }
    
            case WM_ACTIVATEAPP:
            {
                if (WM_ACTIVATEAPP)
                {
                    OutputDebugString(TEXT("WM_ACTIVEAPP->TRUE"));
                    // or: OutputDebugStringW(L"WM_ACTIVEAPP->TRUE");
                }
                else
                {
                    OutputDebugString(TEXT("WM_ACTIVEAPP->FALSE"));
                    // or: OutputDebugStringW(L"WM_ACTIVEAPP->FALSE");
                }
    
                break;
            }
        }
    
        return DefWindowProc(hWnd, uMsg, wParam, lParam);
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    {
        WNDCLASSEX wclass = {0}; // Or: WNDCLASSEXW
        wclass.cbSize = sizeof(wclass);
        wclass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
        wclass.lpfnWndProc = &WindowProc;
        wclass.cbClsExtra = 0;
        wclass.cbWndExtra = 0;
        wclass.hInstance = hInstance;
        wclass.hIcon = NULL; // TODO: CREATE ICON
        wclass.hCursor = NULL;
        wclass.hbrBackground = NULL;//(HBRUSH)(COLOR_WINDOW+1);
        wclass.lpszMenuName = NULL;
        wclass.lpszClassName = WindowClass;
        wclass.hIconSm = NULL;
    
        if (!RegisterClassEx(&wclass)) // Or: RegisterClassExW()
        {
            // error! Use GetLastError() to find out why...
            return 0;
        }
    
        HWND hCreateWin = CreateWindow( // Or: CreateWindowW()
            WindowClass,
            TEXT("NAME OF WINDOW"), // Or: L"NAME OF WINDOW"
            WS_VISIBLE | WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,//WIDTH:[TODO]->Make custom width to fit window
            CW_USEDEFAULT,//HEIGHT:[TODO]->Make custom width to fit window
            0,
            0,
            hInstance,
            0
        );
    
        if (!hCreateWin)    
        {
            // error! Use GetLastError() to find out why...
            return 0;
        }
    
        ShowWindow(hCreateWin, nCmdShow);
        UpdateWindow(hCreateWin);
    
        MSG message;
        while (GetMessage(&message, NULL, 0, 0) > 0)
        {
            TranslateMessage(&message);
            DispatchMessage(&message);
        };
    
        return 0;
    };