New to visual C++: Problem with saving a bmp from a frame after loading the bmp into it

So I’ve been using chatgpt to help (please don’t start with the AI hate). But basically it can’t find what is wrong.

Please bear in mind that this app is my first attempt at building anything with visual c++.

So I have created one dll and one single application main.cpp

Within the dll I have the following two functions:

void LoadBitmapFile(HWND hWnd, HBITMAP & hBitmap, int staticControlId) {
    OPENFILENAME ofn;
    wchar_t szFile[260];
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hWnd;
    ofn.lpstrFile = szFile;
    ofn.lpstrFile[0] = '';
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = L"BMP files*.bmp";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if (GetOpenFileName(&ofn) == TRUE) {
        if (hBitmap) {
            DeleteObject(hBitmap);
        }
        hBitmap = (HBITMAP)LoadImage(NULL, ofn.lpstrFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
        SendMessage(GetDlgItem(hWnd, staticControlId), STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);
    }
}

void SaveBitmapFile(HWND hWnd, int staticControlID) {
    HWND hWndStatic = GetDlgItem(hWnd, staticControlID);
    if (hWndStatic == NULL) {
        MessageBox(hWnd, L"Static control not found.", L"Error", MB_OK | MB_ICONERROR);
        return;
    }

    HBITMAP hBitmap = (HBITMAP)SendMessage(hWndStatic, STM_GETIMAGE, IMAGE_BITMAP, 0);
    if (hBitmap == NULL) {
        MessageBox(hWnd, L"No bitmap associated with the static control.", L"Error", MB_OK | MB_ICONERROR);
        return;
    }

    OPENFILENAME ofn;
    WCHAR szFile[MAX_PATH] = L"";

    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.hwndOwner = hWnd;
    ofn.lpstrFile = szFile;
    ofn.lpstrFile[0] = '';
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = L"Bitmap Files (*.bmp)*.bmpAll Files (*.*)*.*";
    ofn.nFilterIndex = 1;
    ofn.lpstrFileTitle = NULL;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = NULL;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_OVERWRITEPROMPT;

    if (GetSaveFileName(&ofn) == TRUE) {
        HDC hdcBitmap = CreateCompatibleDC(NULL);
        if (hdcBitmap != NULL) {
            BITMAP bmp;
            GetObject(hBitmap, sizeof(bmp), &bmp);

            BITMAPFILEHEADER bmfh;
            BITMAPINFOHEADER bmih;

            bmfh.bfType = 0x4D42;  // "BM"
            bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + bmp.bmWidthBytes * bmp.bmHeight;
            bmfh.bfReserved1 = 0;
            bmfh.bfReserved2 = 0;
            bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

            bmih.biSize = sizeof(BITMAPINFOHEADER);
            bmih.biWidth = bmp.bmWidth;
            bmih.biHeight = bmp.bmHeight;
            bmih.biPlanes = 1;
            bmih.biBitCount = 24;
            bmih.biCompression = BI_RGB;
            bmih.biSizeImage = bmp.bmWidthBytes * bmp.bmHeight;
            bmih.biXPelsPerMeter = 0;
            bmih.biYPelsPerMeter = 0;
            bmih.biClrUsed = 0;
            bmih.biClrImportant = 0;

            HANDLE hFile = CreateFile(ofn.lpstrFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
            if (hFile != INVALID_HANDLE_VALUE) {
                DWORD dwBytesWritten;

                WriteFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesWritten, NULL);
                WriteFile(hFile, &bmih, sizeof(BITMAPINFOHEADER), &dwBytesWritten, NULL);

                BYTE* lpBitmapBits = (BYTE*)malloc(bmp.bmWidthBytes * bmp.bmHeight);
                GetBitmapBits(hBitmap, bmp.bmWidthBytes * bmp.bmHeight, lpBitmapBits);
                WriteFile(hFile, lpBitmapBits, bmp.bmWidthBytes * bmp.bmHeight, &dwBytesWritten, NULL);

                free(lpBitmapBits);
                CloseHandle(hFile);
                MessageBox(hWnd, L"Bitmap saved successfully.", L"Success", MB_OK | MB_ICONINFORMATION);
            }
            else {
                MessageBox(hWnd, L"Failed to create file.", L"Error", MB_OK | MB_ICONERROR);
            }

            DeleteDC(hdcBitmap);
        }
        else {
            MessageBox(hWnd, L"Failed to create compatible DC.", L"Error", MB_OK | MB_ICONERROR);
        }
    }
}

Then in my main.cpp I have a button load the bmp and a separate button to save the bmp (at least that’s the theory). It all seems so easy until it doesn’t work. The open button works a treat and displays the bmp clearly in the desired frame, however the save button does not do what I want it to at all.

I’ve tried variations, (ideally I’d like save to be more of a “save as” than a “save” but for now I’d be happy with anything that works).

...
#define IDC_picture_IMAGE 1002 // ID for the "picture Image" 
#define IDC_OPEN_picture 2002 // ID for the "Open picture" button
#define IDC_SAVE_picture 2003 // ID for the "Save picture" button
...

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    static HBITMAP hBitmap1 = NULL, hBitmap2 = NULL, hBitmap3 = NULL;
...
    static HWND hWndOpenpicture = NULL; // Handle to the "Open picture" button
    static HWND hWndSavepicture = NULL; // Handle to the "Save picture" button
...
    switch (uMsg) {
    case WM_CREATE: {
...
        // Create title labels
        hWndTitle2 = CreateWindowEx(0, L"STATIC", L"picture Image", WS_CHILD | WS_VISIBLE | SS_CENTER,
            PANEL_WIDTH, 0, PANEL_WIDTH, TITLE_HEIGHT, hwnd, NULL, NULL, NULL);
...
        // Create "Open picture" button
        hWndOpenpicture = CreateWindowEx(0, L"BUTTON", L"Open picture", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            PANEL_WIDTH, TITLE_HEIGHT + PANEL_HEIGHT, PANEL_WIDTH, TITLE_HEIGHT, hwnd, (HMENU)IDC_OPEN_picture, NULL, NULL);

        // Create "Save picture" button
        hWndSavepicture = CreateWindowEx(0, L"BUTTON", L"Save picture", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
            PANEL_WIDTH, 2* TITLE_HEIGHT +  PANEL_HEIGHT, PANEL_WIDTH, TITLE_HEIGHT, hwnd, (HMENU)IDC_SAVE_picture, NULL, NULL);
...
        break;
    }
    case WM_COMMAND: {
        int wmId = LOWORD(wParam);
        switch (wmId) {
...
        case IDC_OPEN_picture:
            LoadBitmapFile(hwnd, hBitmap2, IDC_picture_IMAGE);
            InvalidateRect(hwnd, NULL, TRUE);
            break;
        case IDC_SAVE_picture:
            SaveBitmapFile(hwnd, IDC_picture_IMAGE);
        }
    break;
    }
    case WM_PAINT: {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
...
        // Paint bitmap 2 in panel 2
        if (hBitmap2) {
            HDC hdcMem2 = CreateCompatibleDC(hdc);
            SelectObject(hdcMem2, hBitmap2);
            BitBlt(hdc, PANEL_WIDTH, TITLE_HEIGHT, PANEL_WIDTH, PANEL_HEIGHT, hdcMem2, 0, 0, SRCCOPY);
            DeleteDC(hdcMem2);
        }
...

        }
        EndPaint(hwnd, &ps);
        break;
    }
    case WM_DESTROY:
...
        if (hBitmap2) DeleteObject(hBitmap2);
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

...
}

I’ll try my best to respond to any responses, but beware I’m totally new and will likely need idiot language to understand – think explaining to your granny and I’ll get it.

I’m using visual studio 2019 community edition (if that’s relevant).

The problem I get with the current iteration is

The popup message “Static control not found”.

When I tried only defining 1002 and not bothering with 2002 or 2003 I could get as far as a popup message of “No bitmap associated with the static control.”

Essentially there is something fundamental wrong with the logic – probably wrong with my logic in defining the static controls.

So all I want is the “Save picture” button to save the picture that is displayed in the panel above it.

Thanks in advance!

I asked chatgpt and it didn’t help (at least didn’t help me) it suggested

Verify Resource Definitions: If controls are defined in a resource file, ensure that IDC_SAVE_HIDDEN (2003) matches the correct ID and is correctly assigned.

New contributor

New_to_dotnet is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật