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_to_dotnet is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.