Windows programming - C - Save file function

Please support our C++ advertiser: Intel Parallel Studio Home
Thread Solved

Join Date: Aug 2005
Posts: 188
Reputation: bops is an unknown quantity at this point 
Solved Threads: 3
bops bops is offline Offline
Junior Poster

Re: Windows programming - C - Save file function

 
0
  #11
Feb 14th, 2006
Ok I will post all of the code i have been using for saving the files...
This is the WM_COMMAND Message processing for saving files for the MDIClient...
  1. case CM_FILE_SAVE:
  2. {
  3. LPSTR WindowText;
  4.  
  5. DWORD dwTextLength;
  6. dwTextLength = GetWindowTextLength(hwnd);
  7.  
  8. if (dwTextLength > 0)
  9. {
  10. DWORD dwBufferSize;
  11. dwBufferSize = dwTextLength + 1;
  12.  
  13. WindowText = GlobalAlloc(GPTR, dwBufferSize);
  14.  
  15. if(WindowText != NULL)
  16. {
  17. if ( ! GetWindowText(hwnd, WindowText, dwBufferSize) )
  18. {
  19. MessageBox(hwnd,"Error Getting window text",0,MB_ICONERROR);
  20. }
  21. }
  22. else
  23. {
  24. MessageBox(hwnd,"Error allocating memory for text",0,MB_ICONERROR);
  25. }
  26.  
  27. }
  28. else
  29. {
  30. MessageBox(hwnd,"No Window text",0,MB_ICONERROR);
  31. }
  32.  
  33. // Text of the child window is retrieved correctly !!
  34. HANDLE hFile;
  35.  
  36. hFile = CreateFile(WindowText, GENERIC_READ, FILE_SHARE_READ, NULL,
  37. OPEN_EXISTING, 0, NULL);
  38.  
  39. if (hFile != INVALID_HANDLE_VALUE)
  40. {
  41. if ( ! SaveFile(hwnd,GetDlgItem(hwnd,IDC_CHILD_EDIT),WindowText) )
  42. {
  43. MessageBox(hwnd,"Could not save file",0,MB_ICONERROR);
  44. }
  45. }
  46. else
  47. {
  48. if ( ! SaveFileAs(hwnd,GetDlgItem(hwnd,IDC_CHILD_EDIT)))
  49. {
  50. MessageBox(hwnd,"Could not save file",0,MB_ICONEXCLAMATION);
  51. }
  52. }
  53. CloseHandle(hFile);
  54. SendDlgItemMessage(hwnd,IDC_CHILD_EDIT,EM_SETMODIFY,FALSE,0);
  55. }
  56. break;
  57. case CM_FILE_SAVEAS:
  58. {
  59. SaveFileAs(hwnd,GetDlgItem(hwnd,IDC_CHILD_EDIT));
  60. SendDlgItemMessage(hwnd,IDC_CHILD_EDIT,EM_SETMODIFY,FALSE,0);
  61. }
  62. break;

This is the SaveFile function...
  1. BOOL SaveFile(HWND owner,HWND hEdit, LPCTSTR pszFileName)
  2. {
  3. HANDLE hFile;
  4. BOOL bSuccess = FALSE;
  5.  
  6. MessageBox(owner,pszFileName,0,0); // Testing if the parameter from pszFileName has been recieved
  7.  
  8. // Create the file (overwrite existing files) and assign the handle to hFile
  9. hFile = CreateFile(pszFileName, GENERIC_WRITE, 0, NULL,
  10. CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  11.  
  12. //########## RETURNS INVALID HANDLE VALUE ############
  13. //###### MAYBE PROBLEM WITH CREATING THE FILE ########
  14. //####################################################
  15.  
  16. // If the handle to the file has been created sucessfully
  17. if(hFile != INVALID_HANDLE_VALUE)
  18. {
  19. DWORD dwTextLength;
  20. // Get text length of edit control within child window for allocating memory
  21. dwTextLength = GetWindowTextLength(hEdit);
  22.  
  23. // If there is no text then there is nothing to write to the file that has been created
  24. if(dwTextLength > 0)
  25. {
  26. LPSTR pszText;
  27. // Amount of me mory to be allocated = textsize + 1 for null terminator
  28. DWORD dwBufferSize = dwTextLength + 1;
  29.  
  30. // Allocate memory for the text
  31. pszText = GlobalAlloc(GPTR, dwBufferSize);
  32. if(pszText != NULL)
  33. {
  34. // Get the Text to be saved to the file fromt he edit control
  35. // within the child window.
  36. if(GetWindowText(hEdit, pszText, dwBufferSize))
  37. {
  38. DWORD dwWritten;
  39.  
  40. // Write the text to the file
  41. if(WriteFile(hFile, pszText, dwTextLength, &dwWritten, NULL))
  42. bSuccess = TRUE;
  43.  
  44. //Set Title of child window to the filename
  45. SetWindowText(owner, pszFileName);
  46. MessageBox(owner,"File saved",0,0); // Using to find error
  47. }
  48. else
  49. {
  50. MessageBox(owner,"Could not retrieve text",0,MB_ICONERROR); // Using to find error
  51. }
  52. // Free memory allocated for text
  53. GlobalFree(pszText);
  54. }
  55. else
  56. {
  57. MessageBox(owner,"Could not allocate memory",0,MB_ICONERROR); // Using to find error
  58. }
  59. }
  60. else
  61. {
  62. MessageBox(owner,"No text",0,0);// Using to find error
  63. }
  64. // Close the handle to the file if it exists
  65. CloseHandle(hFile);
  66. }
  67. else
  68. {
  69. ShowLastError ( ) //Function calls GetLastError and then displays the error in a MessageBox
  70. MessageBox(owner,"Invalid handle value",0,MB_ICONERROR); // Using to find error
  71. }
  72. return bSuccess;
  73. }

Finally this is the SaveFileAs Function...
  1.  
  2. BOOL SaveFileAs(HWND owner,HWND hwnd)
  3. {
  4. BOOL RetVal = FALSE;
  5.  
  6. char szFile[MAX_PATH];
  7. OPENFILENAME sfn;
  8. ZeroMemory(&sfn, sizeof(sfn));
  9. sfn.lStructSize = sizeof(sfn);
  10. sfn.hwndOwner = hwnd;
  11. sfn.lpstrFile = szFile;
  12. //
  13. // Set lpstrFile[0] to '\0' so that GetOpenFileName does not
  14. // use the contents of szFile to initialize itself.
  15. //
  16. sfn.lpstrFile[0] = '\0';
  17. sfn.nMaxFile = sizeof(szFile);
  18. sfn.lpstrFilter = "C Source File(*.c*)\0*.c;\0C++ Source File(*.cpp*)\0*.cpp;\0C Header File(*.h*)\0*.h;\0Resource Script(*.rc*)\0*.rc;\0";
  19. sfn.nFilterIndex = 1;
  20. sfn.lpstrFileTitle = NULL;
  21. sfn.nMaxFileTitle = 0;
  22. sfn.lpstrInitialDir = NULL;
  23. sfn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
  24. sfn.lpstrDefExt = "c";
  25.  
  26. GetSaveFileName(&sfn);
  27.  
  28. if (SaveFile(owner,hwnd,szFile))
  29. {
  30. RetVal = TRUE;
  31. }
  32.  
  33. return RetVal;
  34. }

As you can see the WM_COMMAND Message for the MDIClient procedure attempts to create a handle to an existing file..not overwriting! If the file exists the handle is created successfully which is then checked further down. If the file exists, the SaveFile function is called directly, using the WindowText of the ChildWindow as the Filename parameter and if the file does not exist, the SaveFileAs function is called. This basically does what most Text Editors do, decides whether to automatically save the file using its current filename or save the file as the user specifies...

When the user chooses to SaveFileAs...or the program decides that function is to be used, it works fine...the correct dialog appears and and prompts the user to overwrite existing files etc. The SaveFileAs function as you can see calls the SaveFile function and specifies the owner window parameter, the richedit control handle parameter and the filename specified by the user. THIS WORKS FINE !

My problem however is that when the file exists already and the user clicks save, the program takes the current filename of the file from the Title of the Child window and uses this as the FileName parameter. When this method is taken the error is generated. GetLastError() shows me what I have described above that the file is being used by another process etc.

Since when the SaveFile() function is called by the SaveFileAs() function and works correctly, I dont think there can be a problem with SaveFile(). So therefore I think there is something wrong with when I am passing the parameters to SaveFile() straight from the WM_COMMAND processing of the MDI Client.

Thanks for your help...tough 1
Last edited by bops; Feb 14th, 2006 at 9:36 am. Reason: Missed something out.
Reply With Quote Quick reply to this message  
Join Date: Jun 2005
Posts: 1,496
Reputation: WolfPack has a spectacular aura about WolfPack has a spectacular aura about WolfPack has a spectacular aura about 
Solved Threads: 104
Moderator
WolfPack's Avatar
WolfPack WolfPack is offline Offline
Mentally Challenged Mod.

Re: Windows programming - C - Save file function

 
1
  #12
Feb 14th, 2006
Okay. Got it. You are trying to open the same file twice.
Here are the culprits.
case CM_FILE_SAVE:
{
	//...
	HANDLE hFile;
	hFile = CreateFile( WindowText, GENERIC_READ, FILE_SHARE_READ, NULL,
				OPEN_EXISTING, 0, NULL );
	// This function is successfull only when there is a file of name WindowText.
	if ( hFile != INVALID_HANDLE_VALUE )
	{
		// YOu are here because hFile is valid. i.e the File is open.
		// Now you are calling save File. Go to the SaveFile now.
		if ( !SaveFile( hwnd, GetDlgItem( hwnd, IDC_CHILD_EDIT ), WindowText )) 
		{
			MessageBox( hwnd, "Could not save file", 0, MB_ICONERROR );
		}
	}
	else
	{
	//...
	}
}
BOOL SaveFile( HWND owner, HWND hEdit, LPCTSTR pszFileName )
{
	HANDLE hFile;

	// We are here because hFile was valid. ie a File of pszFileName is open already. But you call CreateFile again.

	// Try to create a file of name pszFileName...
	hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
				FILE_ATTRIBUTE_NORMAL, NULL );

	// But we had opened it before calling this function remember?
	// Therefore this hFile should be Invalid with Access Error.

	if ( hFile != INVALID_HANDLE_VALUE )
	{
		// Will not go here if the file exists...
	}
	else
	{
	}
	return bSuccess;
}

Did you get where you are going wrong? You can fix it with a crude fix like this.

case CM_FILE_SAVE:
{
	//...
	HANDLE hFile;
	hFile = CreateFile( WindowText, GENERIC_READ, FILE_SHARE_READ, NULL,
				OPEN_EXISTING, 0, NULL );
	// This function is successfull only when there is a file of name WindowText.
	if ( hFile != INVALID_HANDLE_VALUE )
	{
		// YOu are here because hFile is valid. i.e the File is open.
                // Crude Fix - Close the file :-)
                CloseHandle( hFile );
		// Now you are calling save File. Go to the SaveFile now.
		if ( !SaveFile( hwnd, GetDlgItem( hwnd, IDC_CHILD_EDIT ), WindowText )) 
		{
			MessageBox( hwnd, "Could not save file", 0, MB_ICONERROR );
		}
	}
	else
	{
	//...
	}
}
BOOL SaveFile( HWND owner, HWND hEdit, LPCTSTR pszFileName )
{
	HANDLE hFile;

	// We are here because hFile was valid. ie a File of pszFileName is open already. But you call CreateFile again.

	// Try to create a file of name pszFileName...
	hFile = CreateFile( pszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
				FILE_ATTRIBUTE_NORMAL, NULL );

	// Thank god we closed the file.
	if ( hFile != INVALID_HANDLE_VALUE )
	{
		//...
	}
	else
	{
	}
	return bSuccess;
}

As I said that was a Crude Fix. Basically your design is wrong. That was why the error occured in the first place.

The Better Pseudocode will be something like this.

Global Variable FileName
On FileSave

if ( FileName not NULL )
SAve to FileName
else
Show File Save As
Assign Value for FileName
Save to FileName
Close FileName
On FileSaveAs

Show Save As Dialog
Assign value to FileName
Save To FileName
Close FileName
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 188
Reputation: bops is an unknown quantity at this point 
Solved Threads: 3
bops bops is offline Offline
Junior Poster

Re: Windows programming - C - Save file function

 
0
  #13
Feb 14th, 2006
Haha thankyou so much...genious lol I didnt realise that...I thought that I wouldnt have to close the handle to the file if hFile = INVALID_HANDLE_VALUE, but i suppose it would be better to do that just to avoid errors. Anyway thanks a lot, it is very much appreciated.
Reply With Quote Quick reply to this message  
Join Date: Jun 2005
Posts: 1,496
Reputation: WolfPack has a spectacular aura about WolfPack has a spectacular aura about WolfPack has a spectacular aura about 
Solved Threads: 104
Moderator
WolfPack's Avatar
WolfPack WolfPack is offline Offline
Mentally Challenged Mod.

Re: Windows programming - C - Save file function

 
0
  #14
Feb 15th, 2006
I thought that I wouldnt have to close the handle to the file if hFile = INVALID_HANDLE_VALUE
Actually you dont have to close it if
  1. hFile == INVALID_HANDLE_VALUE
. But in this case the condition is
  1. if ( hFile != INVALID_HANDLE_VALUE )
  2. {
  3. ...
. So you have to close it before trying to open it again.
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:



Other Threads in the C++ Forum
Thread Tools Search this Thread



Tag cloud for C++
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC