IFileDialog Overwrite File and Open Folder/File - c++

I have two issues related to IFileSaveDialog & IFileOpenDialog I did not managed to find a solution for, I hope you can help me.
When the user is saving a file with an existing name, the "Confirm Save As" prompt appears. I need the "Yes" option to be marked as default instead of "No".
The User can open/load a file or a folder from the same dialog.
Can these be done with this API? Or maybe other API?
I tried to google it and go over Microsoft documentation to find a solution, but with no luck.

When the user is saving a file with an existing name, the "Confirm Save As" prompt appears. I need the "Yes" option to be marked as
default instead of "No".
As #Remy Lebeau said that, you can use IFileDialogEvents::OnOverwrite method. And use MessageBox to create a suitable dialog.
Some code:
IFACEMETHODIMP OnOverwrite(IFileDialog* , IShellItem*psi, FDE_OVERWRITE_RESPONSE* response) {
int msgboxID = MessageBox(
NULL,
(LPCWSTR)L"Windows already exists, \n\rDo you want to replace it?",
(LPCWSTR)L"Confirm Save As",
MB_ICONWARNING | MB_YESNO | MB_DEFBUTTON1
);
switch (msgboxID)
{
case IDYES:
*response = FDEOR_ACCEPT;
break;
case IDNO:
*response = FDEOR_REFUSE;
break;
}
return S_OK;
}
Debug:
The User can open/load a file or a folder from the same dialog. Can
these be done with this API? Or maybe other API?
There is no such method in the document, you can only select a folder or file.
As a compromise, I suggest that you can create a new MessageBox and set two buttons in it, namely "select folders" and "select files". When the user selects folders, folder dialog with the FOS_PICKFOLDERS style is opened. Otherwise, Files is selected by default.

Related

How to select specific file using CfileDialog in MFC

I would like to open a file dialog and allow user to select only the file with name "myapplication.ini" and user can only browse folder's to check if the file is existing to select it.
so i came across CFileDialog which would do almost what i want other than limiting it to display only files with name "myapplication.ini"
currently my usage of CFiledialog
CFileDialog FileDialog(TRUE,"features.ini", NULL,OFN_HIDEREADONLY,NULL);
I am not sure what could should be changed to make it work as i expected.
That sounds like a poor UI. Even if you filter out all but that file, the user can override the filter. If you aren't going to allow the user to make a choice of file name, why ask them for their choice?
What you are actually doing, in my view, is asking the user to select a folder. So instead of the file dialog, show them a folder selection dialog, CFolderPickerDialog.
Declare the filter string like this:
static TCHAR BASED_CODE szFilter[] = _T("features.ini (features.ini)|features.ini|");
and then pass it to your CFileDialog ctor:
CFileDialog FileDialog(TRUE, NULL, NULL, OFN_HIDEREADONLY, szFilter);

C++ MFC CFileDialog won't save

I created a MFC programm with a menu option to Save a file. When I click it it shows the CFileDialog and I can choose the location where I want to save my file. When I Click save in the Dialog, it closes the dialog, but after that it does nothing. AND it didn't save my file. What am I doing wrong?
Here is the code
CFileDialog *dlg = new CFileDialog(FALSE, L"dr", NULL, NULL,
L"Drawings (*.dr)|*.dr|"
L"All Files||");
bool result = dlg->DoModal();
if(result)
{
MessageBox(0, dlg->GetPathName(), L"Draw", 0);
}
The bool result, is purely there to check if there is no problem/error.
The file save dialog is called "file save dialog" because its caption says "Save File" and it allows you to only select a single file. That does not mean that it actually does any saving of files. It just returns to you the filename selected by the user. You are still responsible for writing the code which will save your file using this filename.
The CFileDialog does not save the file for you, it only provides you with a dialog for the user to determine where (and if!) the file should be saved. The return value of DoModal() should be compared to IDOK before proceeding to save. From the dialog's member functions you can get the path and filename the user selected. With that, you can create/open a file and save your data.

Issues with CFileDialog for multiple file selection

I'm using the following code to retrieve multiple file selection via UI:
CFileDialog fd(TRUE, NULL, NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER,
NULL, hParentWnd ? CWnd::FromHandle(hParentWnd) : NULL);
fd.m_pOFN->Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_NODEREFERENCELINKS;
int nLnBuff = 32767;
TCHAR* pBuffFileSelect = new TCHAR[nLnBuff];
memset(pBuffFileSelect, 0, nLnBuff * sizeof(TCHAR));
fd.m_ofn.lpstrFile = pBuffFileSelect;
fd.m_ofn.nMaxFile = nLnBuff;
if(fd.DoModal() == IDOK)
{
POSITION fileNamesPosition = fd.GetStartPosition();
while(fileNamesPosition != NULL)
{
CString strSelPath = fd.GetNextPathName(fileNamesPosition);
TRACE("path: %s\n", CStringA(strSelPath));
}
}
delete[] pBuffFileSelect;
So when I try it on my PC, I run the method above and when the "Open File" dialog open up, just as a test, I navigated to my desktop and selected all files using Ctrl+A shortcut and then clicked Open. As a result I started getting the following paths:
The first path is a link, which is correct (it exists on my Public desktop):
"C:\Users\Public\Desktop\avp.lnk"
But then the second path is wrong. It gives me:
"C:\Users\Public\Desktop\1.txt"
when it's supposed to be (for the desktop that I picked):
"C:\Users\UserName\Desktop\1.txt"
and then every consecutive path has "Public" instead of "UserName".
I should point out that I have several user accounts set up on this PC and the one that I'm testing this method from is a Standard user account. The app that I'm running this method from is not running elevated (or with regular user privileges) so it should not have access to other user accounts anyway.
So what am I doing wrong here?
Checked the sources, and GetOpenFileName assumes that all the items are in fact in the same file path. This isn't true for the Desktop (there are items in different paths merged into one shell view), and so you'll see the bad behavior.
The solution is to use the Common Item dialogs, which use the shell namespace rather than file system paths. All the desktop items are in a common shell path, and then you can use IShellItem::GetDisplayName to convert to a file system path.
Unfortunately, MFC doesn't have a wrapper for the common item dialog, so you'll have to manage that yourself.

Allowing IFileOpenDialog to pick a folder that doesn't exist yet

I'm trying to create a dialog to select a new folder to save files into. The IFileOpenDialog class works great except that it won't allow a new folder to be picked.
I.e. "Folder: C:\existings\new-folder" in the bottom of the dialog pops up the following message:
new-folder
Path does not exist.
Check the path and try again.
Here's the code I've got:
IFileDialog* fileDialog
CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&fileDialog));
DWORD options;
fileDialog->GetOptions(&options);
options &= ~FOS_FILEMUSTEXIST;
options &= ~FOS_PATHMUSTEXIST;
fileDialog->SetOptions(options | FOS_PICKFOLDERS);
fileDialog->Show(parentWindow);
Any pointers or hacks would be appreciated! Thanks!
To quote Michael from this other question:
[To head off some comments, the SHBrowseForFolder API still exists, but is still not an acceptable solution for our UI deciders.]
The same applies here...
I think you want to use CLSID_FileSaveDialog instead of CLSID_FileOpenDialog. And possibly make use of IFileSaveDialog in addition to the base class IFileDialog.
As you're selecting a folder, you could use the folder picker dialog.
This, with the right flags, has a "create" button at the bottom and a text entry allowing you to specifiy a non existant path.

Best way to Enable/Disable CMenu items in real time

I'm working on a project using Visual C++ 6.0, and I need to be able to enable or disable certain menu items depending on the permissions assigned to the currently logged in user. This is the code I'm using:
// If the currently logged in user doesn't have permission to edit invoices
if (!((CMyApp *)AfxGetApp())->UserHasPermission(PERMISSION_EditInvoice))
{
// Disable the Edit Menu
pMain->EnableMenuItem(1, MF_BYPOSITION | MF_DISABLED | MF_GRAYED);
}
else
{
// Enable the Edit Menu
pMain->EnableMenuItem(1, MF_BYPOSITION | MF_ENABLED);
}
It does exactly what I want it to do, however I'm trying to find the best place to put it. If I put it in OnInitialUpdate(), I get the results I want, but only for the first invoice opened. If you open a second invoice without closing and re-opening the dialog, the code is not executed again. OnUpdate() isn't called when opening a different invoice, and the only other place I've found that works is OnDraw(), the problem with OnDraw() is that the menu item doesn't visually change state from Grayed out to Enabled or vice versa until you try to click it.
I think you must include this code in a procedure
void check_user_permission();
than you must call it when this events occur:
- OnInitialUpdate()
- new user login (if your software permits user login/logout during the same session)
- new invoice opened
Can it help?
I ended up deciding to disable the Edit Invoice menu item, instead of the Edit menu itself. This proved much easier and cleaner, as it determines permission and enables or disables item every time the main 'Edit menu is opened.
void CViewInvoiceView::OnUpdateEditEditinvoice(CCmdUI* pCmdUI)
{
// If the currently logged in user doesn't have permission to edit invoices
if (!((CJ3App *)AfxGetApp())->UserHasPermission(PERMISSION_EditInvoice))
{
// Disable the Edit Menu
pCmdUI->Enable(false);
}
else
{
// Enable the edit menu
pCmdUI->Enable();
}
}