Jump to content
Tuts 4 You

Need help making this starfield animation draggable


Recommended Posts

iamwho
#include <Windows.h>
#include <iostream>
#include <windowsx.h>

#define IDB_EXIT 102

PAINTSTRUCT ps;
HDC hdc;
RECT starfield_rc;

BOOL g_bDragging = FALSE;
POINT g_ptDragStart;

int WIDTH = 350;
int HEIGHT = 400;

const int numStars = 50;
const int starSpeed = 1;

struct Star
{
    int x, y;
    int speed;
};

const int NUM_STARS = 100;
Star stars[NUM_STARS];

HDC hdcMem;
HBITMAP hbmMem;
HBITMAP hbmOld;

void starfield(HDC hdc, int x, int y, RECT *rc)
{
    int width = 335;
    rc->left = x;
    rc->top = y;
    rc->right = width;
    rc->bottom = 249;

    HDC hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hbmMem = CreateCompatibleBitmap(hdc, width, 215);
    HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, hbmMem);

    HBRUSH brush = CreateSolidBrush(RGB(0, 0, 0));
    FillRect(hdcMem, rc, brush);
    DeleteObject(brush);

    for (int i = 0; i < NUM_STARS; i++)
    {
        SetPixel(hdcMem, stars[i].x, stars[i].y, RGB(255, 255, 255));
        stars[i].x = (stars[i].x + stars[i].speed) % width;
    }
    BitBlt(hdc, x, y, width, 215, hdcMem, 0, 0, SRCCOPY);
    SelectObject(hdcMem, hbmOld);
    DeleteObject(hbmMem);
    DeleteDC(hdcMem);
}
// main function
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lparam);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int nCmdShow)
{
    for (int i = 0; i < NUM_STARS; i++)
    {
        stars[i].x = rand() % 340;
        stars[i].y = rand() % 249;
        stars[i].speed = rand() % 3 + 1;
    }
    TCHAR appname[] = TEXT("Template");
    WNDCLASS wndclass;
    MSG msg;
    HWND hwnd;

    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hInstance = hInstance;
    wndclass.lpfnWndProc = WndProc;
    wndclass.lpszClassName = appname;
    wndclass.lpszMenuName = NULL;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    // check this window class is registered or not
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("Window class is not registered"), TEXT("Error...."), MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindowEx(0,
                          appname,                            // window name
                          appname,                            // window text
                          WS_VISIBLE | WS_POPUP, // set POPUP window style for no border & controls
                          100,                                // window position x
                          100,                                // window position y
                          WIDTH,                              // width
                          HEIGHT,                             // height
                          NULL,
                          NULL,
                          hInstance,
                          NULL);
    // show & update created window
    SetTimer(hwnd, 1, 10, NULL); // Set a timer to trigger every 100ms
    ShowWindow(hwnd, nCmdShow);

    // get message from queue
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return msg.wParam;
}
bool isSizingOrMoving = false;

// WndProc function
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{

    HINSTANCE hIns;
    HWND exit_button, gen_button, title, license;
    LRESULT move = NULL;
    static int xClick;
    static int yClick;

    switch (message)
    {
    case WM_CREATE:

    {
        exit_button = CreateWindow(TEXT("BUTTON"), NULL, WS_CHILD | WS_VISIBLE | BS_BITMAP,
                                   250, 360, 70, 30, hwnd, (HMENU)100, hIns, 0);
        HBITMAP exitImg = (HBITMAP)LoadImageA(GetModuleHandleA(nullptr), (LPCSTR)MAKEINTRESOURCE(IDB_EXIT), IMAGE_BITMAP, 0, 0, NULL);

        title = CreateWindow(TEXT("STATIC"), TEXT("Hello"), WS_CHILD | WS_VISIBLE, 150, 5, 120, 20, hwnd, 0, hIns, 0);

        SendMessageW(exit_button, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)exitImg);
    }

    break;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        hdc = BeginPaint(hwnd, &ps);
        starfield(hdc, 6, 31, &starfield_rc);
        EndPaint(hwnd, &ps);
        break;
    }

    case WM_TIMER:
        InvalidateRect(hwnd, &starfield_rc, FALSE);
        break;

    case WM_COMMAND:

        switch (wParam)
        {
        case 100:
            PostQuitMessage(EXIT_SUCCESS);
            return 0;
        }

        break;
    case WM_CTLCOLORSTATIC:

    {
        hdc = (HDC)wParam;

        return (LRESULT)CreateSolidBrush(RGB(0, 0, 0)); // black and white

        break;
    }

    case WM_CTLCOLOREDIT:

    {
        hdc = (HDC)wParam;

        return (LRESULT)CreateSolidBrush(RGB(0, 0, 0)); // black and white

        break;
    }

    case WM_LBUTTONDOWN:
        {
            // Start dragging
            g_bDragging = TRUE;
            g_ptDragStart.x = LOWORD(lParam);
            g_ptDragStart.y = HIWORD(lParam);
            SetCapture(hwnd);
        }
        return 0;

    case WM_MOUSEMOVE:
        {
            if (g_bDragging)
            {
                // Calculate the offset
                int dx = LOWORD(lParam) - g_ptDragStart.x;
                int dy = HIWORD(lParam) - g_ptDragStart.y;

                // Get the current window position
                RECT rc;
                GetWindowRect(hwnd, &rc);
                // Move the window by the offset
                SetWindowPos(hwnd, NULL, rc.left + dx, rc.top + dy, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
            }
        }
        return 0;

    case WM_LBUTTONUP:
        {
            // Stop dragging
            g_bDragging = FALSE;
            ReleaseCapture();
        }
        return 0;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

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

This is my starfield animation. Although you can drag the window. But if you drag it from extreme left or the top area, it gets lost. Can anyone help on how to fix this?

  • Like 2
Link to comment
iamwho
40 minutes ago, Kurapica said:

What exactly gets lost ?

When you drag it fastly from the title, it gets lost.

  • Like 1
Link to comment
jackyjask

you could save short video and embed right in the post here

  • Like 1
Link to comment
adoxa

LOWORD & HIWORD are unsigned, so when the mouse moves outside the window you're getting big values, causing it to go offscreen; use GET_X_LPARAM & GET_Y_LPARAM instead, then it will work fine.

  • Like 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...