I want to show the file name that is opened by OpenFileDialog but it sends the wrong text into title bar. I hace changed the character set of the project but it did not help. here is my code :
OpenFileDialog .h :
class OpenFileDialog
{
public:
OpenFileDialog(){};
void CreateOpenFileDialog(HWND hWnd, LPCWSTR Title, LPCWSTR InitialDirectory, LPCWSTR Filter, int FilterIndex);
~OpenFileDialog(){};
LPCWSTR result=L"";
};
OpenFileDialog .cpp :
void OpenFileDialog::CreateOpenFileDialog(HWND hWnd, LPCWSTR Title, LPCWSTR InitialDirectory, LPCWSTR Filter, int FilterIndex)
{
OPENFILENAME ofn;
TCHAR szFile[MAX_PATH];
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.hwndOwner = hWnd;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = Filter;
ofn.nFilterIndex = FilterIndex;
ofn.lpstrTitle = Title;
ofn.lpstrInitialDir = InitialDirectory;
ofn.lpstrFileTitle = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn))
{
result = ofn.lpstrFile;
}
else
{
result = L"Empty";
}
}
and in windows procedure in WM_COMMAND :
case WM_COMMAND:
{
if (LOWORD(wParam) == ID_FILE_OPEN)
{
OpenFileDialog ofd;
ofd.CreateOpenFileDialog(hwnd, L"Test", L"C:\\", L"All files(*.*)\0*.*\0TextFiles(*.txt)\0*.txt\0", 2);
SetWindowText(hwnd, ofd.result);
}
break;
}
thanks alot.
In your function CreateOpenFileDialog(), the buffer for storing the file name is a local array szFile[MAX_PATH]. You initialize the lpstrFile = szFile in the ofn structure, making sure that the GetOpenFileName() puts the result of user entry at the right place.
The problem is that as soon as you return from CreateOpenFileDialog(), its local variables are destroyed, including the buffer containing the file name. Hence, the resultpointer that you've set with result = ofn.lpstrFile; then points to an invalid memory location.
You can solve this by allocating the buffer directly in result in the OpenFileDialog constructor (or making it an array), and using this pointer directly with ofn.lpstrFile = buffer;
Related
I am making an app with ImGUI to choose pictures. So I need to call "OPENFILENAME" to call a dialog window, and there is my code to do it:
OPENFILENAME ofn;
::memset(&ofn, 0, sizeof(ofn));
TCHAR f1[MAX_PATH];
f1[0] = 0;
ofn.lStructSize = sizeof(ofn);
ofn.nFilterIndex = 2;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFile = f1;
ofn.Flags = OFN_FILEMUSTEXIST;
if (::GetOpenFileName(&ofn) != FALSE)
{
show_path = TRUE;
}
But later I need to have a path to image, which I chose in char type and lpstrFile is a THCAR type. I found anything to make THCAR into char.
Am I doing choosing file in right way, and if yes, how can I get in usual char format a path to file?
I am using GetOpenFileName() to get the file path, and then CopyFile() to copy the file to the same directory with a different file name.
By using GetLastError(), I am getting an error code:
0x2 - The system cannot find the file specified.
But when I used MessageBox() to see the file names, it showed the correct file names.
In addition to this, I have also tried to StrTrim() the file name, but still it did not work.
I am using Borland C++Builder 6.0.
CODE
OPENFILENAME ofn;
char szFile[260];
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = Form1->Handle;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = "All\0*.*\0Text\0*.txt\0";
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = 0;
GetOpenFileName(&ofn);
LPSTR FileName;
FileName = ofn.lpstrFile;
MessageBox (Form1->Handle, FileName, "File Name", MB_OK);
MessageBox (Form1->Handle, strcat(FileName, ".newfile"), "New File Name", MB_OK);
CopyFile(FileName, strcat(FileName,".newfile"), false);
EDITED CODE
I have tried using two variables, but it is still not working. Can anyone suggest a correction?
LPSTR FileName;
LPSTR NewFileName;
FileName = ofn.lpstrFile;
NewFileName = FileName;
strcat(NewFileName, ".newfile");
MessageBox (Form1->Handle, FileName, "File Name", MB_OK);
MessageBox (Form1->Handle, NewFileName, "New File Name", MB_OK);
CopyFile(FileName, NewFileName, false);
WORKING CODE
The below code works, but I had to add a Text Box / Edit Control. Is there way to do it without adding any extra control?
LPSTR FileName;
AnsiString NewFileName;
FileName = ofn.lpstrFile;
Edit1->Text = FileName;
NewFileName = Edit1->Text + ".bak";
MessageBox (Form1->Handle, FileName, "File Name", MB_OK);
MessageBox (Form1->Handle, NewFileName.c_str(), "New File Name", MB_OK);
You are using a single buffer for both arguments of CopyFile(), and you are appending the new extension to that buffer, so of course CopyFile() is not going to find the file to copy.
You need to use two separate buffers for the two arguments of CopyFile(), eg:
TCHAR szSrcFile[MAX_PATH];
TCHAR szDstFile[MAX_PATH+12];
OPENFILENAME ofn;
ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = Form1->Handle;
ofn.lpstrFile = szSrcFile;
ofn.lpstrFile[0] = TEXT('\0');
ofn.nMaxFile = MAX_PATH;
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 (GetOpenFileName(&ofn))
{
lstrcpy(szDstFile, szSrcFile);
lstrcat(szDstFile, TEXT(".newfile"));
MessageBox(Form1->Handle, szSrcFile, TEXT("File Name"), MB_OK);
MessageBox(Form1->Handle, szDstFile, TEXT("New File Name"), MB_OK);
CopyFile(szSrcFile, szDstFile, FALSE);
}
That being said, since you are using Borland's VCL framework, you should use the TOpenDialog component instead of GetOpenFileName() directly, and then you can use String variables for easy concatenation:
// these properties can also be set at design-time instead...
OpenDialog1->Filter = "All|*.*|Text|*.txt";
OpenDialog1->FilterIndex = 1;
OpenDialog1->Options = TOpenOptions() << ofPathMustExist << ofFileMustExist;
if (OpenDialog1->Execute())
{
String SrcFile = OpenDialog1->FileName;
String DstFile = SrcFile + ".newfile";
CopyFileA(SrcFile.c_str(), DstFile.c_str(), FALSE);
}
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);
}
}
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
How do you create the deafault Save/Open dialog boxes using pure unmanaged Win32 API ?
Following the guide here, the following code is executed when WM_CREATE message is handled in the message loop of the main window:
Ive included <Commdlg.h> also.
OPENFILENAMEA ofn;
char Buffer[300];
fill(Buffer, Buffer + 300, '\0');
ofn.lStructSize = sizeof(OPENFILENAMEA);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = Buffer;
ofn.nMaxFile = 300;
ofn.Flags = OFN_EXPLORER;
ofn.lpstrFilter = NULL;
ofn.lpstrCustomFilter = NULL;
ofn.nFilterIndex = 0;
ofn.lpstrFileTitle = NULL;
ofn.lpstrInitialDir = NULL;
ofn.lpstrTitle = NULL;
out << GetOpenFileNameA(&ofn) << endl;
out << Buffer << (int)CommDlgExtendedError();
However, this code gives NO output whatsoever. Help?!
the following code is executed when WM_CREATE message is handled
Look in the Output window and observe the first-chance exception notification for 0xc0000005, an AccessViolation exception. There's a backstop in the Wow64 emulator that swallows exceptions while WM_CREATE is being dispatched.
The exception is caused by not fully initializing the OPENFILENAMEA structure. Quick fix:
OPENFILENAMEA ofn = {0};
And favor displaying the dialog before calling ShowWindow() instead of the WM_CREATE message handler.
The overall idea is right, but if you are passing the handle of the window you are creating as the owner, then it is not going to be initialized yet.
For diagnostics, consider creating variables to store the API function return values and examining them in the debugger.
It is also more convenient and less error-prone to initialize the structure to zero, instead of explictely zeroing out unneeded members, like this:
OPENFILENAME ofn = { 0 };
GetOpenFileName blocks (for a while), and then returns either TRUE if the dialog was closed by 'OK', or FALSE if it was cancelled.
The actual result (the directory/file path) can be read from the OPENFILENAME structure.
from https://learn.microsoft.com/en-us/windows/win32/dlgbox/using-common-dialog-boxes#opening-a-file we get a utf-16 version of this, with some small changes of mine:
OPENFILENAME ofn = { 0 }; // common dialog box structure
WCHAR 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 = "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);