Mackenzie
Mackenzie

Reputation: 31

WinAPI Window Closes Instantly

I have been experimenting with the WINAPI trying to learn it but the window I have created closes instantly. As you see when the W key is pressed or the left button is pressed it will close the program but when running it with no buttons being pressed it still closes.

#include <windows.h>
#include <windowsx.h>


// the WindowProc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd,
    UINT message,
    WPARAM wParam,
    LPARAM lParam);

// the entry point for any Windows program
int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
{
    // the handle for the window, filled by a function
    HWND hWnd;
    // this struct holds information for the window class
    WNDCLASSEX wc;

    // clear out the window class for use
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    // fill in the struct with the needed information
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass1";

    // register the window class
    RegisterClassEx(&wc);

    // create the window and use the result as the handle
    hWnd = CreateWindowEx(NULL,
        L"WindowClass1",    // name of the window class
        L"Game",   // title of the window
        WS_OVERLAPPEDWINDOW,    // window style
        1,    // x-position of the window
        1,    // y-position of the window
        1800,    // width of the window
        1000,    // height of the window
        NULL,    // we have no parent window, NULL
        NULL,    // we aren't using menus, NULL
        hInstance,    // application handle
        NULL);    // used with multiple windows, NULL

    // display the window on the screen
    ShowWindow(hWnd, nCmdShow);

    // enter the main loop:

    // this struct holds Windows event messages
    MSG msg;

    // wait for the next message in the queue, store the result in 'msg'
    while (GetMessage(&msg, NULL, 0, 0))
    {
        // translate keystroke messages into the right format
        TranslateMessage(&msg);

        // send the message to the WindowProc function
        DispatchMessage(&msg);
    }

    // return this part of the WM_QUIT message to Windows
    return msg.wParam;
}

// this is the main message handler for the program
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // sort through and find what code to run for the message given
    switch (message)
    {
        // this message is read when the window is closed

    case WM_MOUSEMOVE:
    {

        // Retrieve mouse screen position
        int x = (short)LOWORD(lParam);
        int y = (short)HIWORD(lParam);

        // Check to see if the left button is held down:
        bool leftButtonDown = wParam & MK_LBUTTON;

        // Check if right button down:
        bool rightButtonDown = wParam & MK_RBUTTON;

        if (leftButtonDown == true)
        {
            //left click
            //example lets close the program when press w
            PostQuitMessage(0);
            return 0;
        }


    }

    case WM_KEYDOWN:
    {                        
        switch (wParam)
        {
        case 'W':

            //w pressed
            //example lets close the program when press w
            PostQuitMessage(0);
            return 0;
        }
    }

    case WM_DESTROY:
    {
        // close the application entirely
        PostQuitMessage(0);
        return 0;
    }
    default:
        break;
    }

    // Handle any messages the switch statement didn't
    return DefWindowProc(hWnd, message, wParam, lParam);
}

Upvotes: 1

Views: 1798

Answers (4)

SodaTheCoder
SodaTheCoder

Reputation: 1

When you don't receive any message in Window procedure, you should call DefWindowProc() function to handle any unprocesses message. So, you used break statement under default case in window procedure, which is wrong. More on DefWindowProc() function here: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-defwindowproca. Also, as others have stated, you did not use break statements in case blocks in window procedure. This is obivously wrong, because everything will execute, including handling from unreceived messages. And, lastly, my suggestion, you don't need to put curly brackets at the beggining of every case block. You should do that only if you declare new variables in that scope, otherwise it isn't necessary, and it worsens code readability, as too much curly brackets can only cause confusion.

Upvotes: 0

Roddy
Roddy

Reputation: 68033

Don't detect clicks via the WM_MOUSEMOVE message, use the WM_MOUSEDOWN instead.

The problem is that your code is probably launched by you clicking on something, so when your window gets its first WM_MOUSEMOVE message, the button is still actually pressed. Code runs much faster than fingers..

Upvotes: 0

icabod
icabod

Reputation: 7074

You're missing some break statements in your switch, so for example, if you get the WM_MOUSEMOVE message and the leftButtonDown != true, execution will fall through to WM_KEYDOWN, etc.

Eventually you get to case WM_DESTROY:, which will Post you a lovely QuitMessage.

As an aside, this would be very easy to spot by stepping through, statement-by-statement, in a debugger.

Upvotes: 6

manuell
manuell

Reputation: 7620

There is no break in your switch statement.

You end up exetuting

PostQuitMessage(0);

You could do something like this:

case WM_FOO:
{
  if ( bar ) {
      return 0;
  }
  break;
}

Upvotes: 3

Related Questions