Search code examples
c++windowswinapiwindow

Weird cursor behavior: Almost always the resize cursor. (win32 api)


I'm working with the win32 API, and am using it to make a window. This window works, but when I open it, the cursor is a loading cursor, and every time I bring my cursor to the edge to resize it, the cursor gets 'stuck' as that resizing cursor, it doesn't go back to normal. Here's a video to explain what I'm talking about:

video

Here's the reproducible example (compile with g++ reproducible_example.cpp -mwindows -O3 -o reproducible_example.exe):

#undef UNICODE
#undef _UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

bool isRunning = true;

void *buffer;   // buffer memory
BITMAPINFO bmi; // bit map information, needed for rendering

int width, height; // main window's width and height

LRESULT __stdcall WindowProc(HWND, UINT, WPARAM, LPARAM);

int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                      LPSTR pCmdLine, int nCmdShow) {
  LPCSTR CLASS_NAME = "Class Name";

  WNDCLASS wc = {};

  wc.lpfnWndProc = WindowProc;
  wc.hInstance = hInstance;
  wc.lpszClassName = CLASS_NAME;

  RegisterClass(&wc);

  // Create the window.

  HWND hwnd = CreateWindowExA(0,                   // Optional window styles.
                              "Class Name",        // Window class
                              "Window",            // Window text
                              WS_OVERLAPPEDWINDOW, // Window style

                              // Size and position
                              CW_USEDEFAULT, CW_USEDEFAULT, 1280, 720,

                              NULL,      // Parent window
                              NULL,      // Menu
                              hInstance, // Instance handle
                              NULL       // Additional application data
  );

  if (hwnd == NULL)
    return 0;

  ShowWindow(hwnd, nCmdShow);

  bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  bmi.bmiHeader.biPlanes = 1;
  bmi.bmiHeader.biBitCount = 32;
  bmi.bmiHeader.biCompression = BI_RGB;

  // Run the message loop.
  HDC hdc = GetDC(hwnd);
  while (isRunning) {
    MSG msg;
    if (PeekMessage(&msg, hwnd, 0, 0, PM_REMOVE) > 0) {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }

    StretchDIBits(hdc, 0, 0, width, height, 0, 0, width, height, buffer, &bmi,
                  DIB_RGB_COLORS, SRCCOPY);
  }
  ReleaseDC(hwnd, hdc);
  return 0;
}

LRESULT __stdcall WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
                             LPARAM lParam) {
  switch (uMsg) {
  case WM_DESTROY:
    isRunning = false;
    return 0;
  case WM_SIZE: {
    // Calculate window height and width
    width = LOWORD(lParam);
    height = HIWORD(lParam);

    if (buffer) // If memory already exists
                // free it
      VirtualFree(buffer, 0, MEM_RELEASE);

    // Allocate buffer memory
    buffer = VirtualAlloc(0, width * height * sizeof(unsigned int),
                          MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = height;
  }
    return 0;
  }
  return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

Now, I know this isn't some weird windows bug and is definitely something with my code, because it doesn't happen in other apps which I open, and it also didn't happen when I made an equivalent window with SFML (probably because the windows api and SFML are entirely different things). Code for that window:

#include <SFML/Graphics.hpp>

int main() {
  sf::RenderWindow window(sf::VideoMode(1280, 720), "Window");
  while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
      if (event.type == sf::Event::Closed) {
        window.close();
      }

      if (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)) {
        window.close();
      }
    }
    window.clear();
    window.display();
  }
}

I want the first window to act like the second window, but the cursor is the one discrepancy I can find. I've tried googling this, but to no avail. I followed a youtube tutorial series for the window I'm having problems with. Also, on downloading the tutorial's source code and removing some code which makes it full screen and hides the cursor, it has the same problem. How do I fix this? Thank you in advance.


Solution

  • Set wc.hCursor to something other than null. If it's null, the operating system will leave the cursor alone when it enters your window, and you're supposed to set it to the cursor you want.

    Most likely you want the boring old arrow cursor. You can get that cursor by calling LoadCursor(NULL, IDC_ARROW).