Browsing for file location and saving wstring to file - c++

I am trying to create a file dialog where the user selects an existing file or create a new one by selecting a location and entering a name. The browsing works fine, but when I try to save the file, it gives me the following error
fail: file != NULL.
I also have to convert the text that is meant to be written to the file from std::wstring to char *, hence the sprint. I can't figure out what I am doing wrong.
Below is the code I am currently working with:
HMODULE hModule = GetModuleHandleW(NULL);
OPENFILENAME ofn;
char szFile[260]; // buffer for file name
HWND hwnd = NULL; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrTitle = TEXT("Select a location to save the information");
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = TEXT("All\0*.*\0Text\0*.TXT\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if(GetSaveFileName(&ofn)==TRUE)
{
wchar_t hostName[2048] = L"";
DWORD sz = 2048;
hf = CreateFile(ofn.lpstrFile, GENERIC_READ,
0, (LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
(HANDLE)NULL);
char * buffer = new char[242];
//sprintf(buffer, "%ls", hostInfo.c_str());
_snprintf_s(buffer,242, _TRUNCATE, "%ls", hostInfo.c_str());
std::ofstream stream(ofn.lpstrFile, std::ofstream::binary);
stream.write(buffer, 243);
//delete[] buffer;
stream.close();
}
EDIT:
Found the problem. I did not set the pointer for lpstrFile resulting in the selected path being NULL hence the File != NULL assert fail

Related

Call to GetOpenFileNameA causes common dialog error 2

I'm trying to open a dialog box using GetOpenFileNameA. However, the dialog does not open. Instead, I get a nice CommDlgError 2. Searching Google and StackOverflow for this error did not produce any helpful results.
Confusingly, this code works on a school computer that also uses Visual Studio, albeit a different version.
Note: All variables not declared in this block of code are "global" variables that are only accessible within the main code module.
void GetInputFile()
{
char szFileNameIN[MAX_PATH];
char szFileNameOUT[MAX_PATH];
// get the input file name
OPENFILENAME ofn;
ZeroMemory(&fInputPath, sizeof(fInputPath));
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = LPWSTR("Any File\0*.*\0");
ofn.lpstrFile = LPWSTR(fInputPath);
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = LPWSTR(szFileNameIN);
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrTitle = LPWSTR("Select an input File");
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if (GetOpenFileNameA(LPOPENFILENAMEA(&ofn))) // user selected an input file
{
}
else {
// Get error
TCHAR error[MAX_LOADSTRING];
wsprintf(error,TEXT("%i"),CommDlgExtendedError());
MessageBox(NULL,error,TEXT("ERROR"),MB_OK);
}
}
Those awful (LPWSTR) casts tell me that you are compiling with UNICODE defined, so the OPENFILENAME struct you are using is actually OPENFILENAMEW; given that you are using GetOpenFileNameA, you have to use OPENFILENAMEA (or use straight GetOpenFileName with wide strings).
(and remember that, as a rule of thumb, if you have to cast pointers to/from anything different than void * and similar, you are probably doing something wrong; adding pointer casts will only silence the compiler, not make the error go away)
You are using the TCHAR version of OPENFILENAME. Since you are assigning Unicode string pointers to its fields, that means your project is being compiled with UNICODE defined, so TCHAR maps to wchar_t and OPENFILENAME maps to OPENFILENAMEW. But you are using ANSI character buffers and the ANSI version of GetOpenFileName(), and using incorrect type-casts all over the place.
So get rid of all the type-casts, and then either:
use proper TCHAR types and APIs for everything:
void GetInputFile()
{
TCHAR szFileNameIN[MAX_PATH];
TCHAR szFileNameOUT[MAX_PATH];
// get the input file name
OPENFILENAME ofn;
ZeroMemory(&fInputPath, sizeof(fInputPath));
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = TEXT("Any File\0*.*\0");
ofn.lpstrFile = fInputPath; // must be TCHAR[]...
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = szFileNameIN;
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrTitle = TEXT("Select an input File");
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn)) // user selected an input file
{
}
else
{
// Get error
TCHAR error[MAX_LOADSTRING];
wsprintf(error, TEXT("%i"), CommDlgExtendedError());
MessageBox(NULL, error, TEXT("ERROR"), MB_OK);
}
}
use proper CHAR/WCHAR types and APIs for everything:
void GetInputFile()
{
WCHAR szFileNameIN[MAX_PATH];
WCHAR szFileNameOUT[MAX_PATH];
// get the input file name
OPENFILENAMEW ofn;
ZeroMemory(&fInputPath, sizeof(fInputPath));
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = L"Any File\0*.*\0";
ofn.lpstrFile = fInputPath; // must be WCHAR[]...
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = szFileNameIN;
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrTitle = L"Select an input File";
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if (GetOpenFileNameW(&ofn)) // user selected an input file
{
}
else
{
// Get error
WCHAR error[MAX_LOADSTRING];
wsprintfW(error, L"%i", CommDlgExtendedError());
MessageBoxW(NULL, error, L"ERROR", MB_OK);
}
}
void GetInputFile()
{
CHAR szFileNameIN[MAX_PATH];
CHAR szFileNameOUT[MAX_PATH];
// get the input file name
OPENFILENAMEA ofn;
ZeroMemory(&fInputPath, sizeof(fInputPath));
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFilter = "Any File\0*.*\0";
ofn.lpstrFile = fInputPath; // must be CHAR[]...
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFileTitle = szFileNameIN;
ofn.nMaxFileTitle = MAX_PATH;
ofn.lpstrTitle = "Select an input File";
ofn.Flags = OFN_DONTADDTORECENT | OFN_FILEMUSTEXIST;
if (GetOpenFileNameA(&ofn)) // user selected an input file
{
}
else
{
// Get error
CHAR error[MAX_LOADSTRING];
wsprintfA(error, "%i", CommDlgExtendedError());
MessageBoxA(NULL, error, "ERROR", MB_OK);
}
}

GetSaveFileName can't open user's temp-dir

I use a similar function to get the path and the filename, which I want to use to save a file on a Windows 8.1 machine:
void TestFunc()
{
OPENFILENAME ofn;
WCHAR szFileName[MAX_PATH] = L"C:\\Users\\biber\\AppData\\Local\\temp\\test.txt";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = (LPWSTR)szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = (LPCWSTR)L"txt";
GetSaveFileName(&ofn);
return ;
}
The problem is, that the SaveFileDialog doesn't show me initial the Temp-Path. If I change the szFileName to another path than the %TEMP%, it works.
It doesn't work with the temp path.

Strange behaviour with GetOpenFileName dialog and opencv

I'm trying to use the open file dialog to allow the user of my program to select an image which will then be processed using opencv.
I have a function in which i open the dialog and try to load the image:
Mat load_image()
{
OPENFILENAME ofn; // common dialog box structure
TCHAR szFile[260]; // buffer for file name
HWND hwnd; // owner window
HANDLE hf; // file handle
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
// Set lpstrFile[0] to '\0' so that GetOpenFileName does not
// use the contents of szFile to initialize itself.
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)==TRUE)
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
char filepath[260];
wcstombs(filepath, ofn.lpstrFile, 260);
cout << filepath << endl;
Mat src = imread(filepath);
//imshow("src", src);
return src;
}
The code you see here works, opens the dialog box and allows the user to choose a file. The filepath is then converted to string (to be passed into imread). The problem occurs when I try to interact with the image src.
For example, if I uncomment the 'imshow' line, GetOpenFileName will return 0 and the dialog box doesnt even open. This happens more than not, I cant actually access the image because everything I try causes this to happen.
In order for the function to work it is called like this:
load_image();
But if I try to assign an image ie:
img = load_image();
the same problem occurs. Help! What could possibly be causing this?
As it is mentioned in the previous comment, the CreateFile method locks the image file so cv::imread() is not able to access/read its content.
Try to avoid using of CreateFile, I see no reason of using it in your code, the following code is working well:
cv::Mat load_image()
{
cv::Mat outMat;
OPENFILENAME ofn; // common dialog box structure
TCHAR szFile[260]; // buffer for file name
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = NULL;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn) == TRUE)
{
char filepath[260];
wcstombs(filepath, ofn.lpstrFile, 260);
cout << filepath << endl;
outMat = cv::imread(filepath);
}
return outMat;
}
int main()
{
cv::Mat image = load_image();
cv::imshow("image", image);
cv::waitKey(-1);
return 0;
}
These are just things I notice in your code...so I don't expect this to work but maybe it will help.
imread is probably failing. You opened the file using CreateFile and locked it as a result of opening it (No Sharing Attributes. See CreateFile for more info). imread tries to open the file anyways so you don't need to create your own handle! Just use the file path received and call imread instead of using CreateFile.
Mat src;
if (GetOpenFileName(&ofn)==TRUE)
{
// Succeeded in choosing a file
char filepath[260];
wcstombs(filepath, ofn.lpstrFile, 260);
cout << filepath << endl;
src = imread(filepath);
}
Also if you don't have an hwnd then you should just set ofn.hwndOwner=NULL instead of arbitrarily setting it.
If you so choose to use CreateFile (maybe you wish to open it for manual read access for your own purposes outside of OpenCV), then make sure to call CloseHandle( HANDLE h ) on the file handle before you open the file again.

OPENFILENAME open dialog

i want to get a full file path by open file dialog in win32.
i do it by this function:
string openfilename(char *filter = "Mission Files (*.mmf)\0*.mmf", HWND owner = NULL) {
OPENFILENAME ofn ;
char fileName[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = owner;
ofn.lpstrFilter = filter;
ofn.lpstrFile = fileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = "";
ofn.lpstrInitialDir ="Missions\\";
string fileNameStr;
if ( GetOpenFileName(&ofn) )
fileNameStr = fileName;
return fileNameStr;
}
it's work fine and return path . but i can't write into the that file i get path of it with openfilename.
note :
i call this code to write to the file (serialization):
string Mission_Name =openfilename();
ofstream ofs ;
ofs = ofstream ((char*)Mission_Name.c_str(), ios::binary );
ofs.write((char *)&Current_Doc, sizeof(Current_Doc));
ofs.close();
Try this for write:
string s = openfilename();
HANDLE hFile = CreateFile(s.c_str(), // name of the write
GENERIC_WRITE, // open for writing
0, // do not share
NULL, // default security
CREATE_ALWAYS, // Creates a new file, always
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
DWORD writes;
bool writeok = WriteFile(hFile, &Current_Doc, sizeof(Current_Doc), &writes, NULL);
CloseHandle(hFile);
... and read:
HANDLE hFile = CreateFile(s.c_str(), // name of the write
GENERIC_READ, // open for reading
0, // do not share
NULL, // default security
OPEN_EXISTING, // Creates a new file, always
FILE_ATTRIBUTE_NORMAL, // normal file
NULL); // no attr. template
DWORD readed;
bool readok = ReadFile(hFile, &Current_Doc, sizeof(Current_Doc), &readed, NULL);
CloseHandle(hFile);
Help links:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb540534%28v=vs.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
Try closing it and reopen then for writing.

GetOpenFileName triggers breakpoint

I'm trying to call GetOpenFileName like this:
int main(int argc, char* argv[])
{
OPENFILENAME ofn; // common dialog box structure
wchar_t szFile[260]; // buffer for file name
HWND hwnd; // owner window
HANDLE hf; // file handle
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
wchar_t title[500]; // to hold title
GetConsoleTitle( title, 500 );
HWND hwndConsole = FindWindow( NULL, title );
ofn.hwndOwner = hwndConsole;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = L"All\0*.*\0Text\0*.TXT\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
// Display the Open dialog box.
if (GetOpenFileName(&ofn)==TRUE)
hf = CreateFile(ofn.lpstrFile,
GENERIC_READ,
0,
(LPSECURITY_ATTRIBUTES) NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
The prog stops (message: example.exe has triggered a breakpoint(not one I placed)) at "if (GetOpenFileName(&ofn)==TRUE)" When I break i get a message that no source is available.
If I do not break and just press continue, the dialog box pops up and works as expected. What am I doing wrong?
I just noticed that it works without problems in release mode...
One possible issue:
ofn.nMaxFile should be the number of characters, not the size in bytes of the buffer. Try this instead:
ofn.nMaxFile = sizeof(szFile) / sizeof(wchar_t);