1
0
mirror of synced 2024-12-01 02:37:18 +01:00

feat: keep console window on Windows for debug builds

This commit is contained in:
xtex 2021-09-20 10:57:52 +08:00
parent 70666416f7
commit 9fd4699c9f
No known key found for this signature in database
GPG Key ID: 978F2E760D9DB0EB

View File

@ -1,261 +1,263 @@
#include "window.hpp" #include "window.hpp"
#if defined(OS_WINDOWS) #if defined(OS_WINDOWS)
#include <hex/helpers/utils.hpp> #include <hex/helpers/utils.hpp>
#include <hex/helpers/logger.hpp> #include <hex/helpers/logger.hpp>
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h> #include <imgui_internal.h>
#include <codicons_font.h> #include <codicons_font.h>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#define GLFW_EXPOSE_NATIVE_WIN32 #define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h> #include <GLFW/glfw3native.h>
#undef GLFW_EXPOSE_NATIVE_WIN32 #undef GLFW_EXPOSE_NATIVE_WIN32
#include <winuser.h> #include <winuser.h>
#include <dwmapi.h> #include <dwmapi.h>
#include <windowsx.h> #include <windowsx.h>
namespace hex { namespace hex {
static LONG_PTR oldWndProc; static LONG_PTR oldWndProc;
static float titleBarHeight; static float titleBarHeight;
static ImGuiMouseCursor mouseCursorIcon; static ImGuiMouseCursor mouseCursorIcon;
static bool isTaskbarAutoHideEnabled(UINT edge, RECT monitor) { static bool isTaskbarAutoHideEnabled(UINT edge, RECT monitor) {
APPBARDATA data = { .cbSize = sizeof(APPBARDATA), .uEdge = edge, .rc = monitor }; APPBARDATA data = { .cbSize = sizeof(APPBARDATA), .uEdge = edge, .rc = monitor };
return ::SHAppBarMessage(ABM_GETAUTOHIDEBAR, &data); return ::SHAppBarMessage(ABM_GETAUTOHIDEBAR, &data);
} }
static LRESULT windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static LRESULT windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) { switch (uMsg) {
case WM_NCCALCSIZE: { case WM_NCCALCSIZE: {
RECT &rect = *reinterpret_cast<RECT*>(lParam); RECT &rect = *reinterpret_cast<RECT*>(lParam);
RECT client = rect; RECT client = rect;
DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam); DefWindowProcW(hwnd, WM_NCCALCSIZE, wParam, lParam);
if (IsMaximized(hwnd)) { if (IsMaximized(hwnd)) {
WINDOWINFO windowInfo = { .cbSize = sizeof(WINDOWINFO) }; WINDOWINFO windowInfo = { .cbSize = sizeof(WINDOWINFO) };
GetWindowInfo(hwnd, &windowInfo); GetWindowInfo(hwnd, &windowInfo);
rect = RECT { rect = RECT {
.left = static_cast<LONG>(client.left + windowInfo.cyWindowBorders), .left = static_cast<LONG>(client.left + windowInfo.cyWindowBorders),
.top = static_cast<LONG>(client.top + windowInfo.cyWindowBorders), .top = static_cast<LONG>(client.top + windowInfo.cyWindowBorders),
.right = static_cast<LONG>(client.right - windowInfo.cyWindowBorders), .right = static_cast<LONG>(client.right - windowInfo.cyWindowBorders),
.bottom = static_cast<LONG>(client.bottom - windowInfo.cyWindowBorders) .bottom = static_cast<LONG>(client.bottom - windowInfo.cyWindowBorders)
}; };
HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY); HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
MONITORINFO monitorInfo = { .cbSize = sizeof(MONITORINFO) }; MONITORINFO monitorInfo = { .cbSize = sizeof(MONITORINFO) };
GetMonitorInfoW(hMonitor, &monitorInfo); GetMonitorInfoW(hMonitor, &monitorInfo);
if (EqualRect(&rect, &monitorInfo.rcMonitor)) { if (EqualRect(&rect, &monitorInfo.rcMonitor)) {
if (isTaskbarAutoHideEnabled(ABE_BOTTOM, monitorInfo.rcMonitor)) if (isTaskbarAutoHideEnabled(ABE_BOTTOM, monitorInfo.rcMonitor))
rect.bottom--; rect.bottom--;
else if (isTaskbarAutoHideEnabled(ABE_LEFT, monitorInfo.rcMonitor)) else if (isTaskbarAutoHideEnabled(ABE_LEFT, monitorInfo.rcMonitor))
rect.left++; rect.left++;
else if (isTaskbarAutoHideEnabled(ABE_TOP, monitorInfo.rcMonitor)) else if (isTaskbarAutoHideEnabled(ABE_TOP, monitorInfo.rcMonitor))
rect.top++; rect.top++;
else if (isTaskbarAutoHideEnabled(ABE_RIGHT, monitorInfo.rcMonitor)) else if (isTaskbarAutoHideEnabled(ABE_RIGHT, monitorInfo.rcMonitor))
rect.right--; rect.right--;
} }
} else { } else {
rect = client; rect = client;
} }
return 0; return 0;
} }
case WM_SETCURSOR: { case WM_SETCURSOR: {
auto cursorPos = LOWORD(lParam); auto cursorPos = LOWORD(lParam);
switch (cursorPos) { switch (cursorPos) {
case HTRIGHT: case HTRIGHT:
case HTLEFT: case HTLEFT:
mouseCursorIcon = ImGuiMouseCursor_ResizeEW; mouseCursorIcon = ImGuiMouseCursor_ResizeEW;
return TRUE; return TRUE;
case HTTOP: case HTTOP:
case HTBOTTOM: case HTBOTTOM:
mouseCursorIcon = ImGuiMouseCursor_ResizeNS; mouseCursorIcon = ImGuiMouseCursor_ResizeNS;
return TRUE; return TRUE;
case HTTOPLEFT: case HTTOPLEFT:
case HTBOTTOMRIGHT: case HTBOTTOMRIGHT:
mouseCursorIcon = ImGuiMouseCursor_ResizeNWSE; mouseCursorIcon = ImGuiMouseCursor_ResizeNWSE;
return TRUE; return TRUE;
case HTTOPRIGHT: case HTTOPRIGHT:
case HTBOTTOMLEFT: case HTBOTTOMLEFT:
mouseCursorIcon = ImGuiMouseCursor_ResizeNESW; mouseCursorIcon = ImGuiMouseCursor_ResizeNESW;
return TRUE; return TRUE;
default: default:
mouseCursorIcon = ImGuiMouseCursor_None; mouseCursorIcon = ImGuiMouseCursor_None;
return TRUE; return TRUE;
} }
} }
case WM_NCHITTEST: { case WM_NCHITTEST: {
POINT cursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; POINT cursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
const POINT border{ const POINT border{
static_cast<LONG>((::GetSystemMetrics(SM_CXFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * SharedData::globalScale / 2.0F), static_cast<LONG>((::GetSystemMetrics(SM_CXFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * SharedData::globalScale / 2.0F),
static_cast<LONG>((::GetSystemMetrics(SM_CYFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * SharedData::globalScale / 2.0F) static_cast<LONG>((::GetSystemMetrics(SM_CYFRAME) + ::GetSystemMetrics(SM_CXPADDEDBORDER)) * SharedData::globalScale / 2.0F)
}; };
RECT window; RECT window;
if (!::GetWindowRect(hwnd, &window)) { if (!::GetWindowRect(hwnd, &window)) {
return HTNOWHERE; return HTNOWHERE;
} }
constexpr auto RegionClient = 0b0000; constexpr auto RegionClient = 0b0000;
constexpr auto RegionLeft = 0b0001; constexpr auto RegionLeft = 0b0001;
constexpr auto RegionRight = 0b0010; constexpr auto RegionRight = 0b0010;
constexpr auto RegionTop = 0b0100; constexpr auto RegionTop = 0b0100;
constexpr auto RegionBottom = 0b1000; constexpr auto RegionBottom = 0b1000;
const auto result = const auto result =
RegionLeft * (cursor.x < (window.left + border.x)) | RegionLeft * (cursor.x < (window.left + border.x)) |
RegionRight * (cursor.x >= (window.right - border.x)) | RegionRight * (cursor.x >= (window.right - border.x)) |
RegionTop * (cursor.y < (window.top + border.y)) | RegionTop * (cursor.y < (window.top + border.y)) |
RegionBottom * (cursor.y >= (window.bottom - border.y)); RegionBottom * (cursor.y >= (window.bottom - border.y));
switch (result) { switch (result) {
case RegionLeft: case RegionLeft:
return HTLEFT; return HTLEFT;
case RegionRight: case RegionRight:
return HTRIGHT; return HTRIGHT;
case RegionTop: case RegionTop:
return HTTOP; return HTTOP;
case RegionBottom: case RegionBottom:
return HTBOTTOM; return HTBOTTOM;
case RegionTop | RegionLeft: case RegionTop | RegionLeft:
return HTTOPLEFT; return HTTOPLEFT;
case RegionTop | RegionRight: case RegionTop | RegionRight:
return HTTOPRIGHT; return HTTOPRIGHT;
case RegionBottom | RegionLeft: case RegionBottom | RegionLeft:
return HTBOTTOMLEFT; return HTBOTTOMLEFT;
case RegionBottom | RegionRight: case RegionBottom | RegionRight:
return HTBOTTOMRIGHT; return HTBOTTOMRIGHT;
case RegionClient: case RegionClient:
default: default:
if ((cursor.y < (window.top + titleBarHeight * 2)) && !ImGui::IsAnyItemHovered()) if ((cursor.y < (window.top + titleBarHeight * 2)) && !ImGui::IsAnyItemHovered())
return HTCAPTION; return HTCAPTION;
else break; else break;
} }
break; break;
} }
case WM_SETTINGCHANGE: case WM_SETTINGCHANGE:
{ {
if (LPCTSTR(lParam) == std::string_view("ImmersiveColorSet")) { if (LPCTSTR(lParam) == std::string_view("ImmersiveColorSet")) {
EventManager::post<EventOSThemeChanged>(); EventManager::post<EventOSThemeChanged>();
} }
break; break;
} }
default: break; default: break;
} }
return CallWindowProc((WNDPROC)oldWndProc, hwnd, uMsg, wParam, lParam); return CallWindowProc((WNDPROC)oldWndProc, hwnd, uMsg, wParam, lParam);
} }
void Window::initNative() { void Window::initNative() {
auto hConsoleWindow = ::GetConsoleWindow(); auto hConsoleWindow = ::GetConsoleWindow();
::ShowWindow(hConsoleWindow, FALSE); #if !defined(DEBUG)
::ShowWindow(hConsoleWindow, FALSE);
auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE); #endif
if (hConsole != INVALID_HANDLE_VALUE) {
DWORD mode = 0; auto hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
if (::GetConsoleMode(hConsole, &mode)) { if (hConsole != INVALID_HANDLE_VALUE) {
mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; DWORD mode = 0;
::SetConsoleMode(hConsole, mode); if (::GetConsoleMode(hConsole, &mode)) {
} mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
} ::SetConsoleMode(hConsole, mode);
} }
}
void Window::setupNativeWindow() { }
auto hwnd = glfwGetWin32Window(this->m_window);
void Window::setupNativeWindow() {
oldWndProc = ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)windowProc); auto hwnd = glfwGetWin32Window(this->m_window);
MARGINS borderless = {1,1,1,1}; oldWndProc = ::SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)windowProc);
::DwmExtendFrameIntoClientArea(hwnd, &borderless);
MARGINS borderless = {1,1,1,1};
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE); ::DwmExtendFrameIntoClientArea(hwnd, &borderless);
::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_POPUP | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU);
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE);
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0; ::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_POPUP | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU);
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem]{
if (!themeFollowSystem) return; bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem]{
HKEY hkey; if (!themeFollowSystem) return;
if (RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hkey) == ERROR_SUCCESS) {
DWORD value = 0; HKEY hkey;
DWORD size = sizeof(DWORD); if (RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hkey) == ERROR_SUCCESS) {
DWORD value = 0;
auto error = RegQueryValueEx(hkey, "AppsUseLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size); DWORD size = sizeof(DWORD);
if (error == ERROR_SUCCESS) {
EventManager::post<RequestChangeTheme>(value == 0 ? 1 : 2); auto error = RegQueryValueEx(hkey, "AppsUseLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size);
} if (error == ERROR_SUCCESS) {
} EventManager::post<RequestChangeTheme>(value == 0 ? 1 : 2);
}); }
}
if (themeFollowSystem) });
EventManager::post<EventOSThemeChanged>();
} if (themeFollowSystem)
EventManager::post<EventOSThemeChanged>();
void Window::updateNativeWindow() { }
titleBarHeight = ImGui::GetCurrentWindow()->MenuBarHeight();
void Window::updateNativeWindow() {
if (mouseCursorIcon != ImGuiMouseCursor_None) titleBarHeight = ImGui::GetCurrentWindow()->MenuBarHeight();
ImGui::SetMouseCursor(mouseCursorIcon);
} if (mouseCursorIcon != ImGuiMouseCursor_None)
ImGui::SetMouseCursor(mouseCursorIcon);
void Window::drawTitleBar() { }
auto buttonSize = ImVec2(titleBarHeight * 1.5F, titleBarHeight - 1);
void Window::drawTitleBar() {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0)); auto buttonSize = ImVec2(titleBarHeight * 1.5F, titleBarHeight - 1);
ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_MenuBarBg));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabActive)); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabHovered)); ImGui::PushStyleColor(ImGuiCol_Button, ImGui::GetColorU32(ImGuiCol_MenuBarBg));
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabActive));
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - buttonSize.x * 6); ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImGui::GetColorU32(ImGuiCol_ScrollbarGrabHovered));
#if defined(DEBUG)
if (ImGui::TitleBarButton(ICON_VS_DEBUG, buttonSize)) ImGui::SetCursorPosX(ImGui::GetWindowWidth() - buttonSize.x * 6);
hex::openWebpage("https://imhex.werwolv.net/debug"); #if defined(DEBUG)
ImGui::InfoTooltip("hex.menu.debug_build"_lang); if (ImGui::TitleBarButton(ICON_VS_DEBUG, buttonSize))
#endif hex::openWebpage("https://imhex.werwolv.net/debug");
if (ImGui::TitleBarButton(ICON_VS_SMILEY, buttonSize)) ImGui::InfoTooltip("hex.menu.debug_build"_lang);
hex::openWebpage("mailto://hey@werwolv.net"); #endif
ImGui::InfoTooltip("hex.menu.feedback"_lang); if (ImGui::TitleBarButton(ICON_VS_SMILEY, buttonSize))
hex::openWebpage("mailto://hey@werwolv.net");
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - buttonSize.x * 3); ImGui::InfoTooltip("hex.menu.feedback"_lang);
if (ImGui::TitleBarButton(ICON_VS_CHROME_MINIMIZE, buttonSize))
glfwIconifyWindow(this->m_window); ImGui::SetCursorPosX(ImGui::GetWindowWidth() - buttonSize.x * 3);
if (glfwGetWindowAttrib(this->m_window, GLFW_MAXIMIZED)) { if (ImGui::TitleBarButton(ICON_VS_CHROME_MINIMIZE, buttonSize))
if (ImGui::TitleBarButton(ICON_VS_CHROME_RESTORE, buttonSize)) glfwIconifyWindow(this->m_window);
glfwRestoreWindow(this->m_window); if (glfwGetWindowAttrib(this->m_window, GLFW_MAXIMIZED)) {
} else { if (ImGui::TitleBarButton(ICON_VS_CHROME_RESTORE, buttonSize))
if (ImGui::TitleBarButton(ICON_VS_CHROME_MAXIMIZE, buttonSize)) glfwRestoreWindow(this->m_window);
glfwMaximizeWindow(this->m_window); } else {
} if (ImGui::TitleBarButton(ICON_VS_CHROME_MAXIMIZE, buttonSize))
glfwMaximizeWindow(this->m_window);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, 0xFF7A70F1); }
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, 0xFF2311E8);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, 0xFF7A70F1);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, 0xFF2311E8);
if (ImGui::TitleBarButton(ICON_VS_CHROME_CLOSE, buttonSize)) {
ImHexApi::Common::closeImHex();
} if (ImGui::TitleBarButton(ICON_VS_CHROME_CLOSE, buttonSize)) {
ImHexApi::Common::closeImHex();
ImGui::PopStyleColor(5); }
ImGui::PopStyleVar();
ImGui::PopStyleColor(5);
ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize(this->m_windowTitle.c_str()).x) / 2); ImGui::PopStyleVar();
ImGui::TextUnformatted(this->m_windowTitle.c_str());
} ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize(this->m_windowTitle.c_str()).x) / 2);
ImGui::TextUnformatted(this->m_windowTitle.c_str());
} }
}
#endif #endif