关于IFileSaveDialog与IFileOpenDialog的两个技术问题求助
Let’s break down your two problems with practical, actionable solutions:
1. Set "Yes" as Default for Confirm Save As Prompt
By default, the IFileSaveDialog shows a confirmation dialog when overwriting a file, with "No" as the default button. To change this, you’ll need to hook into the dialog’s message loop to tweak the confirmation prompt’s default button. Here’s how to implement it:
Step-by-Step Approach:
- Initialize your
IFileSaveDialoginstance and set basic options as usual. - Register an
IFileDialogEventscallback to detect when the main dialog is displayed. - In the
OnDialogShowevent, grab the dialog’s HWND and set aWH_CALLWNDPROCREThook to monitor child dialogs (like the overwrite confirmation prompt). - When the confirmation dialog initializes (via
WM_INITDIALOG), verify it’s the "Confirm Save As" dialog, then setIDYESas the default button.
Example Code Snippet:
// Global hook handle (remember to unhook later to avoid leaks) HHOOK g_hHook = nullptr; // Hook procedure to intercept dialog messages LRESULT CALLBACK CallWndRetProc(int nCode, WPARAM wParam, LPARAM lParam) { if (nCode == HC_ACTION) { CWPRETSTRUCT* pMsg = (CWPRETSTRUCT*)lParam; if (pMsg->message == WM_INITDIALOG) { // Check if this is the overwrite confirmation dialog wchar_t title[256]; GetWindowText(pMsg->hwnd, title, 256); if (wcscmp(title, L"Confirm Save As") == 0) { // Set "Yes" as the default button HWND hBtnYes = GetDlgItem(pMsg->hwnd, IDYES); if (hBtnYes) { SendMessage(pMsg->hwnd, DM_SETDEFID, IDYES, 0); } } } } return CallNextHookEx(g_hHook, nCode, wParam, lParam); } // IFileDialogEvents implementation for OnDialogShow HRESULT STDMETHODCALLTYPE MyFileDialogEvents::OnDialogShow(IFileDialog* pfd) { HWND hDlg; pfd->GetWindow(&hDlg); // Set hook to monitor child dialogs from the main thread g_hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, CallWndRetProc, nullptr, GetCurrentThreadId()); return S_OK; } // Unhook when the dialog closes (cleanup) HRESULT STDMETHODCALLTYPE MyFileDialogEvents::OnFileOk(IFileDialog* pfd) { if (g_hHook) { UnhookWindowsHookEx(g_hHook); g_hHook = nullptr; } return S_OK; }
Note: For localized Windows versions, replace the title check with a class name check (use GetClassName to look for the common dialog class #32770) to ensure compatibility.
2. Single Dialog for Opening Files or Folders
The standard IFileOpenDialog doesn’t support selecting both files and folders natively, but you can customize it with a radio button group to let users toggle between modes. Here’s how:
Step-by-Step Approach:
- Create an
IFileOpenDialoginstance. - Use
IFileDialogCustomizeto add a radio button group with "Files" and "Folders" options. - Set "Files" as the default selection.
- Register
IFileDialogEventsto handle radio button clicks, and dynamically update the dialog’s options to switch between file and folder picking modes.
Example Code Snippet:
// Custom control IDs #define IDC_RADIO_FILES 1001 #define IDC_RADIO_FOLDERS 1002 // IFileDialogEvents implementation for mode switching HRESULT STDMETHODCALLTYPE MyFileDialogEvents::OnButtonClicked(IFileDialog* pfd, DWORD dwIDCtl) { DWORD dwOptions; pfd->GetOptions(&dwOptions); if (dwIDCtl == IDC_RADIO_FILES) { // Switch to file mode: remove folder pick option, enforce file existence dwOptions &= ~FOS_PICKFOLDERS; dwOptions |= FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST; } else if (dwIDCtl == IDC_RADIO_FOLDERS) { // Switch to folder mode: add folder pick option, remove file requirements dwOptions |= FOS_PICKFOLDERS; dwOptions &= ~(FOS_FILEMUSTEXIST | FOS_PATHMUSTEXIST); } pfd->SetOptions(dwOptions); return S_OK; } // Setup the dual-mode dialog void SetupDualModeDialog(IFileOpenDialog* pOpenDlg) { CComPtr<IFileDialogCustomize> pCustomize; pOpenDlg->GetCustomize(&pCustomize); // Add radio button group pCustomize->AddRadioButtonList(IDC_RADIO_FILES); pCustomize->AddControlItem(IDC_RADIO_FILES, IDC_RADIO_FILES, L"Files"); pCustomize->AddControlItem(IDC_RADIO_FILES, IDC_RADIO_FOLDERS, L"Folders"); // Set default selection to Files pCustomize->SetSelectedControlItem(IDC_RADIO_FILES, IDC_RADIO_FILES); // Register event handler for mode switching CComPtr<MyFileDialogEvents> pEvents = new MyFileDialogEvents(); DWORD dwCookie; pOpenDlg->Advise(pEvents, &dwCookie); }
This setup lets users switch between selecting files and folders in the same dialog, with options updating dynamically based on their choice.
内容的提问来源于stack exchange,提问作者Max

