Search code examples
c++imagewinapidialogbmp

Using SS_BITMAP style on static control in a dialog frame


I am attempting to write a slot machine Win32 App that uses images to display the result of the spins. I know how to display an image on a normal LRESULT CALLBACK frame, but i'm lost when it comes to displaying images on a dialog. Could anyone help me by explaining(in-depth) how i would go about displaying images? I really appreciate it.

My current Dialog callback:

BOOL CALLBACK DlgProc(HWND hwnd, UINT message,WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
        case WM_INITDIALOG:         //dialog created
            g_hbmObject = LoadBitmap(GetModuleHandle(NULL), MAKEINTRESOURCE(IDB_OBJECT));
                                    //initialize slotmachine class
            Machine.Initialize(time(0));
            if(g_hbmObject == NULL) //test if object is loaded correctly
                std::cerr << "Could not load ball..";
        break;
        case WM_COMMAND:            //switch command
            switch(LOWORD(wParam))
            {
                case IDC_SPIN:      //slot machine spins
                                    //put spin function, decide what to display
                                    //do i put the display image command here? or where?
                break;
                case IDC_EXIT:      //exit button
                    DeleteObject(g_hbmObject);
                    EndDialog(hwnd, 0);
                break;
            }
        break;
        case WM_CLOSE:
        case WM_DESTROY:            //case program is exited
            DeleteObject(g_hbmObject);
            PostQuitMessage(0);
        break;
        default:
            return FALSE;
    }
    return TRUE;
}

Solution

  • The following code registers a "REEL" window class: a control that displays a spinning reel for a slot machine. You can create multiple instances of it on a dialog using resource statements like:

    CONTROL         "",IDC_REEL1,"REEL",0,14,50,40,40
    CONTROL         "",IDC_REEL2,"REEL",0,70,50,40,40
    

    The reel spins endlessly, but you can easily add private messages to start and stop it.

    As explained in the comments, it expects a bitmap representing a reel with resource ID IDB_REEL.

    HBITMAP g_hbmpReel;
    
    LRESULT CALLBACK ReelWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        const int ReelTimerId = 5;
    
        switch (message)
        {
        case WM_CREATE:
            SetTimer(hWnd, ReelTimerId, 10, 0);
            break;
        case WM_DESTROY:
            KillTimer(hWnd, ReelTimerId);
            break;
        case WM_SIZE:
            SetWindowPos(hWnd, 0, 0, 0, 40, 40, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
            break;
        case WM_TIMER:
            if (wParam == ReelTimerId)
            {
                int offset = GetWindowLong(hWnd, 0);
                offset = (offset + 5) % 120;
                SetWindowLong(hWnd, 0, offset);
                InvalidateRect(hWnd, 0, FALSE);
            }
            break;
        case WM_PAINT:
            {
                PAINTSTRUCT ps;
                HDC hdc = BeginPaint(hWnd, &ps);
                HDC hdcReel = CreateCompatibleDC(hdc);
                HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcReel, g_hbmpReel);
                int offset = GetWindowLong(hWnd, 0);
                BitBlt(hdc, 0, 0, 40, 40, hdcReel, 0, offset, SRCCOPY);
                SelectObject(hdcReel, hbmpOld);
                DeleteDC(hdcReel);
                EndPaint(hWnd, &ps);
            }
            break;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
        return 0;
    }
    
    ATOM RegisterReel(HINSTANCE hInstance)
    {
        WNDCLASSEX wcex = {0};
    
        wcex.cbSize = sizeof(WNDCLASSEX);
    
        wcex.lpfnWndProc    = ReelWndProc;
        // Window data used to hold the position of the reel
        wcex.cbWndExtra     = sizeof(int);
        wcex.hInstance      = hInstance;
        wcex.hCursor        = LoadCursor(NULL, IDC_ARROW);
        wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
        wcex.lpszClassName  = L"REEL";
    
        // IDB_REEL is a 40x160 bitmap representing a reel with THREE 40x40 symbols.
        // The bottom 40x40 square should be the same as the topmost.
        g_hbmpReel = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_REEL));
    
        return RegisterClassEx(&wcex);
    }