diff --git a/plugins/builtin/source/content/themes.cpp b/plugins/builtin/source/content/themes.cpp index fc28e6fbe..54bca3c43 100644 --- a/plugins/builtin/source/content/themes.cpp +++ b/plugins/builtin/source/content/themes.cpp @@ -13,6 +13,15 @@ namespace hex::plugin::builtin { + namespace { + + [[maybe_unused]] void printThemeData(const auto &colorMap, const auto &colors) { + for (const auto &[name, id] : colorMap) + fmt::print("\"{}\": \"#{:08X}\",\n", name, hex::changeEndianess(colors[id], std::endian::big)); + } + + } + void registerThemeHandlers() { api::ThemeManager::addThemeHandler("imgui", [](const std::string &key, const std::string &value) { const static std::map ColorMap = { diff --git a/plugins/builtin/source/content/views/view_provider_settings.cpp b/plugins/builtin/source/content/views/view_provider_settings.cpp index 50466d4fd..21cb5495e 100644 --- a/plugins/builtin/source/content/views/view_provider_settings.cpp +++ b/plugins/builtin/source/content/views/view_provider_settings.cpp @@ -41,15 +41,15 @@ namespace hex::plugin::builtin { } else { View::showErrorPopup("hex.builtin.view.provider_settings.load_error"_lang); - ImHexApi::Provider::remove(provider); + TaskManager::doLater([=] { ImHexApi::Provider::remove(provider); }); } } ImGui::SameLine(); if (ImGui::Button("hex.builtin.common.cancel"_lang)) { - ImHexApi::Provider::remove(provider); ImGui::CloseCurrentPopup(); + TaskManager::doLater([=] { ImHexApi::Provider::remove(provider); }); } } diff --git a/plugins/windows/include/content/providers/process_memory_provider.hpp b/plugins/windows/include/content/providers/process_memory_provider.hpp index d5923ad2c..89b0f0325 100644 --- a/plugins/windows/include/content/providers/process_memory_provider.hpp +++ b/plugins/windows/include/content/providers/process_memory_provider.hpp @@ -5,6 +5,9 @@ #include +#include +#include + #include #include #include @@ -62,6 +65,7 @@ namespace hex::plugin::windows { struct Process { u32 id; std::string name; + ImGui::Texture icon; }; struct MemoryRegion { @@ -74,7 +78,7 @@ namespace hex::plugin::windows { }; std::vector m_processes; - std::optional m_selectedProcess; + Process *m_selectedProcess = nullptr; std::set m_memoryRegions; diff --git a/plugins/windows/source/content/providers/process_memory_provider.cpp b/plugins/windows/source/content/providers/process_memory_provider.cpp index c3be39e6a..f00d9a1c3 100644 --- a/plugins/windows/source/content/providers/process_memory_provider.cpp +++ b/plugins/windows/source/content/providers/process_memory_provider.cpp @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -105,6 +106,8 @@ namespace hex::plugin::windows { processIds.resize(numProcesses / sizeof(DWORD)); + auto dc = GetDC(nullptr); + ON_SCOPE_EXIT { ReleaseDC(nullptr, dc); }; for (auto processId : processIds) { HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId); if (processHandle == nullptr) @@ -116,14 +119,54 @@ namespace hex::plugin::windows { if (GetModuleBaseNameA(processHandle, nullptr, processName, MAX_PATH) == 0) continue; - this->m_processes.push_back({ processId, processName }); + ImGui::Texture texture; + { + HMODULE moduleHandle = nullptr; + DWORD numModules = 0; + if (EnumProcessModules(processHandle, &moduleHandle, sizeof(HMODULE), &numModules) != FALSE) { + char modulePath[MAX_PATH]; + if (GetModuleFileNameExA(processHandle, moduleHandle, modulePath, MAX_PATH) != FALSE) { + SHFILEINFOA fileInfo; + if (SHGetFileInfoA(modulePath, 0, &fileInfo, sizeof(SHFILEINFOA), SHGFI_ICON | SHGFI_SMALLICON) > 0) { + ON_SCOPE_EXIT { DestroyIcon(fileInfo.hIcon); }; + + ICONINFO iconInfo; + if (GetIconInfo(fileInfo.hIcon, &iconInfo) != FALSE) { + ON_SCOPE_EXIT { DeleteObject(iconInfo.hbmColor); DeleteObject(iconInfo.hbmMask); }; + + BITMAP bitmap; + if (GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bitmap) > 0) { + BITMAPINFO bitmapInfo = { }; + bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bitmapInfo.bmiHeader.biWidth = bitmap.bmWidth; + bitmapInfo.bmiHeader.biHeight = -bitmap.bmHeight; + bitmapInfo.bmiHeader.biPlanes = 1; + bitmapInfo.bmiHeader.biBitCount = 32; + bitmapInfo.bmiHeader.biCompression = BI_RGB; + + std::vector pixels(bitmap.bmWidth * bitmap.bmHeight * 4); + if (GetDIBits(dc, iconInfo.hbmColor, 0, bitmap.bmHeight, pixels.data(), &bitmapInfo, DIB_RGB_COLORS) > 0) { + for (auto &pixel : pixels) + pixel = (pixel & 0xFF00FF00) | ((pixel & 0xFF) << 16) | ((pixel & 0xFF0000) >> 16); + + texture = ImGui::Texture((u8*)pixels.data(), pixels.size(), bitmap.bmWidth, bitmap.bmHeight); + } + } + } + } + } + } + } + + this->m_processes.push_back({ processId, processName, std::move(texture) }); } } if (this->m_enumerationFailed) { ImGui::TextUnformatted("hex.windows.provider.process_memory.enumeration_failed"_lang); } else { - if (ImGui::BeginTable("##process_table", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 500_scaled))) { + if (ImGui::BeginTable("##process_table", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_ScrollY, ImVec2(0, 500_scaled))) { + ImGui::TableSetupColumn("##icon"); ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_id"_lang); ImGui::TableSetupColumn("hex.windows.provider.process_memory.process_name"_lang); ImGui::TableSetupScrollFreeze(0, 1); @@ -134,12 +177,15 @@ namespace hex::plugin::windows { ImGui::PushID(process.id); ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Image(process.icon, process.icon.getSize()); + ImGui::TableNextColumn(); ImGui::Text("%d", process.id); ImGui::TableNextColumn(); - if (ImGui::Selectable(process.name.c_str(), this->m_selectedProcess.has_value() && process.id == this->m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns)) - this->m_selectedProcess = process; + if (ImGui::Selectable(process.name.c_str(), this->m_selectedProcess != nullptr && process.id == this->m_selectedProcess->id, ImGuiSelectableFlags_SpanAllColumns, ImVec2(0, process.icon.getSize().y))) + this->m_selectedProcess = &process; ImGui::PopID(); }