1
0

refactor: migrate windows specific content.

- move com, dialog and winfct function into new place.
- add testbench for com and winfct.
- dialog now still not working.
This commit is contained in:
2025-08-13 15:29:47 +08:00
parent ff8c7d04cc
commit bdeaea294f
14 changed files with 1138 additions and 124 deletions

View File

@ -1,48 +0,0 @@
#include "COMHelper.hpp"
#if defined(YYCC_OS_WINDOWS)
namespace YYCC::COMHelper {
/**
* @brief The guard for initialize COM environment.
* @details This class will try initializing COM environment by calling CoInitialize when constructing,
* and it also will try uninitializing COM environment when destructing.
* If initialization failed, uninitialization will not be executed.
*/
class ComGuard {
public:
ComGuard() : m_HasInit(false) {
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr)) m_HasInit = true;
}
~ComGuard() {
if (m_HasInit) {
CoUninitialize();
}
}
bool IsInitialized() const {
return m_HasInit;
}
protected:
bool m_HasInit;
};
/**
* @brief The instance of COM environment guard.
* @details Dialog related function need COM environment,
* so we need initializing COM environment when loading this module,
* and uninitializing COM environment when we no longer use this module.
* So we use a static instance in here.
* And make it be const so no one can change it.
*/
static const ComGuard c_ComGuard {};
bool IsInitialized() {
return c_ComGuard.IsInitialized();
}
}
#endif

View File

@ -1,71 +0,0 @@
#pragma once
#include "YYCCInternal.hpp"
#if defined(YYCC_OS_WINDOWS)
#include <memory>
#include "WinImportPrefix.hpp"
#include <Windows.h>
#include <shlobj_core.h>
#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 {
/// @brief C++ standard deleter for every COM interfaces inheriting IUnknown.
class ComPtrDeleter {
public:
ComPtrDeleter() {}
void operator() (IUnknown* com_ptr) {
if (com_ptr != nullptr) {
com_ptr->Release();
}
}
};
/// @brief Smart unique pointer of \c IFileDialog
using SmartIFileDialog = std::unique_ptr<IFileDialog, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IFileOpenDialog
using SmartIFileOpenDialog = std::unique_ptr<IFileOpenDialog, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellItem
using SmartIShellItem = std::unique_ptr<IShellItem, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellItemArray
using SmartIShellItemArray = std::unique_ptr<IShellItemArray, ComPtrDeleter>;
/// @brief Smart unique pointer of \c IShellFolder
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()
class CoTaskMemDeleter {
public:
CoTaskMemDeleter() {}
void operator() (void* com_ptr) {
if (com_ptr != nullptr) {
CoTaskMemFree(com_ptr);
}
}
};
/// @brief Smart unique pointer of COM created \c WCHAR sequence.
using SmartLPWSTR = std::unique_ptr<std::remove_pointer_t<LPWSTR>, CoTaskMemDeleter>;
/**
* @brief Check whether COM environment has been initialized.
* @return True if it is, otherwise false.
* @remarks
* This function will call corresponding function of COM Guard.
* Do not remove this function and you must preserve at least one reference to this function in final program.
* Some compiler will try to drop COM Guard in final program if no reference to it and it will cause the initialization of COM environment failed.
* This is the reason why I order you do the things said above.
*/
bool IsInitialized();
}
#endif