doc: update documentation in code

This commit is contained in:
yyc12345 2024-07-25 11:22:50 +08:00
parent 87fa30fe82
commit 31a7cb5675
2 changed files with 140 additions and 43 deletions

View File

@ -9,11 +9,17 @@
#include <shlobj_core.h> #include <shlobj_core.h>
#include "WinImportSuffix.hpp" #include "WinImportSuffix.hpp"
/**
* @brief Windows COM related types and checker.
* @details
* This namespace is Windows specific.
* In other platforms, this whole namespace will be unavailable.
*
* See also \ref com_helper.
*/
namespace YYCC::COMHelper { namespace YYCC::COMHelper {
/** /// @brief C++ standard deleter for every COM interfaces inheriting IUnknown.
* @brief C++ standard deleter for every COM interfaces inheriting IUnknown.
*/
class ComPtrDeleter { class ComPtrDeleter {
public: public:
ComPtrDeleter() {} ComPtrDeleter() {}
@ -24,15 +30,18 @@ namespace YYCC::COMHelper {
} }
}; };
/// @brief Smart unique pointer of \c IFileDialog
using SmartIFileDialog = std::unique_ptr<IFileDialog, ComPtrDeleter>; using SmartIFileDialog = std::unique_ptr<IFileDialog, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IFileOpenDialog
using SmartIFileOpenDialog = std::unique_ptr<IFileOpenDialog, ComPtrDeleter>; using SmartIFileOpenDialog = std::unique_ptr<IFileOpenDialog, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellItem
using SmartIShellItem = std::unique_ptr<IShellItem, ComPtrDeleter>; using SmartIShellItem = std::unique_ptr<IShellItem, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellItemArray
using SmartIShellItemArray = std::unique_ptr<IShellItemArray, ComPtrDeleter>; using SmartIShellItemArray = std::unique_ptr<IShellItemArray, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellFolder
using SmartIShellFolder = std::unique_ptr<IShellFolder, ComPtrDeleter>; using SmartIShellFolder = std::unique_ptr<IShellFolder, ComPtrDeleter>;
/** /// @brief C++ standard deleter for almost raw pointer used in COM which need to be free by CoTaskMemFree()
* @brief C++ standard deleter for almost raw pointer used in COM which need to be free by CoTaskMemFree()
*/
class CoTaskMemDeleter { class CoTaskMemDeleter {
public: public:
CoTaskMemDeleter() {} CoTaskMemDeleter() {}
@ -42,7 +51,8 @@ namespace YYCC::COMHelper {
} }
} }
}; };
/// @brief Smart unique pointer of COM created \c WCHAR sequence.
using SmartLPWSTR = std::unique_ptr<std::remove_pointer_t<LPWSTR>, CoTaskMemDeleter>; using SmartLPWSTR = std::unique_ptr<std::remove_pointer_t<LPWSTR>, CoTaskMemDeleter>;
/** /**

View File

@ -12,11 +12,19 @@
#include <shlobj_core.h> #include <shlobj_core.h>
#include "WinImportSuffix.hpp" #include "WinImportSuffix.hpp"
/**
* @brief The namespace providing Windows universal dialog features.
* @details
* This namespace only available on Windows platform.
* See also \ref dialog_helper.
*/
namespace YYCC::DialogHelper { namespace YYCC::DialogHelper {
/** /**
* @brief The class represent the file types region in file dialog * @brief The class representing the file types region in file dialog.
* @details THis class is specific for Windows use, not user oriented. * @details
* This class is served for Windows used.
* Programmer should \b not create this class manually.
*/ */
class WinFileFilters { class WinFileFilters {
friend class FileFilters; friend class FileFilters;
@ -24,9 +32,11 @@ namespace YYCC::DialogHelper {
public: public:
WinFileFilters() : m_WinFilters(), m_WinDataStruct(nullptr) {} WinFileFilters() : m_WinFilters(), m_WinDataStruct(nullptr) {}
/// @brief Get the count of available file filters
UINT GetFilterCount() const { UINT GetFilterCount() const {
return static_cast<UINT>(m_WinFilters.size()); return static_cast<UINT>(m_WinFilters.size());
} }
/// @brief Get pointer to Windows used file filters declarations
const COMDLG_FILTERSPEC* GetFilterSpecs() const { const COMDLG_FILTERSPEC* GetFilterSpecs() const {
return m_WinDataStruct.get(); return m_WinDataStruct.get();
} }
@ -39,6 +49,7 @@ namespace YYCC::DialogHelper {
std::vector<WinFilterPair> m_WinFilters; std::vector<WinFilterPair> m_WinFilters;
std::unique_ptr<COMDLG_FILTERSPEC[]> m_WinDataStruct; std::unique_ptr<COMDLG_FILTERSPEC[]> m_WinDataStruct;
/// @brief Clear all current file filters
void Clear() { void Clear() {
m_WinDataStruct.reset(); m_WinDataStruct.reset();
m_WinFilters.clear(); m_WinFilters.clear();
@ -46,9 +57,12 @@ namespace YYCC::DialogHelper {
}; };
/** /**
* @brief The class represent the file types region in file dialog. * @brief The class representing the file types region in file dialog.
* @details This class is user oriented. User can use function manipulate file types * @details
* and final generation function will produce Windows-understood data struct from this. * This class is served for programmer using.
* But you don't need create it on your own.
* You can simply fetch it by FileDialog::ConfigreFileTypes ,
* because this class is a part of FileDialog.
*/ */
class FileFilters { class FileFilters {
public: public:
@ -56,31 +70,34 @@ namespace YYCC::DialogHelper {
/** /**
* @brief Add a filter pair in file types list. * @brief Add a filter pair in file types list.
* @param filter_name[in] The friendly name of the filter. * @param[in] filter_name The friendly name of the filter.
* @param il[in] A C++ initialize list. * @param[in] il
* Every entries must be `const yycc_char8_t*` represent a single filter pattern. * A C++ initialize list containing acceptable file filter pattern.
* Every entries must be `const yycc_char8_t*` representing a single filter pattern.
* The list at least should have one valid pattern. * The list at least should have one valid pattern.
* This function will not validate these filter patterns, so please write them carefully. * This function will not validate these filter patterns, so please write them carefully.
* @return True if added success, otherwise false. * @return True if added success, otherwise false.
* @remarks This function allow you register multiple filter patterns for single friendly name. * @remarks
* For example: `Add("Microsoft Word (*.doc; *.docx)", {"*.doc", "*.docx"})` * This function allow you register multiple filter patterns for single friendly name.
* For example: <TT>Add(u8"Microsoft Word (*.doc; *.docx)", {u8"*.doc", u8"*.docx"})</TT>
*/ */
bool Add(const yycc_char8_t* filter_name, std::initializer_list<const yycc_char8_t*> il); bool Add(const yycc_char8_t* filter_name, std::initializer_list<const yycc_char8_t*> il);
/**
* @brief Clear filter pairs for following re-use.
*/
void Clear() { m_Filters.clear(); }
/** /**
* @brief Get the count of added filter pairs. * @brief Get the count of added filter pairs.
* @return The count of already added filter pairs. * @return The count of already added filter pairs.
*/ */
size_t Count() const { return m_Filters.size(); } size_t Count() const { return m_Filters.size(); }
/// @brief Clear filter pairs for following re-use.
void Clear() { m_Filters.clear(); }
/** /**
* @brief Generate Windows dialog system used data struct. * @brief Generate Windows dialog system used data struct.
* @param win_result[out] The class holding the generated filter data struct. * @param[out] win_result The class receiving the generated filter data struct.
* @return True if generation is success, otherwise false. * @return True if generation success, otherwise false.
* @remarks User should not call this function, this function is used in internal code. * @remarks
* Programmer should not call this function,
* this function is used as YYCC internal code.
*/ */
bool Generate(WinFileFilters& win_result) const; bool Generate(WinFileFilters& win_result) const;
@ -93,8 +110,10 @@ namespace YYCC::DialogHelper {
}; };
/** /**
* @brief The class represent the file dialog * @brief The class representing the file dialog.
* @details THis class is specific for Windows use, not user oriented. * @details
* This class is served for Windows used.
* Programmer should \b not create this class manually.
*/ */
class WinFileDialog { class WinFileDialog {
friend class FileDialog; friend class FileDialog;
@ -105,18 +124,28 @@ namespace YYCC::DialogHelper {
m_HasTitle(false), m_HasInitFileName(false), m_WinTitle(), m_WinInitFileName(), m_HasTitle(false), m_HasInitFileName(false), m_WinTitle(), m_WinInitFileName(),
m_WinInitDirectory(nullptr) {} m_WinInitDirectory(nullptr) {}
/// @brief Get whether this dialog has owner.
bool HasOwner() const { return m_WinOwner != NULL; } bool HasOwner() const { return m_WinOwner != NULL; }
/// @brief Get the \c HWND of dialog owner.
HWND GetOwner() const { return m_WinOwner; } HWND GetOwner() const { return m_WinOwner; }
/// @brief Get the struct holding Windows used file filters data.
const WinFileFilters& GetFileTypes() const { return m_WinFileTypes; } const WinFileFilters& GetFileTypes() const { return m_WinFileTypes; }
/// @brief Get the index of default selected file filter.
UINT GetDefaultFileTypeIndex() const { return m_WinDefaultFileTypeIndex; } UINT GetDefaultFileTypeIndex() const { return m_WinDefaultFileTypeIndex; }
/// @brief Get whether dialog has custom title.
bool HasTitle() const { return m_HasTitle; } bool HasTitle() const { return m_HasTitle; }
/// @brief Get custom title of dialog.
const wchar_t* GetTitle() const { return m_WinTitle.c_str(); } const wchar_t* GetTitle() const { return m_WinTitle.c_str(); }
/// @brief Get whether dialog has custom initial file name.
bool HasInitFileName() const { return m_HasInitFileName; } bool HasInitFileName() const { return m_HasInitFileName; }
/// @brief Get custom initial file name of dialog
const wchar_t* GetInitFileName() const { return m_WinInitFileName.c_str(); } const wchar_t* GetInitFileName() const { return m_WinInitFileName.c_str(); }
/// @brief Get whether dialog has custom initial directory.
bool HasInitDirectory() const { return m_WinInitDirectory.get() != nullptr; } bool HasInitDirectory() const { return m_WinInitDirectory.get() != nullptr; }
/// @brief Get custom initial directory of dialog.
IShellItem* GetInitDirectory() const { return m_WinInitDirectory.get(); } IShellItem* GetInitDirectory() const { return m_WinInitDirectory.get(); }
protected: protected:
@ -124,15 +153,17 @@ namespace YYCC::DialogHelper {
WinFileFilters m_WinFileTypes; WinFileFilters m_WinFileTypes;
/** /**
* @brief The default selected file type in dialog * @brief The default selected file type in dialog
* @remarks This is 1-based index according to Windows specification. * @remarks
* In other words, you should plus 1 for this index when generating this struct from * This is 1-based index according to Windows specification.
* user oriented file dialog parameters. * In other words, when generating this struct from FileDialog to this struct this field should plus 1.
* Because the same field located in FileDialog is 0-based index.
*/ */
UINT m_WinDefaultFileTypeIndex; UINT m_WinDefaultFileTypeIndex;
bool m_HasTitle, m_HasInitFileName; bool m_HasTitle, m_HasInitFileName;
std::wstring m_WinTitle, m_WinInitFileName; std::wstring m_WinTitle, m_WinInitFileName;
COMHelper::SmartIShellItem m_WinInitDirectory; COMHelper::SmartIShellItem m_WinInitDirectory;
/// @brief Clear all data and reset them to default value.
void Clear() { void Clear() {
m_WinOwner = nullptr; m_WinOwner = nullptr;
m_WinFileTypes.Clear(); m_WinFileTypes.Clear();
@ -146,8 +177,9 @@ namespace YYCC::DialogHelper {
/** /**
* @brief The class represent the file dialog. * @brief The class represent the file dialog.
* @details This class is user oriented. User can use function manipulate file dialog properties * @details
* and final generation function will produce Windows-understood data struct from this. * This class is served for programming using to describe every aspectes of the dialog.
* For how to use this struct, see \ref dialog_helper.
*/ */
class FileDialog { class FileDialog {
public: public:
@ -158,27 +190,55 @@ namespace YYCC::DialogHelper {
m_Title(), m_InitFileName(), m_InitDirectory(), m_Title(), m_InitFileName(), m_InitDirectory(),
m_HasTitle(false), m_HasInitFileName(false), m_HasInitDirectory(false) {} m_HasTitle(false), m_HasInitFileName(false), m_HasInitDirectory(false) {}
/**
* @brief Set the owner of dialog.
* @param[in] owner The \c HWND pointing to the owner of dialog, or NULL to remove owner.
*/
void SetOwner(HWND owner) { m_Owner = owner; } void SetOwner(HWND owner) { m_Owner = owner; }
/**
* @brief Set custom title of dialog
* @param[in] title The string pointer to custom title, or nullptr to remove it.
*/
void SetTitle(const yycc_char8_t* title) { void SetTitle(const yycc_char8_t* title) {
if (m_HasTitle = title != nullptr) if (m_HasTitle = title != nullptr)
m_Title = title; m_Title = title;
} }
/**
* @brief Fetch the struct describing file filters for future configuration.
* @return The reference to the struct describing file filters.
*/
FileFilters& ConfigreFileTypes() { FileFilters& ConfigreFileTypes() {
return m_FileTypes; return m_FileTypes;
} }
/**
* @brief Set the index of default selected file filter.
* @param[in] idx
* The index to default one.
* This must be a valid index in file filters.
*/
void SetDefaultFileTypeIndex(size_t idx) { m_DefaultFileTypeIndex = idx; } void SetDefaultFileTypeIndex(size_t idx) { m_DefaultFileTypeIndex = idx; }
/**
* @brief Set the initial file name of dialog
* @details If set, the file name will always be same one when opening dialog.
* @param[in] init_filename String pointer to initial file name, or nullptr to remove it.
*/
void SetInitFileName(const yycc_char8_t* init_filename) { void SetInitFileName(const yycc_char8_t* init_filename) {
if (m_HasInitFileName = init_filename != nullptr) if (m_HasInitFileName = init_filename != nullptr)
m_InitFileName = init_filename; m_InitFileName = init_filename;
} }
/**
* @brief Set the initial directory of dialog
* @details If set, the opended directory will always be the same one when opening dialog
* @param[in] init_dir
* String pointer to initial directory.
* Invalid path or nullptr will remove this feature.
*/
void SetInitDirectory(const yycc_char8_t* init_dir) { void SetInitDirectory(const yycc_char8_t* init_dir) {
if (m_HasInitDirectory = init_dir != nullptr) if (m_HasInitDirectory = init_dir != nullptr)
m_InitDirectory = init_dir; m_InitDirectory = init_dir;
} }
/** /// @brief Clear file dialog parameters for following re-use.
* @brief Clear file dialog parameters for following re-use.
*/
void Clear() { void Clear() {
m_Owner = nullptr; m_Owner = nullptr;
m_HasTitle = m_HasInitFileName = m_HasInitDirectory = false; m_HasTitle = m_HasInitFileName = m_HasInitDirectory = false;
@ -191,9 +251,11 @@ namespace YYCC::DialogHelper {
/** /**
* @brief Generate Windows dialog system used data struct. * @brief Generate Windows dialog system used data struct.
* @param win_result[out] The class holding the generated filter data struct. * @param[out] win_result The class receiving the generated filter data struct.
* @return True if generation is success, otherwise false. * @return True if generation is success, otherwise false.
* @remarks User should not call this function, this function is used in internal code. * @remarks
* Programmer should not call this function.
* This function is used as YYCC internal code.
*/ */
bool Generate(WinFileDialog& win_result) const; bool Generate(WinFileDialog& win_result) const;
@ -204,16 +266,41 @@ namespace YYCC::DialogHelper {
FileFilters m_FileTypes; FileFilters m_FileTypes;
/** /**
* @brief The default selected file type in dialog * @brief The default selected file type in dialog
* @remarks Although Windows notice that this is a 1-based index, * @remarks
* but for universal experience, we order this is 0-based index. * The index Windows used is 1-based index.
* But for universal experience, we order this is 0-based index.
* And do convertion when generating Windows used struct.
*/ */
size_t m_DefaultFileTypeIndex; size_t m_DefaultFileTypeIndex;
}; };
/**
* @brief Open the dialog which order user select single file to open.
* @param[in] params The configuration of dialog.
* @param[out] ret Full path to user selected file.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool OpenFileDialog(const FileDialog& params, yycc_u8string& ret); bool OpenFileDialog(const FileDialog& params, yycc_u8string& ret);
/**
* @brief Open the dialog which order user select multiple file to open.
* @param[in] params The configuration of dialog.
* @param[out] ret The list of full path of user selected files.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool OpenMultipleFileDialog(const FileDialog& params, std::vector<yycc_u8string>& ret); bool OpenMultipleFileDialog(const FileDialog& params, std::vector<yycc_u8string>& ret);
/**
* @brief Open the dialog which order user select single file to save.
* @param[in] params The configuration of dialog.
* @param[out] ret Full path to user selected file.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool SaveFileDialog(const FileDialog& params, yycc_u8string& ret); bool SaveFileDialog(const FileDialog& params, yycc_u8string& ret);
/**
* @brief Open the dialog which order user select single directory to open.
* @param[in] params The configuration of dialog.
* @param[out] ret Full path to user selected directory.
* @return False if user calcel the operation or something went wrong, otherwise true.
*/
bool OpenFolderDialog(const FileDialog& params, yycc_u8string& ret); bool OpenFolderDialog(const FileDialog& params, yycc_u8string& ret);
} }