feat: add some dialog code which can not work now.
- add common file dialog showcase code but all of them are not work now.
This commit is contained in:
@ -69,9 +69,219 @@ namespace YYCC::DialogHelper {
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region FileDialog
|
||||
#pragma region File Dialog
|
||||
|
||||
bool FileDialog::Generate(WinFileDialog& win_result) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Windows Dialog Code
|
||||
|
||||
enum class CommonFileDialogType {
|
||||
OpenFile,
|
||||
OpenMultipleFiles,
|
||||
SaveFile,
|
||||
OpenFolder
|
||||
};
|
||||
|
||||
using SmartFileDialogPtr = std::unique_ptr<IFileDialog, std::function<void(IFileDialog*)>>;
|
||||
|
||||
template<CommonFileDialogType EDialogType>
|
||||
bool CommonFileDialog(const FileDialog& params, std::vector<std::string>& ret) {
|
||||
// Reference: https://learn.microsoft.com/en-us/windows/win32/shell/common-file-dialog
|
||||
// prepare result variable
|
||||
HRESULT hr;
|
||||
|
||||
// create file dialog instance
|
||||
// fetch dialog CLSID first
|
||||
CLSID dialog_clsid;
|
||||
switch (EDialogType) {
|
||||
case CommonFileDialogType::OpenFile:
|
||||
case CommonFileDialogType::OpenMultipleFiles:
|
||||
case CommonFileDialogType::OpenFolder:
|
||||
dialog_clsid = CLSID_FileOpenDialog;
|
||||
break;
|
||||
case CommonFileDialogType::SaveFile:
|
||||
dialog_clsid = CLSID_FileSaveDialog;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// create raw dialog pointer
|
||||
IFileDialog* _pfd = nullptr;
|
||||
hr = CoCreateInstance(
|
||||
dialog_clsid,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&_pfd)
|
||||
);
|
||||
if (!SUCCEEDED(hr)) return false;
|
||||
// create memory-safe dialog pointer
|
||||
SmartFileDialogPtr pfd(
|
||||
_pfd,
|
||||
[](IFileDialog* instance) -> void {
|
||||
if (instance != nullptr)
|
||||
instance->Release();
|
||||
}
|
||||
);
|
||||
|
||||
// set options for dialog
|
||||
// before setting, always get the options first in order.
|
||||
// not to override existing options.
|
||||
DWORD dwFlags;
|
||||
hr = pfd->GetOptions(&dwFlags);
|
||||
if (!SUCCEEDED(hr)) return false;
|
||||
// modify options
|
||||
switch (EDialogType) {
|
||||
// We want user only can pick file system files: FOS_FORCEFILESYSTEM.
|
||||
// Open dialog default: FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR
|
||||
// Save dialog default: FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR
|
||||
// Pick folder: FOS_PICKFOLDERS
|
||||
case CommonFileDialogType::OpenFile:
|
||||
dwFlags |= FOS_FORCEFILESYSTEM;
|
||||
dwFlags |= FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
|
||||
break;
|
||||
case CommonFileDialogType::OpenMultipleFiles:
|
||||
dwFlags |= FOS_FORCEFILESYSTEM;
|
||||
dwFlags |= FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
|
||||
dwFlags |= FOS_ALLOWMULTISELECT;
|
||||
break;
|
||||
case CommonFileDialogType::SaveFile:
|
||||
dwFlags |= FOS_FORCEFILESYSTEM;
|
||||
dwFlags |= FOS_OVERWRITEPROMPT | FOS_NOREADONLYRETURN | FOS_PATHMUSTEXIST | FOS_NOCHANGEDIR;
|
||||
break;
|
||||
case CommonFileDialogType::OpenFolder:
|
||||
dwFlags |= FOS_FORCEFILESYSTEM;
|
||||
dwFlags |= FOS_PATHMUSTEXIST | FOS_FILEMUSTEXIST | FOS_NOCHANGEDIR;
|
||||
dwFlags |= FOS_PICKFOLDERS;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
// set folder dialog options
|
||||
hr = pfd->SetOptions(dwFlags);
|
||||
if (!SUCCEEDED(hr)) return false;
|
||||
|
||||
// set title
|
||||
std::wstring wtitle, winit_filename, winit_directory;
|
||||
if (params.GetTitle() != nullptr) {
|
||||
EncodingHelper::UTF8ToWchar(params.GetTitle(), wtitle);
|
||||
}
|
||||
|
||||
// set file types and default file index when we picking file
|
||||
WinFileFilters win_file_filters;
|
||||
if constexpr (EDialogType != CommonFileDialogType::OpenFolder) {
|
||||
// generate data from user specified file filters
|
||||
const auto& file_filters = params.GetFileTypes();
|
||||
if (!file_filters.Generate(win_file_filters))
|
||||
return false;
|
||||
|
||||
// set file types list
|
||||
hr = pfd->SetFileTypes(win_file_filters.GetFilterCount(), win_file_filters.GetFilterSpecs());
|
||||
if (!SUCCEEDED(hr)) return false;
|
||||
|
||||
// set default file type index
|
||||
// Windows order this is 1-based index.
|
||||
// We plus 1 for it because we used is 0-based index.
|
||||
hr = pfd->SetFileTypeIndex(params.GetDefaultFileTypeIndex() + 1);
|
||||
if (!SUCCEEDED(hr)) return false;
|
||||
}
|
||||
|
||||
// CoCreate the File Open Dialog object.
|
||||
IFileDialog* pfd = NULL;
|
||||
HRESULT hr = CoCreateInstance(
|
||||
CLSID_FileOpenDialog,
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(&pfd)
|
||||
);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Set the options on the dialog.
|
||||
DWORD dwFlags;
|
||||
|
||||
// Before setting, always get the options first in order
|
||||
// not to override existing options.
|
||||
hr = pfd->GetOptions(&dwFlags);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// In this case, get shell items only for file system items.
|
||||
hr = pfd->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Set the file types to display only.
|
||||
// Notice that this is a 1-based array.
|
||||
hr = pfd->SetFileTypes(ARRAYSIZE(c_rgSaveTypes), c_rgSaveTypes);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Set the selected file type index to Word Docs for this example.
|
||||
hr = pfd->SetFileTypeIndex(INDEX_WORDDOC);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Set the default extension to be ".doc" file.
|
||||
hr = pfd->SetDefaultExtension(L"doc;docx");
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Show the dialog
|
||||
hr = pfd->Show(NULL);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// Obtain the result once the user clicks
|
||||
// the 'Open' button.
|
||||
// The result is an IShellItem object.
|
||||
IShellItem* psiResult;
|
||||
hr = pfd->GetResult(&psiResult);
|
||||
if (SUCCEEDED(hr)) {
|
||||
// We are just going to print out the
|
||||
// name of the file for sample sake.
|
||||
PWSTR pszFilePath = NULL;
|
||||
hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH,
|
||||
&pszFilePath);
|
||||
if (SUCCEEDED(hr)) {
|
||||
TaskDialog(NULL,
|
||||
NULL,
|
||||
L"CommonFileDialogApp",
|
||||
pszFilePath,
|
||||
NULL,
|
||||
TDCBF_OK_BUTTON,
|
||||
TD_INFORMATION_ICON,
|
||||
NULL);
|
||||
CoTaskMemFree(pszFilePath);
|
||||
}
|
||||
psiResult->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pfd->Release();
|
||||
}
|
||||
return SUCCEEDED(hr);
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Wrapper Functions
|
||||
|
||||
bool OpenFileDialog(const FileDialog& params, std::string& ret) {
|
||||
std::vector<std::string> cache;
|
||||
bool isok = CommonFileDialog<CommonFileDialogType::OpenFile>(params, cache);
|
||||
if (isok) ret = cache.front();
|
||||
return isok;
|
||||
}
|
||||
bool OpenMultipleFileDialog(const FileDialog& params, std::vector<std::string>& ret) {
|
||||
return CommonFileDialog<CommonFileDialogType::OpenMultipleFiles>(params, ret);
|
||||
}
|
||||
bool SaveFileDialog(const FileDialog& params, std::string& ret) {
|
||||
std::vector<std::string> cache;
|
||||
bool isok = CommonFileDialog<CommonFileDialogType::SaveFile>(params, cache);
|
||||
if (isok) ret = cache.front();
|
||||
return isok;
|
||||
}
|
||||
|
||||
bool OpenFolderDialog(const FileDialog& params, std::string& ret) {
|
||||
std::vector<std::string> cache;
|
||||
bool isok = CommonFileDialog<CommonFileDialogType::OpenFolder>(params, cache);
|
||||
if (isok) ret = cache.front();
|
||||
return isok;
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
Reference in New Issue
Block a user