Jump to content

C - GetOpenFileName() fails on Windows 95

Recommended Posts

I want to make my programs compatible with all versions of Windows from Windows 95 to Windows 8. I'm currently working on a small word processor and I need to have working open and save file requesters. However, I can't seem to get the GetOpenFileName function to work properly. This is the code for a simple bitmap viewer program I made. It runs fine on Windows 98, XP, Vista, and 7, but on Windows 95, GetOpenFileName fails, and CommDlgExtendedError() returns error code 1 (CDERR_STRUCTSIZE). Now, I specified sizeof(ofn) for ofn.lStructSize, which should be valid, and it is on other Windows versions. Any ideas why this happens?

#include <windows.h>#include <stdio.h>#include <commctrl.h>#define MSGBOX_ERROR(MESSAGE) MessageBox(NULL, MESSAGE, NULL, MB_OK|MB_ICONERROR)#define COMMAND_EXIT 9000#define COMMAND_OPEN 9001#define COMMAND_STRETCH 9002LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam){	static BOOL IsStretched;	static HBITMAP hBmp;	switch(msg)	{		case WM_PAINT:		{			if(hBmp==NULL) //Leave WM_PAINT to DefWindowProc if no bitmap is loaded.				goto defwndproc;			RECT client_rect;			GetClientRect(hwnd,&client_rect);			BITMAP bmp;			PAINTSTRUCT ps;			HDC hdc = BeginPaint(hwnd, &ps);			HDC hdcmem = CreateCompatibleDC(hdc);			HBITMAP hbmOld = SelectObject(hdcmem, hBmp);			GetObject(hBmp,sizeof(bmp),&bmp);			if(IsStretched)				StretchBlt(hdc,0,0,client_rect.right-client_rect.left,client_rect.bottom-client_rect.top,hdcmem,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);			else				BitBlt(hdc,0,0,bmp.bmWidth,bmp.bmHeight,hdcmem,0,0,SRCCOPY);			SelectObject(hdcmem, hbmOld);			DeleteDC(hdcmem);			EndPaint(hwnd, &ps);			break;		}		case WM_CREATE:		{				HMENU hMenuBar = CreateMenu();			HMENU hFileMenu = CreatePopupMenu();			HMENU hViewMenu = CreatePopupMenu();			AppendMenu(hFileMenu,MF_STRING,COMMAND_OPEN,"&Open");			AppendMenu(hFileMenu,MF_SEPARATOR,0,NULL);			AppendMenu(hFileMenu,MF_STRING,COMMAND_EXIT,"&Exit");			AppendMenu(hViewMenu,MF_STRING|MF_UNCHECKED,COMMAND_STRETCH,"&Stretch to fit window");			AppendMenu(hMenuBar,MF_STRING|MF_POPUP,(UINT)hFileMenu,"&File");			AppendMenu(hMenuBar,MF_STRING|MF_POPUP,(UINT)hViewMenu,"&View");			SetMenu(hwnd,hMenuBar);			IsStretched = FALSE;			break;		}		case WM_SIZE:			if(IsStretched)				InvalidateRect(hwnd,NULL,FALSE);			break;		case WM_COMMAND:			switch(LOWORD(wParam))			{				case COMMAND_OPEN:				{					OPENFILENAME ofn;					char szFile[MAX_PATH];					ZeroMemory(&ofn,sizeof(ofn));					ofn.lStructSize		= sizeof(ofn);					ofn.hwndOwner		= hwnd;					ofn.lpstrFile		= szFile;					ofn.lpstrFile[0]	= '\0';					ofn.nMaxFile		= sizeof(szFile);					ofn.lpstrFilter		= "Windows Bitmap (*.bmp)\0*.bmp\0All Files\0*.*\0";					ofn.nFilterIndex	= 1;					ofn.lpstrFileTitle	= NULL;					ofn.nMaxFileTitle	= 0;					ofn.lpstrInitialDir	= NULL;					ofn.Flags			= OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST;					GetOpenFileName(&ofn);					//Testing to see if GetOpenFileName worked					if(fopen(ofn.lpstrFile,"r")==NULL)					{						char errorbuf[20];						sprintf(errorbuf,"Failed to open a file. Error code: %hu",(unsigned short)CommDlgExtendedError());						MSGBOX_ERROR(errorbuf);						return 0;					}					hBmp = LoadImage(NULL,szFile,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);					if(!hBmp)						MSGBOX_ERROR("Failed to load bitmap.");					InvalidateRect(hwnd,NULL,FALSE);					UpdateWindow(hwnd);					break;				}				case COMMAND_EXIT:					goto close;				case COMMAND_STRETCH:					IsStretched = !IsStretched;					InvalidateRect(hwnd,NULL,TRUE);					break;			}			break;		case WM_CLOSE:			close:			ExitProcess(0);		default:			defwndproc:			return DefWindowProc(hwnd,msg,wParam,lParam);	}	return 0;}int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){	InitCommonControls();	WNDCLASS rwc;	rwc.style			= 0;	rwc.lpfnWndProc		= MainWndProc;	rwc.cbClsExtra		= 0;	rwc.cbWndExtra		= 0;	rwc.hInstance		= hInst;	rwc.hIcon			= NULL;	rwc.hCursor			= LoadCursor(NULL, IDC_ARROW);	rwc.hbrBackground	= (HBRUSH)(COLOR_APPWORKSPACE+1);	rwc.lpszMenuName	= NULL;	rwc.lpszClassName	= "yo mama";	RegisterClass(&rwc);	HWND hMainWnd = CreateWindow("yo mama", "Bitmap Viewer", WS_OVERLAPPEDWINDOW,		CW_USEDEFAULT, CW_USEDEFAULT, 450, 450,		0, 0, hInst, 0);	ShowWindow(hMainWnd,nCmdShow);	UpdateWindow(hMainWnd);	MSG msg;	msgloop:		GetMessage(&msg,NULL,0,0);		TranslateMessage(&msg);		DispatchMessage(&msg);	goto msgloop;}
Link to comment
Share on other sites

Cross-compatibility windows programming is a pure PITA, simply because Microsoft changes the API around all the time and does an incredibly poor job of documenting those changes.  You really have to get the SDK's for every version in order to even have a chance at getting these changes right.


Solving this problem will require that you delve into Windows.H and post what the "ofn" structure is.  Your results clearly indicate that the "ofn" structure was changed between Windows 95 and 98 to be larger.  Once you can find out what the changes were, you can adjust your code accordingly since most of the API changes are designed to be backward compatible (code that works in 95 works on 98).  Basically that should mean testing for version (GetVersion/GetVersionEx) and then passing the different structure size.


Barring any concrete documentation, I'd start subtracting fields from the end of the structure in relationship to its size and then see when it starts working.  But in any event, please post what the "ofn" structure is, so others might see what is going on.

Link to comment
Share on other sites

Thanks for your input, Glenn9999.


Aha! I found the issue. The OPENFILENAME structure is declared in commdlg.h. I came across this macro in that header which looked intriguing:

#if (WINVER >= 0x0500)...#define OPENFILENAME_SIZE_VERSION_400 76

 OPENFILENAME_SIZE_VERSION_400 is the size of the OPENFILENAME structure on previous Windows versions. After a quick Google search, I found that starting with Windows 2000, 3 additional members (pvReserved,dwReserved,FlagsEx) were added, so the size of the OPENFILENAME structure is larger. I don't use these members anyway, so seting ofn.lStructSize to OPENFILENAME_SIZE_VERSION_400 fixed the problem, and now it works on all Windows versions.


FYI, an OPENFILENAME structure contains info on how the "Open" dialog box is to be displayed, and is passed to the GetOpenFileName() function.

Link to comment
Share on other sites

After a quick Google search, I found that starting with Windows 2000, 3 additional members (pvReserved,dwReserved,FlagsEx) were added, so the size of the OPENFILENAME structure is larger. I don't use these members anyway, so seting ofn.lStructSize to OPENFILENAME_SIZE_VERSION_400 fixed the problem, and now it works on all Windows versions.


Good you have it solved.  Looks like that was what it was.

Link to comment
Share on other sites

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
  • Recently Browsing   0 members

    • No registered users viewing this page.

  • Create New...