#include "cru/platform/win/win_application.hpp" #include "cru/platform/win/exception.hpp" #include "cru/platform/win/god_window.hpp" #include "cru/platform/win/graph_manager.hpp" #include "cru/platform/win/win_graph_factory.hpp" #include "cru/platform/win/win_native_window.hpp" #include "god_window_message.hpp" #include "timer.hpp" #include "window_manager.hpp" #include #include namespace cru::platform { UiApplication* UiApplication::GetInstance() { return win::WinApplication::GetInstance(); } } // namespace cru::platform namespace cru::platform::win { WinApplication* WinApplication::instance_ = nullptr; WinApplication* WinApplication::GetInstance() { if (instance_ == nullptr) instance_ = new WinApplication(::GetModuleHandleW(nullptr)); return instance_; } WinApplication::WinApplication(HINSTANCE h_instance) : h_instance_(h_instance) { if (instance_) throw std::runtime_error("A application instance already exists."); instance_ = this; if (!::IsWindows8OrGreater()) throw std::runtime_error("Must run on Windows 8 or later."); god_window_ = std::make_shared(this); timer_manager_ = std::make_shared(god_window_.get()); window_manager_ = std::make_shared(this); graph_manager_ = std::make_shared(); graph_factory_ = std::make_shared(graph_manager_.get()); } WinApplication::~WinApplication() { instance_ = nullptr; } int WinApplication::Run() { MSG msg; while (GetMessageW(&msg, nullptr, 0, 0)) { TranslateMessage(&msg); DispatchMessageW(&msg); } return static_cast(msg.wParam); } void WinApplication::Quit(const int quit_code) { ::PostQuitMessage(quit_code); } void WinApplication::InvokeLater(const std::function& action) { // copy the action to a safe place auto p_action_copy = new std::function(action); if (PostMessageW(GetGodWindow()->GetHandle(), invoke_later_message_id, reinterpret_cast(p_action_copy), 0) == 0) throw Win32Error(::GetLastError(), "InvokeLater failed to post message."); } unsigned long WinApplication::SetTimeout(std::chrono::milliseconds milliseconds, const std::function& action) { return static_cast(timer_manager_->CreateTimer( static_cast(milliseconds.count()), false, action)); } unsigned long WinApplication::SetInterval( std::chrono::milliseconds milliseconds, const std::function& action) { return static_cast(timer_manager_->CreateTimer( static_cast(milliseconds.count()), true, action)); } void WinApplication::CancelTimer(unsigned long id) { timer_manager_->KillTimer(static_cast(id)); } std::vector WinApplication::GetAllWindow() { const auto&& windows = window_manager_->GetAllWindows(); std::vector result; for (const auto w : windows) { result.push_back(static_cast(w)); } return result; } NativeWindow* WinApplication::CreateWindow(NativeWindow* parent) { WinNativeWindow* p = nullptr; if (parent != nullptr) { p = dynamic_cast(parent); assert(p); } return new WinNativeWindow(this, window_manager_->GetGeneralWindowClass(), WS_OVERLAPPEDWINDOW, p); } GraphFactory* WinApplication::GetGraphFactory() { return graph_factory_.get(); } } // namespace cru::platform::win