diff --git a/.clang-tidy b/.clang-tidy index bb71363..da28d6f 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -6,6 +6,7 @@ Checks: > -boost-*, -bugprone-easily-swappable-parameters, -bugprone-forward-declaration-namespace, + -bugprone-reserved-identifier, -bugprone-unhandled-exception-at-new, -cert-err58-cpp, -cppcoreguidelines-avoid-*, @@ -13,6 +14,7 @@ Checks: > -cppcoreguidelines-macro-usage, -cppcoreguidelines-missing-std-forward, -cppcoreguidelines-owning-memory, + -cppcoreguidelines-pro-bounds-constant-array-index, -cppcoreguidelines-pro-bounds-pointer-arithmetic, -cppcoreguidelines-pro-type-member-init, -cppcoreguidelines-pro-type-reinterpret-cast, @@ -27,6 +29,7 @@ Checks: > -google-explicit-constructor, -google-runtime-int, -hicpp-avoid-c-arrays, + -hicpp-explicit-conversions, -hicpp-member-init, -hicpp-signed-bitwise, -hicpp-use-auto, @@ -38,6 +41,7 @@ Checks: > -misc-unused-parameters, -misc-use-internal-linkage, -modernize-avoid-c-arrays, + -modernize-return-braced-init-list, -modernize-use-auto, -modernize-use-designated-initializers, -modernize-use-ranges, diff --git a/File.h b/File.h index ad9de35..b18bf26 100644 --- a/File.h +++ b/File.h @@ -4,7 +4,7 @@ #pragma once -class File { +class File final { public: String path{}; std::wfstream file{}; @@ -13,7 +13,7 @@ public: File(const String& path) : path(path) {} File(const File&) = delete; File(File&&) = delete; - ~File() { if (file.is_open()) file.close(); } + ~File() = default; File& operator=(const File&) = delete; File& operator=(File&&) = delete; @@ -71,7 +71,7 @@ public: return *this; } - File& operator<<(decltype(std::endl>) value) { + File& operator<<(decltype(std::endl>)& value) { if (file.is_open()) file << value; return *this; } @@ -153,5 +153,3 @@ public: return loadUntil(line); } }; - -inline File& [[carlbeks::releasedat]] MainLogFile = (new File(L"log.txt"))->binary().inputs().outputs().truncate().open().operator<<(L"initialize MainLogFile\n"); diff --git a/Game.h b/Game.h index 0e8d4af..4397d52 100644 --- a/Game.h +++ b/Game.h @@ -84,10 +84,12 @@ public: floatWindow->onResize(); } - void passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) const noexcept { - caption->passEvent(action, value, x, y); + int passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) const noexcept { + int ret = 0; + ret = caption->passEvent(action, value, x, y); if (Window* const window = getWindow()) window->passEvent(action, value, x, y); floatWindow->passEvent(action, value, x, y); + return ret; } }; diff --git a/IText.cpp b/IText.cpp index 62efb93..1b0afb9 100644 --- a/IText.cpp +++ b/IText.cpp @@ -127,5 +127,13 @@ void TranslatableText::refreshText() const noexcept { } } +void languageMakeChinese(Language& lang) { + Logger.debug(L"languageMakeChinese called"); + Map& map = lang.translateTable; + map.emplace(String(L"hbp.title"), TranslatedText(L"高血压")); + map.emplace(String(L"hbp.confirm.confirm"), TranslatedText(L"确认")); + map.emplace(String(L"hbp.confirm.cancel"), TranslatedText(L"取消")); +} + inline Translator translator = Translator(); inline FontManager fontManager = FontManager(); diff --git a/IText.h b/IText.h index 2c153fb..f10ddef 100644 --- a/IText.h +++ b/IText.h @@ -8,6 +8,7 @@ #include "def.h" #include "Chars.h" +#include "exception.h" #include "InteractManager.h" class LiteralText; @@ -356,6 +357,7 @@ private: inline RenderableString operator""_renderable(const wchar* const text, const QWORD) noexcept { return RenderableString(text); } + class Font { public: Function resize; @@ -508,31 +510,77 @@ public: void refreshText() const noexcept; }; +using LangID = unsigned int; + struct Language { Map translateTable; - int id = 1; + LangID id = 1; + using IterText = Map::const_iterator; + + Language(const LangID id) : id(id) {} + Language(const Language&) = delete; + Language(Language&&) = default; + Language& operator=(const Language&) = delete; + Language& operator=(Language&&) = default; + + String toString() { + std::wstringstream stream{}; + stream.imbue(std::locale("zh-CN.UTF-8")); + stream << L"Language ID: " << id << std::endl; + for (const auto& [key, value] : translateTable) stream << L" " << key << L": (" << value.getText().length() << L") " << value.getText() << std::endl; + return stream.str(); + } }; +void languageMakeChinese(Language&); + class Translator { - Map langMap{}; - List langList{}; + Map langMap{}; + List langList{}; TranslatedText nullText{ L"\\#FF""EE0000" }; String lang = L"zh-cn"; + LangID idLangMax = 0; int langConfig = 1; - int idLangMax = 1; - using IterID = Map::const_iterator; + using IterLangName = Map::const_iterator; using IterLang = List::const_iterator; public: - Translator() { langMap.insert(std::make_pair(String(L"zh-cn"), 1)); } - void addLang(const String& lang) noexcept { langMap.insert(std::make_pair(lang, ++idLangMax)); } - void addLang(String&& lang) noexcept { langMap.insert(std::make_pair(lang, ++idLangMax)); } + void initialize() { + Language& chinese = addLang(L"zh-cn"); + languageMakeChinese(chinese); + useLanguage(L"zh-cn"); + } + + Translator() = default; + Language& addLang(const String& lang) noexcept { return langMap.insert(std::make_pair(lang, Language(++idLangMax))).first->second; } + Language& addLang(String&& lang) noexcept { return langMap.insert(std::make_pair(lang, Language(++idLangMax))).first->second; } + Language& getLang(const String& lang) noexcept { return langMap.at(lang); } + + const Language* useLanguage(const String& lang) noexcept { + const Map::iterator language = langMap.find(lang); + if (language == langMap.cend()) return nullptr; + for (const Language* i : langList) if (i->id == language->second.id) return i; + langList.push_front(&language->second); + return &language->second; + } + + void unuseLanguage(const String& lang) noexcept { + const Map::iterator language = langMap.find(lang); + if (language == langMap.cend()) return; + for (const Language* i : langList) + if (i->id == language->second.id) { + langMap.erase(lang); + break; + } + } + void loadLang(); [[nodiscard]] const TranslatedText* getText(const String& id) const noexcept { - for (const auto& [translateTable, _] : langList) { - IterID iterator = translateTable.find(id); - if (iterator != translateTable.cend()) return &iterator->second; + Logger.debug(L"getText called"); + for (const Language* language : langList) { + const Language::IterText iterator = language->translateTable.find(id); + if (iterator != language->translateTable.cend()) return &iterator->second; } return &nullText; } diff --git a/InteractManager.cpp b/InteractManager.cpp index 1604820..178ce1a 100644 --- a/InteractManager.cpp +++ b/InteractManager.cpp @@ -279,5 +279,5 @@ bool InteractManager::isInSizeBox() const noexcept { return isInWindow() && !isI bool InteractManager::isInClientCaption() const noexcept { return mouseX > interactSettings.actual.marginWidth && mouseX < renderer.getSyncWidth() - interactSettings.actual.marginWidth && mouseY > interactSettings.actual.marginWidth && mouseY < renderer.getSyncHeight() - interactSettings.actual.marginWidth; } -KeyStatus& InteractManager::getKey(const KeyBinding& binding) noexcept { return keyStatus[binding.keyCode]; } +KeyStatus& InteractManager::getKey(const KeyBindingLegacy& binding) noexcept { return keyStatus[binding.keyCode]; } MouseButtonCode InteractManager::getMouseButtonCode() const noexcept { return (keyStatus[VK_LBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_L_DOWN) : 0) | (keyStatus[VK_RBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_R_DOWN) : 0) | (keyStatus[VK_MBUTTON].isPressed() ? static_cast(MouseButtonCodeEnum::MBC_M_DOWN) : 0); } diff --git a/InteractManager.h b/InteractManager.h index 102ff47..e17aed9 100644 --- a/InteractManager.h +++ b/InteractManager.h @@ -5,7 +5,6 @@ #pragma once #include "def.h" -#include "exception.h" #include "hbp.h" struct KeyStatus { @@ -43,7 +42,7 @@ struct MouseStatus { [[nodiscard]] String toString() const noexcept { return L"MouseStatus: { name = \"" + name + L"\"; pressTimes = " + std::to_wstring(pressTimes) + L"; pressed = " + (pressed ? L"true, longHold = " : L"false, longHold = ") + (longHold ? L"true; }" : L"false; }"); } }; -struct KeyBinding; +struct KeyBindingLegacy; class InteractManager { TRACKMOUSEEVENT trackMouseEvent{ @@ -52,11 +51,11 @@ class InteractManager { .hwndTrack = nullptr, .dwHoverTime = HOVER_DEFAULT }; - KeyStatus keyStatus[256]; + KeyStatus keyStatus[256] {}; int mouseX = 0, mouseY = 0; int mouseWheel = 0; int rebindResult = 0; - char outsideWindow = 0;// 鼠标是否在窗口外部。1位:在客户区;2位:在标题栏 + char outsideWindow = 0; // 鼠标是否在窗口外部。1位:在客户区;2位:在标题栏 bool rebinding = false; bool hovering = false; @@ -99,7 +98,7 @@ public: [[nodiscard]] bool isInSizeBox() const noexcept; [[nodiscard]] bool isInClientCaption() const noexcept; [[nodiscard]] KeyStatus& getKey(const int keyCode) noexcept { return keyStatus[keyCode]; } - [[nodiscard]] KeyStatus& getKey(const KeyBinding& binding) noexcept; + [[nodiscard]] KeyStatus& getKey(const KeyBindingLegacy& binding) noexcept; [[nodiscard]] unsigned int /*MouseButtonCode*/ getMouseButtonCode() const noexcept; int dealMouseWheel() noexcept { @@ -111,7 +110,7 @@ public: inline InteractManager interactManager = InteractManager(); -struct KeyBinding { +struct KeyBindingLegacy { String id; int keyCode; [[nodiscard]] bool isPressed() const noexcept { return interactManager.getKey(keyCode).isPressed(); } @@ -119,6 +118,88 @@ struct KeyBinding { void deals() const noexcept { interactManager.getKey(keyCode).deals(); } }; +class KeyBinding; +struct LessKeyBinding; +class KeyRegion; +struct LessKeyRegion; +class KeyBindingManager; + +class KeyBinding { + friend struct LessKeyBinding; + friend class KeyBindingManager; + String id; + unsigned int pressTimes = 0; + unsigned char keyCode[8]{}; + +public: + [[nodiscard]] bool isPressed() const noexcept { + for (const int i : keyCode) if (!interactManager.getKey(i).isPressed()) return false; + return true; + } + + [[nodiscard]] unsigned int wasPressed() const noexcept { return pressTimes; } + + [[nodiscard]] unsigned int boundKeyCount() const noexcept { + unsigned int ret = 0; + while (keyCode[ret] && ret < 8) ++ret; + return ret; + } +}; + +struct LessKeyBinding { // std::less + [[nodiscard]] bool operator()(const KeyBinding& lhs, const KeyBinding& rhs) const noexcept { + const unsigned int lc = lhs.boundKeyCount(), rc = rhs.boundKeyCount(); + if (lc < rc) return false; + if (lc > rc) return true; + if (lhs.keyCode[0] < rhs.keyCode[0]) return true; + if (lhs.keyCode[0] > rhs.keyCode[0]) return false; + if (lhs.keyCode[1] == 0) return false; + if (lhs.keyCode[1] < rhs.keyCode[1]) return true; + if (lhs.keyCode[1] > rhs.keyCode[1]) return false; + if (lhs.keyCode[2] == 0) return false; + if (lhs.keyCode[2] < rhs.keyCode[2]) return true; + if (lhs.keyCode[2] > rhs.keyCode[2]) return false; + if (lhs.keyCode[3] == 0) return false; + if (lhs.keyCode[3] < rhs.keyCode[3]) return true; + if (lhs.keyCode[3] > rhs.keyCode[3]) return false; + if (lhs.keyCode[4] == 0) return false; + if (lhs.keyCode[4] < rhs.keyCode[4]) return true; + if (lhs.keyCode[4] > rhs.keyCode[4]) return false; + if (lhs.keyCode[5] == 0) return false; + if (lhs.keyCode[5] < rhs.keyCode[5]) return true; + if (lhs.keyCode[5] > rhs.keyCode[5]) return false; + if (lhs.keyCode[6] == 0) return false; + if (lhs.keyCode[6] < rhs.keyCode[6]) return true; + if (lhs.keyCode[6] > rhs.keyCode[6]) return false; + if (lhs.keyCode[7] == 0) return false; + if (lhs.keyCode[7] < rhs.keyCode[7]) return true; + return false; + } +}; + +class KeyRegion { + friend struct LessKeyRegion; + friend class KeyBindingManager; + const unsigned int idRegion; + mutable Set keyBindings; + + KeyRegion(const unsigned int id) : idRegion(id) {} + void addKeyBinding(const KeyBinding& binding) const noexcept { keyBindings.insert(binding); } + void addKeyBinding(KeyBinding&& binding) const noexcept { keyBindings.insert(std::move(binding)); } +}; + +struct LessKeyRegion { + [[nodiscard]] bool operator()(const KeyRegion& lhs, const KeyRegion& rhs) const noexcept { return lhs.idRegion < rhs.idRegion; } +}; + +class KeyBindingManager { + Set keyRegions; + unsigned int keyRegionCount = 0; + +public: + const KeyRegion& registerRegion() noexcept { return keyRegions.emplace(KeyRegion(++keyRegionCount)).first.operator*(); } +}; + class InteractSettings { struct Options { int captionHeight = 120; diff --git a/Renderer.h b/Renderer.h index 1b75f4a..d0b1cb6 100644 --- a/Renderer.h +++ b/Renderer.h @@ -89,7 +89,6 @@ public: Logger.info(L"Successfully reload bitmap " + ptrtow(reinterpret_cast(canvasBitmap)) + L" " + ptrtow(reinterpret_cast(assistBitmap))); this->resizeEnd(); } - Logger.print(task.reserved[0]); } }; private: diff --git a/Window.cpp b/Window.cpp index 83771f8..df2fad3 100644 --- a/Window.cpp +++ b/Window.cpp @@ -16,7 +16,12 @@ int Window::pop() noexcept { void Window::render() const noexcept { for (const Widget* widget : widgets) widget->render(); } void Window::tick() noexcept { for (Widget* widget : widgets) widget->tick(); } void Window::onResize() { for (Widget* widget : widgets) widget->onResize(); } -void Window::passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept { for (Widget* widget : widgets) widget->passEvent(action, value, x, y); } + +int Window::passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept { + int ret = 0; + for (Widget* widget : widgets) ret |= widget->passEvent(action, value, x, y); + return ret; +} int WindowManager::pop(Window* value) noexcept { if (value->list != static_cast(this)) { @@ -53,16 +58,23 @@ CaptionWindow::CaptionWindow() { close->foregroundColor.inactive = 0xff000000; close->foregroundColor.clicked = 0xff000000; - Widget* minmax = widgets.emplace_back(Button(-interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"\\f\1🗖"))); - minmax->absolute(); - minmax->backgroundColor.hover = 0xffcccccc; - minmax->backgroundColor.active = 0; - minmax->backgroundColor.inactive = 0xff555555; - minmax->backgroundColor.clicked = 0xffaaaaaa; - minmax->foregroundColor.hover = 0xff000000; - minmax->foregroundColor.active = 0xff000000; - minmax->foregroundColor.inactive = 0xff000000; - minmax->foregroundColor.clicked = 0xff000000; + Widget* maxRestore = widgets.emplace_back(Button(-interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(IsZoomed(MainWindowHandle) ? L"\\f\1🗗" : L"\\f\1🗖" ))); + maxRestore->mouseClick = [](Widget&, MouseButtonCode) {}; + maxRestore->mouseClick = [](Widget& self, MouseButtonCode) { + if ((self.unused[1] = IsZoomed(MainWindowHandle))) ShowWindow(MainWindowHandle, SW_RESTORE); + else ShowWindow(MainWindowHandle, SW_MAXIMIZE); + }; + maxRestore->onTick = [this](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(self.unused[1] ? L"\\#ff4488ee复原窗口"_renderable : L"\\#ff4488ee最大化窗口"_renderable); }; + maxRestore->absolute(); + maxRestore->unused[1] = IsZoomed(MainWindowHandle); + maxRestore->backgroundColor.hover = 0xffcccccc; + maxRestore->backgroundColor.active = 0; + maxRestore->backgroundColor.inactive = 0xff555555; + maxRestore->backgroundColor.clicked = 0xffaaaaaa; + maxRestore->foregroundColor.hover = 0xff000000; + maxRestore->foregroundColor.active = 0xff000000; + maxRestore->foregroundColor.inactive = 0xff000000; + maxRestore->foregroundColor.clicked = 0xff000000; Widget* hide = widgets.emplace_back(Button(-2 * interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, LiteralText(L"\\f\1🗕"))); hide->mouseClick = [](Widget&, MouseButtonCode) { ShowWindow(MainWindowHandle, SW_MINIMIZE); }; @@ -261,7 +273,7 @@ void Button::render() const noexcept { } ConfirmWindow& ConfirmWindow::requireConfirm(const Function& func) { - confirm = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0, 0.4, 0.08, Location::CENTER, LiteralText(L"Confirm")))).ptr()); + confirm = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0, 0.4, 0.08, Location::CENTER, TranslatableText(L"hbp.confirm.confirm")))).ptr()); confirm->location = Location::CENTER; confirm->backgroundColor.active = 0x99000000; confirm->backgroundColor.hover = 0x9900ff00; @@ -281,15 +293,15 @@ ConfirmWindow& ConfirmWindow::requireConfirm(const Function& func confirm->w = 0.5; confirm->x = 0; } - confirm->onTick = [](Widget& confirm, MouseButtonCode) { if (confirm.containsMouse()) confirm.backgroundColor.hover = static_cast(confirm).animation.adaptsColor(0x99008800, 0x9900ff00); }; - confirm->mouseLeave = [](Widget& confirm, MouseButtonCode) { static_cast(confirm).animation.reset(); }; + confirm->onTick = [](Widget& confirm, MouseButtonCode) { if (confirm.containsMouse()) confirm.backgroundColor.hover = dynamic_cast(confirm).animation.adaptsColor(0x99008800, 0x9900ff00); }; + confirm->mouseLeave = [](Widget& confirm, MouseButtonCode) { dynamic_cast(confirm).animation.reset(); }; if (func) func(*confirm); confirm->onResize(); return *this; } ConfirmWindow& ConfirmWindow::requireCancel(const Function& func) { - cancel = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, Location::CENTER, LiteralText(L"Cancel")))).ptr()); + cancel = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, Location::CENTER, TranslatableText(L"hbp.confirm.cancel")))).ptr()); cancel->mouseClick = [this](Widget&, MouseButtonCode) { game.tasks.pushNewed(allocatedFor(new Task([this](Task& self) { if (game.closeWindow(this)) this->onClose(); diff --git a/Window.h b/Window.h index 77d38f6..6403a8c 100644 --- a/Window.h +++ b/Window.h @@ -60,11 +60,8 @@ protected: public: Location location; Location textLocation = Location::CENTER; // 多余字节预声明备用 + char unused[2]{}; // [0]: [1]: maxRestore_flag_IsZoomed -protected: - char unused[2]{}; - -public: Widget(const double x, const double y, const double w, const double h, const Location location) : x(x), y(y), w(w), h(h), location(location) {} unsigned int colorSelector(const Color& clr) const; @@ -116,11 +113,11 @@ public: virtual void onMouseClick(const MouseButtonCode value) noexcept { if (mouseClick) mouseClick(*this, value); } void tick() noexcept override { if (onTick) onTick(*this, 0); } - virtual void passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept { + virtual int passEvent(const MouseActionCode action, const MouseButtonCode value, const int x, const int y) noexcept { if (action == MouseActionCode::MAC_LEAVE || !isMouseIn(x, y)) { if (hasMouse) onMouseLeave(0); hasMouse = false; - return; + return 0; } hasMouse = true; switch (action) { @@ -142,6 +139,7 @@ public: default: break; } + return 1; } }; @@ -173,7 +171,7 @@ public: */ virtual void onClose() = 0; virtual void onResize(); - virtual void passEvent(MouseActionCode action, MouseButtonCode value, int x, int y) noexcept; + virtual int passEvent(MouseActionCode action, MouseButtonCode value, int x, int y) noexcept; }; class WindowManager final : public AnywhereEditableList, public IRenderable, public ITickable { diff --git a/def.h b/def.h index 6391881..34de0d2 100644 --- a/def.h +++ b/def.h @@ -18,14 +18,17 @@ #include #include #include +#include #include +#include using wchar = wchar_t; using QWORD = unsigned long long int; using String = std::wstring; using Thread = std::thread; template, typename Alloc = std::allocator>> using Map = std::map; -template> using List = std::list; +template> using Set = std::set; +template> using List = std::list; template using Function = std::function; #define Success() { return 0; } diff --git a/exception.h b/exception.h index d668f23..04845b2 100644 --- a/exception.h +++ b/exception.h @@ -4,6 +4,9 @@ #pragma once +#include "warnings.h" +#include "File.h" + class Exception : public std::exception { const String* type; @@ -53,6 +56,7 @@ public: class RuntimeException final : public Exception { inline static const String type = L"RuntimeException"; + public: RuntimeException(String&& msg) : Exception(std::move(msg), &type) {} RuntimeException(const String& msg) : Exception(msg, &type) {} @@ -60,62 +64,98 @@ public: class PublicLogger final { + File mainLogger = File(L"log.txt"); [[nodiscard]] String build(const String& msg, const String& type) const; - template requires requires(T t, Ts... ts) { - std::wcout << t; - (std::wcout << ... << ts); + template requires requires(std::wstringstream stream, T& t, Ts&&... ts) { + stream << std::forward(t); + (stream << ... << std::forward(ts)); } - static void prints(T&& t, Ts&&... ts) { - std::wcout << L" " << t; - prints(ts...); + static void prints(std::wstringstream& stream, T&& t, Ts&&... ts) { + stream << L" " << std::forward(t); + prints(stream, std::forward(ts)...); } - template requires requires(T t) { std::wcout << t; } - static void prints(T&& t) { std::wcout << L" " << t; } + template requires requires(std::wstringstream stream, T&& t) { stream << std::forward(t); } + static void prints(std::wstringstream& stream, T&& t) { stream << L" " << std::forward(t); } + + template requires requires(std::wstringstream stream, T&& t, Ts&&... ts) { + stream << std::forward(t); + (stream << ... << std::forward(ts)); + } + static void ofs(std::wstringstream& stream, T&& t, Ts&&... ts) { + stream << L" " << std::forward(t); + ofs(stream, std::forward(ts)...); + } + + template requires requires(std::wstringstream stream, T&& t) { stream << std::forward(t); } + static void ofs(std::wstringstream& stream, T&& t) { stream << L" " << std::forward(t); } public: const String name; - PublicLogger(const String& name): name(L" [" + name + L"] ") { std::wcout << L"PublicLogger created\n"; } + + PublicLogger(const String& name): name(L" [" + name + L"] ") { + std::wcout << L"PublicLogger created\n"; + std::wcout.imbue(std::locale("zh-CN.UTF-8")); + mainLogger.truncate().open(); + } PublicLogger& put(const String& msg) noexcept { - std::wcout << L"[] [Root]" + name + msg + L"\n"; + String str = L" " + name + L" " + msg + L"\n"; + std::wcout << str; + mainLogger << str; return *this; } PublicLogger& trace(const String& msg) noexcept { - std::wcout << build(msg, L"[Trace] "); + String str = build(msg, L"[Trace] "); + std::wcout << str; + mainLogger << str; return *this; } PublicLogger& debug(const String& msg) noexcept { - std::wcout << build(msg, L"[Debug] "); + String str = build(msg, L"[Debug] "); + std::wcout << str; + mainLogger << str; return *this; } PublicLogger& log(const String& msg) noexcept { - std::wcout << build(msg, L"[Log] "); + String str = build(msg, L"[Log] "); + std::wcout << str; + mainLogger << str; return *this; } PublicLogger& info(const String& msg) noexcept { - std::wcout << build(msg, L"[Info] "); + String str = build(msg, L"[Info] "); + std::wcout << str; + mainLogger << str; return *this; } PublicLogger& warn(const String& msg) noexcept { - std::wcout << build(msg, L"[Warn] "); + String str = build(msg, L"[Warn] "); + std::wcout << str; + mainLogger << str; return *this; } PublicLogger& error(const String& msg) noexcept { - std::wcout << build(msg, L"[Error] "); + String str = build(msg, L"[Error] "); + std::wcout << str; + mainLogger << str; return *this; } template requires requires(T t) { std::wcout << t; } PublicLogger& print(T&& msg) noexcept { - std::wcout << L"[] [Root]" + name << msg << std::endl; + std::wstringstream stream = {}; + stream << L" " << name << L" " << msg << std::endl; + String str = stream.str(); + mainLogger << str; + std::wcout << str; return *this; } @@ -124,12 +164,34 @@ public: std::wcout << (ts, ...); } PublicLogger& print(T&& msg, Ts&&... other) noexcept { - std::wcout << L"[] [Root]" + name << msg; - prints(other...); - std::wcout << std::endl; + std::wstringstream stream = {}; + stream << L" " << name << L" " << msg; + prints(stream, other...); + stream << std::endl; + String str = stream.str(); + mainLogger << str; + std::wcout << str; return *this; } + + template requires requires(std::wstringstream stream, T&& t, Ts&&... ts) { + stream << std::forward(t); + (stream << ... << std::forward(ts)); + } + String of(T&& t, Ts&&... ts) const { + std::wstringstream stream = {}; + stream << std::forward(t); + ofs(stream, ts...); + return stream.str(); + } + + template requires requires(std::wstringstream stream, T&& t) { std::wstringstream(t); } + String of(T&& ts) const { + std::wstringstream stream = {}; + ofs(stream, ts...); + return stream.str(); + } }; -inline PublicLogger Logger(L"Main"); +[[carlbeks::releasedat("main.cpp")]] inline PublicLogger& Logger = *new PublicLogger(L"Main"); diff --git a/gc.h b/gc.h index a155de7..218f291 100644 --- a/gc.h +++ b/gc.h @@ -6,7 +6,7 @@ #include "warnings.h" #include "def.h" -#include "File.h" +#include "exception.h" struct IGarbage; template @@ -46,7 +46,7 @@ class GarbageCollector { IGarbage* processing = nullptr; public: - GarbageCollector() { MainLogFile << L"initialize GarbageCollector" << std::endl; } + GarbageCollector() { Logger.info(L"initialize GarbageCollector"); } GarbageCollector(const GarbageCollector&) = delete; GarbageCollector(GarbageCollector&&) = delete; GarbageCollector& operator=(const GarbageCollector&) = delete; diff --git a/main.cpp b/main.cpp index 307fd69..1b7736a 100644 --- a/main.cpp +++ b/main.cpp @@ -86,7 +86,7 @@ LRESULT __stdcall WndProc(const HWND hwnd, const UINT uMsg, const WPARAM wParam, case WM_NCLBUTTONDOWN: if (interactManager.isInClientCaption()) { interactManager.update(VK_LBUTTON, true); - game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY()); + if (game.passEvent(MouseActionCode::MAC_DOWN, interactManager.getMouseButtonCode() | static_cast(MouseButtonCodeEnum::MBC_L_CHANGE), interactManager.getMouseX(), interactManager.getMouseY())) return 0; } break; case WM_RBUTTONDOWN: @@ -187,12 +187,12 @@ LRESULT __stdcall HookProc(const int code, const WPARAM wParam, const LPARAM lPa case WM_LBUTTONUP: case WM_NCLBUTTONUP: PostMessageW(MainWindowHandle, WM_APP_LBUTTONUP, p->wParam, p->lParam); - MainLogFile << L"BUTTON-UP\n"; + Logger.info(wParam ? L"[Hook] LButtonUp (Removed)" : L"[Hook] LButtonUp"); return 0; case WM_MBUTTONDOWN: case WM_NCMBUTTONDOWN: PostMessageW(MainWindowHandle, WM_APP_MBUTTONDOWN, p->wParam, p->lParam); - MainLogFile << L"BUTTON-DOWN\n"; + Logger.info(wParam ? L"[Hook] MButtonDown (Removed)" : L"[Hook] MButtonDown"); return 0; default: break; @@ -245,11 +245,12 @@ void renderThread() { } int __stdcall wWinMain(const HINSTANCE hInstance, const HINSTANCE, [[maybe_unused]] const LPWSTR lpCmdLine, [[maybe_unused]] const int nShowCmd) { - MainLogFile << L"wWinMain started" << std::endl; + Logger.info(L"wWinMain started"); + SetConsoleOutputCP(65001); + translator.initialize(); game.setWindow(StartWindow::create()); // 次序提前至最先 + Logger.info(L"--------Program Start--------"); for (const auto& [addr, info] : memoryManager.allocated) { Logger.print(L" using", addr, info.size, L"B", info.msg); } - MainLogFile << L"--------Program Start--------" << std::endl; - for (const auto& [addr, info] : memoryManager.allocated) { MainLogFile << L" using " << addr << L" " << info.size << L"B " << info.msg << std::endl; } WNDCLASSEX wc = {}; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; @@ -266,7 +267,7 @@ int __stdcall wWinMain(const HINSTANCE hInstance, const HINSTANCE, [[maybe_unuse if (!SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE)) Logger.print(L"SetProcessDpiAwarenessContext failed. LastError:", GetLastError()); MainInstance = hInstance; MainWindowHandle = CreateWindowExW(0, wc.lpszClassName, wc.lpszClassName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr, hInstance, nullptr); - SetWindowLongW(MainWindowHandle, GWL_STYLE, WS_VISIBLE | WS_MAXIMIZEBOX | WS_MAXIMIZE); + SetWindowLongW(MainWindowHandle, GWL_STYLE, WS_VISIBLE | WS_MAXIMIZEBOX); constexpr MARGINS margins{ .cxLeftWidth = 0, .cxRightWidth = 0, @@ -288,11 +289,10 @@ int __stdcall wWinMain(const HINSTANCE hInstance, const HINSTANCE, [[maybe_unuse })); SetWindowLongW(MainWindowHandle, GWL_EXSTYLE, GetWindowLongW(MainWindowHandle, GWL_EXSTYLE) | WS_EX_LAYERED); SetLayeredWindowAttributes(MainWindowHandle, 0xffffff, 0xe0, LWA_COLORKEY | LWA_ALPHA); - ShowWindow(MainWindowHandle, SW_SHOWMAXIMIZED); - SetConsoleOutputCP(65001); + ShowWindow(MainWindowHandle, nShowCmd); const HHOOK hook = SetWindowsHookW(WH_GETMESSAGE, HookProc); const HACCEL hAccelTable = LoadAcceleratorsW(hInstance, MAKEINTRESOURCE(109)); - if (!hook) MainLogFile << L"SetWindowsHookW failed. LastError: " << GetLastError() << std::endl; + if (!hook) Logger.error(Logger.of(L"SetWindowsHookW failed. LastError:", GetLastError())); test(); { interactManager.initialize(); @@ -313,9 +313,8 @@ int __stdcall wWinMain(const HINSTANCE hInstance, const HINSTANCE, [[maybe_unuse } DestroyAcceleratorTable(hAccelTable); UnhookWindowsHookEx(hook); - for (const auto& [addr, info] : memoryManager.allocated) { Logger.print(L"using", addr, info.size, L"B", info.msg); } - MainLogFile << L"-------- Program End --------" << std::endl; - for (const auto& [addr, info] : memoryManager.allocated) { MainLogFile << L" using " << addr << L" " << info.size << L"B " << info.msg << std::endl; } + Logger.info(L"------- Program End --------"); + for (const auto& [addr, info] : memoryManager.allocated) { Logger.print(L" using", addr, info.size, L"B", info.msg); } _wsystem(L"pause"); return static_cast(msg.wParam); } @@ -325,9 +324,8 @@ struct Release { ~Release() { delete &gc; - MainLogFile << L"--------- Last Check ---------" << std::endl; - for (const auto& [addr, info] : memoryManager.allocated) { MainLogFile << L" using " << addr << L" " << info.size << L"B " << info.msg << std::endl; } - MainLogFile.close(); - delete &MainLogFile; + Logger.put(L"--------- Last Check ---------\n"); + for (const auto& [addr, info] : memoryManager.allocated) { Logger.print(L" using", addr, info.size, L"B", info.msg); } + delete &Logger; } } NEVER_REFERENCED_release;