From 875cad990ed7f70da1926b4bca3cad8c54b15ad6 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 00:44:00 +0100 Subject: [PATCH 1/9] Resolve My Pictures folder --- include/utility/fsutil.h | 8 +++++++- src/utility/fsutil.cpp | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/utility/fsutil.h b/include/utility/fsutil.h index 2b346ed..2c2b86a 100644 --- a/include/utility/fsutil.h +++ b/include/utility/fsutil.h @@ -53,6 +53,10 @@ struct SKIF_CommonPathsCache { { FOLDERID_Documents, L"%USERPROFILE%\\My Documents" }; + win_path_s my_pictures = + { FOLDERID_Pictures, + L"%USERPROFILE%\\My Documents\\My Pictures" + }; win_path_s app_data_local = { FOLDERID_LocalAppData, L"%USERPROFILE%\\AppData\\Local" @@ -92,7 +96,9 @@ struct SKIF_CommonPathsCache { wchar_t skiv_install [MAX_PATH + 2] = { }; // Holds the install folder for SKIV wchar_t skiv_userdata [MAX_PATH + 2] = { }; // Holds the user data folder for SKIV wchar_t specialk_userdata [MAX_PATH + 2] = { }; // Holds the user data folder for SK (often lines up with its install folder) - wchar_t skiv_temp [MAX_PATH + 2] = { }; // Holds the temp data folder for SKIV (images downloaded from the web; cleared out on every launch): %APPDATA%\TEMP\SKIV\ + wchar_t skiv_temp [MAX_PATH + 2] = { }; // Holds the temp data folder for SKIV (images downloaded from the web; cleared out on every launch): %APPDATA%\TEMP\SKIV + wchar_t skiv_screenshots [MAX_PATH + 2] = { }; // Holds the screenshot folder for SKIV + char skiv_screenshotsA [MAX_PATH + 2] = { }; // UTF-8 // Functions diff --git a/src/utility/fsutil.cpp b/src/utility/fsutil.cpp index 10f0f48..5f94a14 100644 --- a/src/utility/fsutil.cpp +++ b/src/utility/fsutil.cpp @@ -337,6 +337,7 @@ SKIF_CommonPathsCache::SKIF_CommonPathsCache (void) { // Cache user profile locations SKIF_GetFolderPath ( &my_documents ); + SKIF_GetFolderPath ( &my_pictures ); SKIF_GetFolderPath ( &app_data_local ); SKIF_GetFolderPath ( &app_data_local_low ); SKIF_GetFolderPath ( &app_data_roaming ); From 48dcd52b6f3cadb1eb55171e50cc5a89a7cd9654 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 00:44:21 +0100 Subject: [PATCH 2/9] Add new Screenshots path + toggle --- include/utility/registry.h | 10 ++++++++++ src/utility/registry.cpp | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/include/utility/registry.h b/include/utility/registry.h index 792bf3e..00b3d7f 100644 --- a/include/utility/registry.h +++ b/include/utility/registry.h @@ -265,6 +265,10 @@ struct SKIF_RegistrySettings { SKIF_MakeRegKeyB ( LR"(SOFTWARE\Kaldaien\Special K\Viewer\)", LR"(99th Percentile MaxCLL)" ); + KeyValue regKVSaveScreenshots = + SKIF_MakeRegKeyB ( LR"(SOFTWARE\Kaldaien\Special K\Viewer\)", + LR"(Save Screenshots)" ); + // Integers (DWORDs) KeyValue regKVImageScaling = @@ -357,6 +361,10 @@ struct SKIF_RegistrySettings { SKIF_MakeRegKeyWS ( LR"(SOFTWARE\Kaldaien\Special K\Viewer\)", LR"(Path)" ); + KeyValue regKVPathScreenshots = + SKIF_MakeRegKeyWS ( LR"(SOFTWARE\Kaldaien\Special K\Viewer\)", + LR"(Screenshots)" ); + KeyValue regKVAutoUpdateVersion = SKIF_MakeRegKeyWS ( LR"(SOFTWARE\Kaldaien\Special K\Viewer\)", LR"(Auto-Update Version)" ); @@ -451,11 +459,13 @@ struct SKIF_RegistrySettings { bool bFadeCovers = true; bool bControllers = true; // Should SKIF support controller input ? bool bLoggingDeveloper = false; // This is a log level "above" verbose logging that also includes stuff like window messages. Only useable for SKIF developers + bool bSaveScreenshots = true; // Wide strings std::wstring wsUpdateChannel = L"Website"; // Default to stable channel std::wstring wsIgnoreUpdate; std::wstring wsPathViewer; + std::wstring wsPathScreenshots; std::wstring wsPathSpecialK; std::wstring wsAutoUpdateVersion; // Holds the version the auto-updater is trying to install std::wstring wsDefaultHDRExt = L".png"; diff --git a/src/utility/registry.cpp b/src/utility/registry.cpp index 8e5452e..7059c63 100644 --- a/src/utility/registry.cpp +++ b/src/utility/registry.cpp @@ -378,6 +378,9 @@ SKIF_RegistrySettings::SKIF_RegistrySettings (void) if (regKVPathViewer.hasData(&hKey)) wsPathViewer = regKVPathViewer .getData (&hKey); + if (regKVPathScreenshots.hasData(&hKey)) + wsPathScreenshots = regKVPathScreenshots .getData (&hKey); + if (regKVAutoUpdateVersion.hasData(&hKey)) wsAutoUpdateVersion = regKVAutoUpdateVersion .getData (&hKey); @@ -397,6 +400,9 @@ SKIF_RegistrySettings::SKIF_RegistrySettings (void) if (regKV99thPercentileMaxCLL.hasData(&hKey)) b99thPercentileMaxCLL = regKV99thPercentileMaxCLL .getData (&hKey); + if (regKVSaveScreenshots.hasData(&hKey)) + bSaveScreenshots = regKVSaveScreenshots .getData (&hKey); + // These defaults to false, so no need to check if the registry has another value // since getData ( ) defaults to false for non-existent registry values bFirstLaunch = regKVFirstLaunch .getData (&hKey); From 0cbf6aeb4d614fb373eef28fb0f684077118aee3 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 00:44:44 +0100 Subject: [PATCH 3/9] Add a "Browse Folder" helper function --- include/utility/utility.h | 1 + src/utility/utility.cpp | 44 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/include/utility/utility.h b/include/utility/utility.h index e32e79e..2bbea2a 100644 --- a/include/utility/utility.h +++ b/include/utility/utility.h @@ -216,6 +216,7 @@ std::wstring SKIF_Util_GetClipboardHDROP (void); DirectX::Image SKIF_Util_GetClipboardBitmapData (void); std::wstring SKIF_Util_AddEnvironmentBlock (const void* pEnvBlock, const std::wstring& varName, const std::wstring& varValue); void SKIF_Util_FileExplorer_SelectFile (PCWSTR filePath); +std::wstring SKIF_Util_FileExplorer_BrowseFolder (PCWSTR defaultPath); std::string SKIF_Util_GetWindowMessageAsStr (UINT msg); diff --git a/src/utility/utility.cpp b/src/utility/utility.cpp index 0c25b58..d272634 100644 --- a/src/utility/utility.cpp +++ b/src/utility/utility.cpp @@ -2700,6 +2700,50 @@ SKIF_Util_FileExplorer_SelectFile (PCWSTR filePath) delete data; } +static int +CALLBACK +SKIF_Util_FileExplorer_BrowseFolder_CallbackProc (HWND hWnd,UINT uMsg, LPARAM lParam, LPARAM lpData) +{ + UNREFERENCED_PARAMETER (lParam); + + if (uMsg == BFFM_INITIALIZED) + SendMessage (hWnd, BFFM_SETSELECTION, TRUE, lpData); + + return 0; +} + +std::wstring +SKIF_Util_FileExplorer_BrowseFolder (PCWSTR defaultPath) +{ + TCHAR path[MAX_PATH]; + + BROWSEINFO + bi = { }; + bi.lpszTitle = L"Select a new screenshot folder for SKIV to use:"; + bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE; + bi.lpfn = SKIF_Util_FileExplorer_BrowseFolder_CallbackProc; + bi.lParam = (LPARAM) defaultPath; + + LPITEMIDLIST pidl = SHBrowseForFolder ( &bi ); + + if ( pidl != 0 ) + { + // Get the name of the folder and put it in path + SHGetPathFromIDList ( pidl, path ); + + // Free memory used + IMalloc * imalloc = 0; + if ( SUCCEEDED( SHGetMalloc ( &imalloc )) ) + { + imalloc->Free ( pidl ); + imalloc->Release ( ); + } + + return path; + } + + return L""; +} #if NTDDI_VERSION < NTDDI_WIN10_RS5 // Effective Power Mode (Windows 10 1809+) From 1de4f03b45f7ddaede1f200f8855b2259a4548c6 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 00:45:21 +0100 Subject: [PATCH 4/9] Make the new Screenshots settings configurable --- src/tabs/settings.cpp | 64 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/src/tabs/settings.cpp b/src/tabs/settings.cpp index d4dea38..a01e419 100644 --- a/src/tabs/settings.cpp +++ b/src/tabs/settings.cpp @@ -62,9 +62,65 @@ SKIF_UI_Tab_DrawSettings (void) ImGui::Spacing (); ImGui::Spacing (); +#pragma region Section: Screenshots + + if (ImGui::CollapsingHeader ("Screenshots###SKIF_SettingsHeader-0", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::PushStyleColor ( + ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_SKIF_TextBase) + ); + + SKIF_ImGui_Spacing ( ); + + + if ( ImGui::Checkbox ( "Save screenshots", &_registry.bSaveScreenshots ) ) + _registry.regKVSaveScreenshots.putData ( _registry.bSaveScreenshots); + + ImGui::TreePush ("ScreenshotsFolder"); + + if (! _registry.bSaveScreenshots) + SKIF_ImGui_PushDisableState ( ); + + if (ImGui::Button ("Browse")) + { + std::wstring newPath = SKIF_Util_FileExplorer_BrowseFolder (_path_cache.skiv_screenshots); + + if (PathFileExistsW (newPath.c_str())) + { + if (newPath.back() != '\\') + newPath += '\\'; + + wcsncpy_s (_path_cache.skiv_screenshots, MAX_PATH, + newPath.c_str(), _TRUNCATE); + strncpy_s (_path_cache.skiv_screenshotsA, MAX_PATH, + SK_WideCharToUTF8 (_path_cache.skiv_screenshots).data(), _TRUNCATE); + + _registry.regKVPathScreenshots.putData (_path_cache.skiv_screenshots); + + PLOG_INFO << "Screenshots folder was changed: " << _path_cache.skiv_screenshots; + } + } + + ImGui::SameLine ( ); + ImGui::Spacing ( ); + ImGui::SameLine ( ); + + ImGui::Text ("%s", _path_cache.skiv_screenshotsA); + + if (! _registry.bSaveScreenshots) + SKIF_ImGui_PopDisableState ( ); + + ImGui::TreePop ( ); + } + + ImGui::Spacing (); + ImGui::Spacing (); + +#pragma endregion + #pragma region Section: Keybindings - if (ImGui::CollapsingHeader ("Keybindings###SKIF_SettingsHeader-0", ImGuiTreeNodeFlags_DefaultOpen)) + if (ImGui::CollapsingHeader ("Keybindings###SKIF_SettingsHeader-1", ImGuiTreeNodeFlags_DefaultOpen)) { SKIF_ImGui_Spacing ( ); @@ -123,7 +179,7 @@ SKIF_UI_Tab_DrawSettings (void) #pragma region Section: Image - if (ImGui::CollapsingHeader ("Images###SKIF_SettingsHeader-1", ImGuiTreeNodeFlags_DefaultOpen)) + if (ImGui::CollapsingHeader ("Images###SKIF_SettingsHeader-2", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::PushStyleColor ( ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_SKIF_TextBase) @@ -244,7 +300,7 @@ SKIF_UI_Tab_DrawSettings (void) #pragma region Section: Appearances - if (ImGui::CollapsingHeader ("Appearance###SKIF_SettingsHeader-2", ImGuiTreeNodeFlags_DefaultOpen)) + if (ImGui::CollapsingHeader ("Appearance###SKIF_SettingsHeader-3", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::PushStyleColor ( ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_SKIF_TextBase) @@ -629,7 +685,7 @@ SKIF_UI_Tab_DrawSettings (void) #pragma endregion #pragma region Section: Advanced - if (ImGui::CollapsingHeader ("Advanced###SKIF_SettingsHeader-3", ImGuiTreeNodeFlags_DefaultOpen)) + if (ImGui::CollapsingHeader ("Advanced###SKIF_SettingsHeader-4", ImGuiTreeNodeFlags_DefaultOpen)) { ImGui::PushStyleColor ( ImGuiCol_Text, ImGui::GetStyleColorVec4(ImGuiCol_SKIF_TextBase) From 8b80065b1edd066682ee0d89b1beff461fa91645 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 00:46:33 +0100 Subject: [PATCH 5/9] Add new save functionality + window-based filename with a fallback to the process name if the window has no name... --- include/utility/image.h | 15 ++++- src/SKIV.cpp | 132 ++++++++++++++++++++++++++++++++-------- src/tabs/viewer.cpp | 4 +- src/utility/image.cpp | 73 +++++++++++++++------- 4 files changed, 173 insertions(+), 51 deletions(-) diff --git a/include/utility/image.h b/include/utility/image.h index 0beffdd..46be7f0 100644 --- a/include/utility/image.h +++ b/include/utility/image.h @@ -134,6 +134,17 @@ static const ParamsPQ PQ = #pragma warning( pop ) +struct SKIV_Rect { + ImRect _area; + std::wstring _title; + + SKIV_Rect (ImRect area = ImRect(), std::wstring title = L"") + { + _area = area; + _title = title; + } +}; + // Declarations DirectX::XMVECTOR SKIV_Image_PQToLinear (DirectX::XMVECTOR N, DirectX::XMVECTOR maxPQValue = DirectX::g_XMOne); DirectX::XMVECTOR SKIV_Image_LinearToPQ (DirectX::XMVECTOR N, DirectX::XMVECTOR maxPQValue = DirectX::g_XMOne); @@ -141,11 +152,11 @@ float SKIV_Image_LinearToPQY (float N); DirectX::XMVECTOR SKIV_Image_Rec709toICtCp (DirectX::XMVECTOR N); DirectX::XMVECTOR SKIV_Image_ICtCptoRec709 (DirectX::XMVECTOR N); -bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool snipped, bool isHDR); +bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool isHDR, const wchar_t* wszFileName); // SKIV_Clipboard HRESULT SKIV_Image_SaveToDisk_HDR (const DirectX::Image& image, const wchar_t* wszFileName); HRESULT SKIV_Image_SaveToDisk_SDR (const DirectX::Image& image, const wchar_t* wszFileName, bool force_sRGB); HRESULT SKIV_Image_CaptureDesktop (DirectX::ScratchImage& image, POINT pos, int flags = 0x0); -void SKIV_Image_CaptureRegion (ImRect capture_area); +void SKIV_Image_CaptureRegion (SKIV_Rect capture_area); HRESULT SKIV_Image_TonemapToSDR (const DirectX::Image& image, DirectX::ScratchImage& final_sdr, float mastering_max_nits, float mastering_sdr_nits); bool SKIV_Image_IsUltraHDR (const wchar_t* wszFileName); diff --git a/src/SKIV.cpp b/src/SKIV.cpp index 1227a53..90f6767 100644 --- a/src/SKIV.cpp +++ b/src/SKIV.cpp @@ -79,6 +79,8 @@ #include #include +#include "psapi.h" + const int SKIF_STEAM_APPID = 1157970; bool RecreateSwapChains = false; bool RecreateSwapChainsPending = false; @@ -986,6 +988,15 @@ void SKIF_Initialize (LPWSTR lpCmdLine) FindClose (hFind); } + + // Populate SKIV's default screenshot folder + const std::wstring screenshotsDir = + SKIF_Util_NormalizeFullPath (std::wstring (_path_cache.my_pictures.path) + LR"(\Special K\SKIV\)"); + + wcsncpy_s (_path_cache.skiv_screenshots, MAX_PATH, + screenshotsDir.c_str(), _TRUNCATE); + strncpy_s (_path_cache.skiv_screenshotsA, MAX_PATH, + SK_WideCharToUTF8 (_path_cache.skiv_screenshots).data(), _TRUNCATE); } bool bKeepWindowAlive = true, @@ -1195,6 +1206,36 @@ wWinMain ( _In_ HINSTANCE hInstance, SKIF_Util_RegisterApp (true); } + // Read screenshots folder from registry if populated + if (! _registry.wsPathScreenshots.empty()) + { + if (_registry.wsPathScreenshots.back() != '\\') + _registry.wsPathScreenshots += '\\'; + + wcsncpy_s (_path_cache.skiv_screenshots, MAX_PATH, + _registry.wsPathScreenshots.c_str(), _TRUNCATE); + strncpy_s (_path_cache.skiv_screenshotsA, MAX_PATH, + SK_WideCharToUTF8 (_path_cache.skiv_screenshots).data(), _TRUNCATE); + } + + // Create the folder for our screenshots (or fall back to skiv_temp if we cannot create it) + std::error_code ec; + if (! std::filesystem::exists (_path_cache.skiv_screenshots, ec)) + { + if (! std::filesystem::create_directories (_path_cache.skiv_screenshots, ec)) + { + if (! std::filesystem::exists (_path_cache.skiv_screenshots, ec)) + { + wcsncpy_s (_path_cache.skiv_screenshots, MAX_PATH, + _path_cache.skiv_temp, _TRUNCATE); + strncpy_s (_path_cache.skiv_screenshotsA, MAX_PATH, + SK_WideCharToUTF8 (_path_cache.skiv_screenshots).data(), _TRUNCATE); + } + else + PLOG_INFO << "Created screenshot folder: " << _path_cache.skiv_screenshots; + } + } + PLOG_INFO << "Creating notification icon..."; // Create invisible notify window (for the traybar icon and notification toasts, and for doing D3D11 tests) @@ -2087,7 +2128,7 @@ wWinMain ( _In_ HINSTANCE hInstance, ImRect allowable (SKIV_DesktopImage._desktop_pos, SKIV_DesktopImage._desktop_pos + resolution); - ImRect capture_area; + SKIV_Rect capture_area; bool HDR_Image = SKIV_DesktopImage._hdr_image; bool SKIV_HDR = (HDR_Image ? SKIF_ImGui_IsViewportHDR (SKIF_ImGui_hWnd) : false); @@ -2120,8 +2161,8 @@ wWinMain ( _In_ HINSTANCE hInstance, draw_list->AddRectFilled (allowable.Min, allowable.Max, ImGui::GetColorU32 (IM_COL32 (0, 0, 0, 20))); } - static ImRect selection; - static ImRect selection_auto; + static SKIV_Rect selection = SKIV_Rect (ImRect(), L"SKIV_Snip"); + static SKIV_Rect selection_auto = SKIV_Rect (ImRect(), L"SKIV_Snip"); if (GetForegroundWindow () != SKIF_ImGui_hWnd) SetForegroundWindow ( SKIF_ImGui_hWnd); @@ -2169,8 +2210,8 @@ wWinMain ( _In_ HINSTANCE hInstance, if (SKIV_DesktopImage._rotation == DXGI_MODE_ROTATION_ROTATE90 || SKIV_DesktopImage._rotation == DXGI_MODE_ROTATION_ROTATE270) { - selection_auto.Min = ImVec2 (0.0f, 0.0f); - selection_auto.Max = ImVec2 (0.0f, 0.0f); + selection_auto._area.Min = ImVec2 (0.0f, 0.0f); + selection_auto._area.Max = ImVec2 (0.0f, 0.0f); return; } @@ -2233,10 +2274,10 @@ wWinMain ( _In_ HINSTANCE hInstance, } */ - selection_auto.Min.x = static_cast (rect.left); - selection_auto.Min.y = static_cast (rect.top); - selection_auto.Max.x = static_cast (rect.right); - selection_auto.Max.y = static_cast (rect.bottom); + selection_auto._area.Min.x = static_cast (rect.left); + selection_auto._area.Min.y = static_cast (rect.top); + selection_auto._area.Max.x = static_cast (rect.right); + selection_auto._area.Max.y = static_cast (rect.bottom); /* PLOG_VERBOSE << "----------------------"; @@ -2337,7 +2378,7 @@ wWinMain ( _In_ HINSTANCE hInstance, if (! bHoveringSnipToolbar) { - if (! clicked && SKIF_ImGui_SelectionRect (&selection, allowable, 0, SelectionFlag_Filled)) + if (! clicked && SKIF_ImGui_SelectionRect (&selection._area, allowable, 0, SelectionFlag_Filled)) { _registry._SnippingModeExit = true; capture_area = selection; @@ -2348,7 +2389,7 @@ wWinMain ( _In_ HINSTANCE hInstance, _GetRectBelowCursor ( ); // Keep the selection within the allowed rectangle - selection_auto.ClipWithFull (allowable); + selection_auto._area.ClipWithFull (allowable); if (ImGui::IsMouseClicked (ImGuiMouseButton_Left)) clicked = true; @@ -2360,20 +2401,20 @@ wWinMain ( _In_ HINSTANCE hInstance, capture_area = selection_auto; } - else if (selection_auto.Min != selection_auto.Max) + else if (selection_auto._area.Min != selection_auto._area.Max) { ImDrawList* draw_list = ImGui::GetForegroundDrawList (); - draw_list->AddRect (selection_auto.Min, selection_auto.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,255)), 0.0f, 0, 5.0f); // Border - //draw_list->AddRectFilled (selection_auto.Min, selection_auto.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,50))); // Background + draw_list->AddRect (selection_auto._area.Min, selection_auto._area.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,255)), 0.0f, 0, 5.0f); // Border + //draw_list->AddRectFilled (selection_auto._area.Min, selection_auto._area.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,50))); // Background } } else clicked = false; - if (capture_area.GetArea() != 0) + if (capture_area._area.GetArea() != 0) { ignoredWindows.clear(); @@ -4034,8 +4075,9 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) extern HWND hwndBeforeSnip; hwndBeforeSnip = GetForegroundWindow (); - POINT capture_point = { }; - RECT capture_rect = { }; + POINT capture_point = { }; + RECT capture_rect = { }; + std::wstring filename_base = L""; if (mode == CaptureMode_Window) { @@ -4060,6 +4102,42 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) capture_rect.right = std::min (capture_rect.right, minfo.rcMonitor.right); capture_rect.bottom = std::min (capture_rect.bottom, minfo.rcMonitor.bottom); + + // Window title, if retrievable (limited to 60 characters) + wchar_t buffer[60]; + if (GetWindowTextW (hwndBeforeSnip, buffer, 60) > 0) + { + filename_base = std::wstring(buffer); + } + + // Process name + else { + DWORD dwProcessId = 0; + if (GetWindowThreadProcessId (hwndBeforeSnip, &dwProcessId)) + { + HANDLE hProcess = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId); + + if (hProcess != NULL) + { + wchar_t wszProcessName [MAX_PATH + 2] = { }; + GetProcessImageFileNameW (hProcess, wszProcessName, MAX_PATH); + PathStripPathW (wszProcessName); + + std::wstring wsProcessName = std::wstring(wszProcessName); + + // Strip all null terminator \0 characters from the string + wsProcessName.erase (std::find(wsProcessName.begin(), wsProcessName.end(), '\0'), wsProcessName.end()); + + if (wsProcessName.size() > 0) + { + filename_base = wsProcessName; + } + else { + filename_base = L""; + } + } + } + } } } @@ -4074,6 +4152,9 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { PLOG_VERBOSE << "Capture was successful!"; + // Strip all null terminator \0 characters from the string + filename_base.erase (std::find(filename_base.begin(), filename_base.end(), '\0'), filename_base.end()); + extern HWND hwndTopBeforeSnip; extern bool iconicBeforeSnip; extern bool trayedBeforeSnip; @@ -4082,10 +4163,13 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (mode == CaptureMode_Window) { - const ImRect area = ImRect (static_cast (capture_rect.left ), - static_cast (capture_rect.top ), - static_cast (capture_rect.right ), - static_cast (capture_rect.bottom) + const SKIV_Rect rect = + SKIV_Rect ( + ImRect (static_cast (capture_rect.left ), + static_cast (capture_rect.top ), + static_cast (capture_rect.right ), + static_cast (capture_rect.bottom)), + filename_base ); //PLOG_VERBOSE << "capture_rect.left : " << capture_rect.left; @@ -4093,15 +4177,15 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) //PLOG_VERBOSE << "capture_rect.right : " << capture_rect.right; //PLOG_VERBOSE << "capture_rect.bottom: " << capture_rect.bottom; - SKIV_Image_CaptureRegion (area); + SKIV_Image_CaptureRegion (rect); _registry._SnippingMode = false; } else if (mode == CaptureMode_Screen) { extern skiv_image_desktop_s SKIV_DesktopImage; - const ImRect area = ImRect (ImVec2 (0, 0), SKIV_DesktopImage._resolution); - SKIV_Image_CaptureRegion (area); + const SKIV_Rect rect = SKIV_Rect (ImRect (ImVec2 (0, 0), SKIV_DesktopImage._resolution)); + SKIV_Image_CaptureRegion (rect); _registry._SnippingMode = false; } diff --git a/src/tabs/viewer.cpp b/src/tabs/viewer.cpp index b4febdb..79fc134 100644 --- a/src/tabs/viewer.cpp +++ b/src/tabs/viewer.cpp @@ -2725,7 +2725,7 @@ SKIF_UI_Tab_DrawViewer (void) SUCCEEDED (DirectX::CopyRectangle (*captured_img.GetImages (), src_rect, *subrect.GetImages (), DirectX::TEX_FILTER_DEFAULT, 0, 0))) { - if (SKIV_Image_CopyToClipboard (subrect.GetImages (), true, cover.is_hdr)) + if (SKIV_Image_CopyToClipboard (subrect.GetImages (), cover.is_hdr, L"SKIV_Snip")) { ImGui::InsertNotification ( { @@ -2760,7 +2760,7 @@ SKIF_UI_Tab_DrawViewer (void) else { - if (SKIV_Image_CopyToClipboard (captured_img.GetImages (), false, cover.is_hdr)) + if (SKIV_Image_CopyToClipboard (captured_img.GetImages (), cover.is_hdr, L"SKIV_Clipboard")) { ImGui::InsertNotification ( { diff --git a/src/utility/image.cpp b/src/utility/image.cpp index cc3284c..429532b 100644 --- a/src/utility/image.cpp +++ b/src/utility/image.cpp @@ -1078,7 +1078,7 @@ SKIV_PNG_CopyToClipboard (const DirectX::Image& image, const void *pData, size_t return false; } -bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool snipped, bool isHDR) +bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool isHDR, const wchar_t* wszFileName) { using namespace DirectX; @@ -1087,10 +1087,34 @@ using namespace DirectX; static SKIF_CommonPathsCache& _path_cache = SKIF_CommonPathsCache::GetInstance ( ); - std::wstring wsPNGPath = _path_cache.skiv_temp; - wsPNGPath += snipped ? L"SKIV_Snip" - : L"SKIV_Clipboard"; - wsPNGPath += L".png"; + std::wstring wsPNGPath = _path_cache.skiv_screenshots; + std::wstring wsFilename = std::wstring (wszFileName); + //wsPNGPath += snipped ? L"SKIV_Snip" + // : L"SKIV_Clipboard"; + + wsFilename += L"_"; + + // DateTime + SYSTEMTIME st; + GetLocalTime(&st); + + // Buffers for formatted output + wchar_t dateBuffer[100]; + wchar_t timeBuffer[100]; + + // Get locale-aware date + if (GetDateFormatEx (LOCALE_NAME_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, dateBuffer, 100, NULL)) + wsFilename += std::wstring(dateBuffer); + + wsFilename += L"_"; + + // Get locale-aware time + if (GetTimeFormatEx (LOCALE_NAME_USER_DEFAULT, 0, &st, NULL, timeBuffer, 100)) + wsFilename += std::wstring(timeBuffer); + + wsFilename = SKIF_Util_StripInvalidFilenameChars (wsFilename); + + wsPNGPath += wsFilename + L".png"; PLOG_VERBOSE << wsPNGPath; @@ -1158,6 +1182,9 @@ using namespace DirectX; if (SUCCEEDED (SKIV_Image_TonemapToSDR (*pImage, tonemapped_sdr, SKIV_DesktopImage._max_display_nits, SKIV_DesktopImage._sdr_display_nits))) { pImage = tonemapped_sdr.GetImage (0,0,0); + + if (_registry.bSaveScreenshots && SUCCEEDED (SKIV_Image_SaveToDisk_SDR (*pImage, wsPNGPath.c_str(), false))) + PLOG_INFO << "SKIV_Image_SaveToDisk_SDR ( ): SUCCEEDED!"; } else @@ -3374,11 +3401,11 @@ SKIV_Image_CaptureDesktop (DirectX::ScratchImage& image, POINT point, int flags) } void -SKIV_Image_CaptureRegion (ImRect capture_area) +SKIV_Image_CaptureRegion (SKIV_Rect capture_area) { HMONITOR hMonCaptured = - MonitorFromPoint ({ static_cast (capture_area.Min.x), - static_cast (capture_area.Min.y) }, MONITOR_DEFAULTTONEAREST); + MonitorFromPoint ({ static_cast (capture_area._area.Min.x), + static_cast (capture_area._area.Min.y) }, MONITOR_DEFAULTTONEAREST); MONITORINFO minfo = { .cbSize = sizeof (MONITORINFO) }; GetMonitorInfo (hMonCaptured, &minfo); @@ -3386,11 +3413,11 @@ SKIV_Image_CaptureRegion (ImRect capture_area) // Fixes snipping rectangles on non-primary (origin != 0,0) displays auto _AdjustCaptureAreaRelativeToDisplayOrigin = [&](void) { - capture_area.Min.x -= minfo.rcMonitor.left; - capture_area.Max.x -= minfo.rcMonitor.left; + capture_area._area.Min.x -= minfo.rcMonitor.left; + capture_area._area.Max.x -= minfo.rcMonitor.left; - capture_area.Min.y -= minfo.rcMonitor.top; - capture_area.Max.y -= minfo.rcMonitor.top; + capture_area._area.Min.y -= minfo.rcMonitor.top; + capture_area._area.Max.y -= minfo.rcMonitor.top; }; _AdjustCaptureAreaRelativeToDisplayOrigin (); @@ -3403,18 +3430,18 @@ SKIV_Image_CaptureRegion (ImRect capture_area) width = static_cast (minfo.rcMonitor.bottom - minfo.rcMonitor.top); - std::swap (capture_area.Min.x, capture_area.Min.y); - std::swap (capture_area.Max.x, capture_area.Max.y); + std::swap (capture_area._area.Min.x, capture_area._area.Min.y); + std::swap (capture_area._area.Max.x, capture_area._area.Max.y); const float capture_height = - static_cast (capture_area.Max.y - capture_area.Min.y), + static_cast (capture_area._area.Max.y - capture_area._area.Min.y), capture_width = - static_cast (capture_area.Max.x - capture_area.Min.x); + static_cast (capture_area._area.Max.x - capture_area._area.Min.x); if (SKIV_DesktopImage._rotation == DXGI_MODE_ROTATION_ROTATE90) { - capture_area.Min.y = height - capture_area.Max.y; - capture_area.Max.y = height - capture_area.Max.y + capture_height; + capture_area._area.Min.y = height - capture_area._area.Max.y; + capture_area._area.Max.y = height - capture_area._area.Max.y + capture_height; } else @@ -3427,10 +3454,10 @@ SKIV_Image_CaptureRegion (ImRect capture_area) } const size_t - x = static_cast (std::max (0.0f, capture_area.Min.x)), - y = static_cast (std::max (0.0f, capture_area.Min.y)), - width = static_cast (std::max (0.0f, capture_area.GetWidth ())), - height = static_cast (std::max (0.0f, capture_area.GetHeight ())); + x = static_cast (std::max (0.0f, capture_area._area.Min.x)), + y = static_cast (std::max (0.0f, capture_area._area.Min.y)), + width = static_cast (std::max (0.0f, capture_area._area.GetWidth ())), + height = static_cast (std::max (0.0f, capture_area._area.GetHeight ())); const DirectX::Rect src_rect (x,y, width,height); @@ -3489,7 +3516,7 @@ SKIV_Image_CaptureRegion (ImRect capture_area) PLOG_VERBOSE << "DirectX::FlipRotate ( ): FAILED"; } - if (SKIV_Image_CopyToClipboard (final, true, SKIV_DesktopImage._hdr_image)) + if (SKIV_Image_CopyToClipboard (final, SKIV_DesktopImage._hdr_image, capture_area._title.c_str())) { PLOG_VERBOSE << "SKIV_Image_CopyToClipboard ( ): SUCCEEDED"; From b82997c815b7287f8649bc7b6cc5b5a91cbda165 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 06:11:10 +0100 Subject: [PATCH 6/9] Fixed Display capture mode not having a name --- src/SKIV.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/SKIV.cpp b/src/SKIV.cpp index 90f6767..fa1bfac 100644 --- a/src/SKIV.cpp +++ b/src/SKIV.cpp @@ -2161,8 +2161,8 @@ wWinMain ( _In_ HINSTANCE hInstance, draw_list->AddRectFilled (allowable.Min, allowable.Max, ImGui::GetColorU32 (IM_COL32 (0, 0, 0, 20))); } - static SKIV_Rect selection = SKIV_Rect (ImRect(), L"SKIV_Snip"); - static SKIV_Rect selection_auto = SKIV_Rect (ImRect(), L"SKIV_Snip"); + static SKIV_Rect selection = SKIV_Rect (ImRect(), L"Desktop"); + static SKIV_Rect selection_auto = SKIV_Rect (ImRect(), L"Desktop"); if (GetForegroundWindow () != SKIF_ImGui_hWnd) SetForegroundWindow ( SKIF_ImGui_hWnd); @@ -4077,7 +4077,7 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) POINT capture_point = { }; RECT capture_rect = { }; - std::wstring filename_base = L""; + std::wstring filename_base = L"Display"; if (mode == CaptureMode_Window) { @@ -4184,7 +4184,13 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) else if (mode == CaptureMode_Screen) { extern skiv_image_desktop_s SKIV_DesktopImage; - const SKIV_Rect rect = SKIV_Rect (ImRect (ImVec2 (0, 0), SKIV_DesktopImage._resolution)); + const SKIV_Rect rect = + SKIV_Rect ( + ImRect (ImVec2 (0, 0), + SKIV_DesktopImage._resolution), + L"Display" + ); + SKIV_Image_CaptureRegion (rect); _registry._SnippingMode = false; } From fe8dfdce734f692c80de5bc55069987d1c6c5213 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 06:11:38 +0100 Subject: [PATCH 7/9] Use Desktop instead of SKIV_Snip as the filename --- src/tabs/viewer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tabs/viewer.cpp b/src/tabs/viewer.cpp index 79fc134..7f04f48 100644 --- a/src/tabs/viewer.cpp +++ b/src/tabs/viewer.cpp @@ -2725,7 +2725,7 @@ SKIF_UI_Tab_DrawViewer (void) SUCCEEDED (DirectX::CopyRectangle (*captured_img.GetImages (), src_rect, *subrect.GetImages (), DirectX::TEX_FILTER_DEFAULT, 0, 0))) { - if (SKIV_Image_CopyToClipboard (subrect.GetImages (), cover.is_hdr, L"SKIV_Snip")) + if (SKIV_Image_CopyToClipboard (subrect.GetImages (), cover.is_hdr, L"Desktop")) { ImGui::InsertNotification ( { From 6ca5baff4ea17291e7458c768b16a35446ba2a94 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 06:12:15 +0100 Subject: [PATCH 8/9] Fixed SDR mode not storing the file --- src/utility/image.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/utility/image.cpp b/src/utility/image.cpp index 429532b..5c79268 100644 --- a/src/utility/image.cpp +++ b/src/utility/image.cpp @@ -1180,17 +1180,19 @@ using namespace DirectX; if (snipping_tonemap_mode && isHDR) { if (SUCCEEDED (SKIV_Image_TonemapToSDR (*pImage, tonemapped_sdr, SKIV_DesktopImage._max_display_nits, SKIV_DesktopImage._sdr_display_nits))) - { pImage = tonemapped_sdr.GetImage (0,0,0); - - if (_registry.bSaveScreenshots && SUCCEEDED (SKIV_Image_SaveToDisk_SDR (*pImage, wsPNGPath.c_str(), false))) - PLOG_INFO << "SKIV_Image_SaveToDisk_SDR ( ): SUCCEEDED!"; - } - else PLOG_INFO << "SKIV_Image_TonemapToSDR ( ): FAILED!"; } + if (_registry.bSaveScreenshots) + { + if (SUCCEEDED (SKIV_Image_SaveToDisk_SDR (*pImage, wsPNGPath.c_str(), false))) + PLOG_VERBOSE << "SKIV_Image_SaveToDisk_SDR ( ): SUCCEEDED!"; + else + PLOG_VERBOSE << "SKIF_Image_SaveToDisk_HDR ( ): FAILED"; + } + const int _bpc = (int)(DirectX::BitsPerPixel (pImage->format)), From f9afaaf0ab73384481ad34224191d85aaaafb865 Mon Sep 17 00:00:00 2001 From: Aemony Date: Thu, 19 Mar 2026 18:37:31 +0100 Subject: [PATCH 9/9] Extended wnd title/proc name to all captures Also fixed internal snips/copies not being stored in the temp folder --- include/utility/image.h | 14 ++-- src/SKIV.cpp | 153 ++++++++++++++++++++----------------- src/tabs/viewer.cpp | 11 ++- src/utility/image.cpp | 42 +++++----- src/utility/skif_imgui.cpp | 2 +- 5 files changed, 119 insertions(+), 103 deletions(-) diff --git a/include/utility/image.h b/include/utility/image.h index 46be7f0..06f5c98 100644 --- a/include/utility/image.h +++ b/include/utility/image.h @@ -134,14 +134,14 @@ static const ParamsPQ PQ = #pragma warning( pop ) -struct SKIV_Rect { - ImRect _area; +struct SKIV_Region { + ImRect _rect; std::wstring _title; - SKIV_Rect (ImRect area = ImRect(), std::wstring title = L"") + SKIV_Region (ImRect r_ = ImRect(), std::wstring t_ = L"") { - _area = area; - _title = title; + _rect = r_; + _title = t_; } }; @@ -152,11 +152,11 @@ float SKIV_Image_LinearToPQY (float N); DirectX::XMVECTOR SKIV_Image_Rec709toICtCp (DirectX::XMVECTOR N); DirectX::XMVECTOR SKIV_Image_ICtCptoRec709 (DirectX::XMVECTOR N); -bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool isHDR, const wchar_t* wszFileName); // SKIV_Clipboard +bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool isHDR, bool isTemp, const wchar_t* wszFileName); HRESULT SKIV_Image_SaveToDisk_HDR (const DirectX::Image& image, const wchar_t* wszFileName); HRESULT SKIV_Image_SaveToDisk_SDR (const DirectX::Image& image, const wchar_t* wszFileName, bool force_sRGB); HRESULT SKIV_Image_CaptureDesktop (DirectX::ScratchImage& image, POINT pos, int flags = 0x0); -void SKIV_Image_CaptureRegion (SKIV_Rect capture_area); +void SKIV_Image_CaptureRegion (SKIV_Region capture_area); HRESULT SKIV_Image_TonemapToSDR (const DirectX::Image& image, DirectX::ScratchImage& final_sdr, float mastering_max_nits, float mastering_sdr_nits); bool SKIV_Image_IsUltraHDR (const wchar_t* wszFileName); diff --git a/src/SKIV.cpp b/src/SKIV.cpp index fa1bfac..1b28938 100644 --- a/src/SKIV.cpp +++ b/src/SKIV.cpp @@ -999,6 +999,45 @@ void SKIF_Initialize (LPWSTR lpCmdLine) SK_WideCharToUTF8 (_path_cache.skiv_screenshots).data(), _TRUNCATE); } +static +std::wstring +SKIV_GetBaseFilename (HWND hWnd) +{ + // Limit window title / process name to 60 characters + const size_t len = MAX_PATH + 2; + wchar_t wszFilename [len] = { }; + + // Window title, if retrievable, else process name + if (GetWindowTextW (hWnd, wszFilename, len) == 0) + { + // Process name + DWORD dwProcessId = 0; + if (GetWindowThreadProcessId (hWnd, &dwProcessId)) + { + HANDLE hProcess = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId); + + if (hProcess != NULL) + { + GetProcessImageFileNameW (hProcess, wszFilename, MAX_PATH); + PathStripPathW (wszFilename); + PathRemoveExtensionW (wszFilename); + } + } + } + + std::wstring wsFilename = std::wstring (wszFilename); + + // Strip all null terminator \0 characters from the string + wsFilename.erase (std::find(wsFilename.begin(), wsFilename.end(), '\0'), wsFilename.end()); + + if (wsFilename.size() > 60) + wsFilename = wsFilename.substr(0, 60); + else if (wsFilename.empty()) + wsFilename = L"explorer"; + + return wsFilename; +} + bool bKeepWindowAlive = true, bKeepProcessAlive = true; @@ -2128,7 +2167,7 @@ wWinMain ( _In_ HINSTANCE hInstance, ImRect allowable (SKIV_DesktopImage._desktop_pos, SKIV_DesktopImage._desktop_pos + resolution); - SKIV_Rect capture_area; + SKIV_Region capture_area; bool HDR_Image = SKIV_DesktopImage._hdr_image; bool SKIV_HDR = (HDR_Image ? SKIF_ImGui_IsViewportHDR (SKIF_ImGui_hWnd) : false); @@ -2161,8 +2200,8 @@ wWinMain ( _In_ HINSTANCE hInstance, draw_list->AddRectFilled (allowable.Min, allowable.Max, ImGui::GetColorU32 (IM_COL32 (0, 0, 0, 20))); } - static SKIV_Rect selection = SKIV_Rect (ImRect(), L"Desktop"); - static SKIV_Rect selection_auto = SKIV_Rect (ImRect(), L"Desktop"); + static SKIV_Region selection = SKIV_Region (ImRect(), L"Desktop_Region"); + static SKIV_Region selection_auto = SKIV_Region (ImRect(), L"Desktop_Auto"); if (GetForegroundWindow () != SKIF_ImGui_hWnd) SetForegroundWindow ( SKIF_ImGui_hWnd); @@ -2203,15 +2242,18 @@ wWinMain ( _In_ HINSTANCE hInstance, return false; }; - auto _GetRectBelowCursor = [&](void) -> void + auto _GetRectBelowCursor = [&](SKIV_Region* _region, bool isAutoSelection) -> void { // This feature is unsupported on rotated displays // if (SKIV_DesktopImage._rotation == DXGI_MODE_ROTATION_ROTATE90 || SKIV_DesktopImage._rotation == DXGI_MODE_ROTATION_ROTATE270) { - selection_auto._area.Min = ImVec2 (0.0f, 0.0f); - selection_auto._area.Max = ImVec2 (0.0f, 0.0f); + if (isAutoSelection) + { + _region->_rect.Min = ImVec2 (0.0f, 0.0f); + _region->_rect.Max = ImVec2 (0.0f, 0.0f); + } return; } @@ -2273,11 +2315,16 @@ wWinMain ( _In_ HINSTANCE hInstance, break; } */ + + if (isAutoSelection) + { + _region->_rect.Min.x = static_cast (rect.left); + _region->_rect.Min.y = static_cast (rect.top); + _region->_rect.Max.x = static_cast (rect.right); + _region->_rect.Max.y = static_cast (rect.bottom); + } - selection_auto._area.Min.x = static_cast (rect.left); - selection_auto._area.Min.y = static_cast (rect.top); - selection_auto._area.Max.x = static_cast (rect.right); - selection_auto._area.Max.y = static_cast (rect.bottom); + _region->_title = SKIV_GetBaseFilename (hWnd); /* PLOG_VERBOSE << "----------------------"; @@ -2286,8 +2333,8 @@ wWinMain ( _In_ HINSTANCE hInstance, if (RealGetWindowClassW (top_most, wszRealWindowClass, 64)) PLOG_VERBOSE << "Class: " << wszRealWindowClass; PLOG_VERBOSE << "Pos: " << point.x << "," << point.y; - PLOG_VERBOSE << "Min: " << selection_auto.Min.x << "," << selection_auto.Min.y; - PLOG_VERBOSE << "Max: " << selection_auto.Max.x << "," << selection_auto.Max.y; + PLOG_VERBOSE << "Min: " << _region.Min.x << "," << _region.Min.y; + PLOG_VERBOSE << "Max: " << _region.Max.x << "," << _region.Max.y; */ breakLoop = true; @@ -2378,18 +2425,19 @@ wWinMain ( _In_ HINSTANCE hInstance, if (! bHoveringSnipToolbar) { - if (! clicked && SKIF_ImGui_SelectionRect (&selection._area, allowable, 0, SelectionFlag_Filled)) + if (! clicked && SKIF_ImGui_SelectionRect (&selection._rect, allowable, 0, SelectionFlag_Filled)) { _registry._SnippingModeExit = true; + _GetRectBelowCursor (&selection, false); capture_area = selection; } else if (! ImGui::IsMouseDragging (ImGuiMouseButton_Left)) { - _GetRectBelowCursor ( ); + _GetRectBelowCursor (&selection_auto, true); // Keep the selection within the allowed rectangle - selection_auto._area.ClipWithFull (allowable); + selection_auto._rect.ClipWithFull (allowable); if (ImGui::IsMouseClicked (ImGuiMouseButton_Left)) clicked = true; @@ -2401,20 +2449,20 @@ wWinMain ( _In_ HINSTANCE hInstance, capture_area = selection_auto; } - else if (selection_auto._area.Min != selection_auto._area.Max) + else if (selection_auto._rect.Min != selection_auto._rect.Max) { ImDrawList* draw_list = ImGui::GetForegroundDrawList (); - draw_list->AddRect (selection_auto._area.Min, selection_auto._area.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,255)), 0.0f, 0, 5.0f); // Border - //draw_list->AddRectFilled (selection_auto._area.Min, selection_auto._area.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,50))); // Background + draw_list->AddRect (selection_auto._rect.Min, selection_auto._rect.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,255)), 0.0f, 0, 5.0f); // Border + //draw_list->AddRectFilled (selection_auto._rect.Min, selection_auto._rect.Max, ImGui::GetColorU32 (IM_COL32(0,130,216,50))); // Background } } else clicked = false; - if (capture_area._area.GetArea() != 0) + if (capture_area._rect.GetArea() != 0) { ignoredWindows.clear(); @@ -4077,7 +4125,7 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) POINT capture_point = { }; RECT capture_rect = { }; - std::wstring filename_base = L"Display"; + std::wstring filename = L"Display"; if (mode == CaptureMode_Window) { @@ -4103,46 +4151,16 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) capture_rect.right = std::min (capture_rect.right, minfo.rcMonitor.right); capture_rect.bottom = std::min (capture_rect.bottom, minfo.rcMonitor.bottom); - // Window title, if retrievable (limited to 60 characters) - wchar_t buffer[60]; - if (GetWindowTextW (hwndBeforeSnip, buffer, 60) > 0) - { - filename_base = std::wstring(buffer); - } - - // Process name - else { - DWORD dwProcessId = 0; - if (GetWindowThreadProcessId (hwndBeforeSnip, &dwProcessId)) - { - HANDLE hProcess = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId); - - if (hProcess != NULL) - { - wchar_t wszProcessName [MAX_PATH + 2] = { }; - GetProcessImageFileNameW (hProcess, wszProcessName, MAX_PATH); - PathStripPathW (wszProcessName); - - std::wstring wsProcessName = std::wstring(wszProcessName); - - // Strip all null terminator \0 characters from the string - wsProcessName.erase (std::find(wsProcessName.begin(), wsProcessName.end(), '\0'), wsProcessName.end()); - - if (wsProcessName.size() > 0) - { - filename_base = wsProcessName; - } - else { - filename_base = L""; - } - } - } - } + filename = SKIV_GetBaseFilename (hwndBeforeSnip); } } else + { GetCursorPos (&capture_point); + HWND hWndBelowCursor = WindowFromPoint (capture_point); + filename = SKIV_GetBaseFilename (hWndBelowCursor); + } DirectX::ScratchImage captured_img; HRESULT hr = @@ -4152,24 +4170,21 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { PLOG_VERBOSE << "Capture was successful!"; - // Strip all null terminator \0 characters from the string - filename_base.erase (std::find(filename_base.begin(), filename_base.end(), '\0'), filename_base.end()); - extern HWND hwndTopBeforeSnip; extern bool iconicBeforeSnip; extern bool trayedBeforeSnip; - extern ImRect selection_rect; + //extern ImRect selection_rect; if (mode == CaptureMode_Window) { - const SKIV_Rect rect = - SKIV_Rect ( + const SKIV_Region region = + SKIV_Region ( ImRect (static_cast (capture_rect.left ), static_cast (capture_rect.top ), static_cast (capture_rect.right ), static_cast (capture_rect.bottom)), - filename_base + filename ); //PLOG_VERBOSE << "capture_rect.left : " << capture_rect.left; @@ -4177,21 +4192,21 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) //PLOG_VERBOSE << "capture_rect.right : " << capture_rect.right; //PLOG_VERBOSE << "capture_rect.bottom: " << capture_rect.bottom; - SKIV_Image_CaptureRegion (rect); + SKIV_Image_CaptureRegion (region); _registry._SnippingMode = false; } else if (mode == CaptureMode_Screen) { extern skiv_image_desktop_s SKIV_DesktopImage; - const SKIV_Rect rect = - SKIV_Rect ( + const SKIV_Region region = + SKIV_Region ( ImRect (ImVec2 (0, 0), SKIV_DesktopImage._resolution), - L"Display" + filename ); - SKIV_Image_CaptureRegion (rect); + SKIV_Image_CaptureRegion (region); _registry._SnippingMode = false; } @@ -4220,8 +4235,8 @@ SKIF_WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) SKIF_ImGui_SetFullscreen (SKIF_ImGui_hWnd, true, monitor); UpdateWindow (SKIF_ImGui_hWnd); - selection_rect.Min = ImVec2 (0.0f, 0.0f); - selection_rect.Max = ImVec2 (0.0f, 0.0f); + //selection_rect.Min = ImVec2 (0.0f, 0.0f); + //selection_rect.Max = ImVec2 (0.0f, 0.0f); ImGui::GetIO ().MouseDown [0] = false; ImGui::GetIO ().MouseDownDuration [0] = -1.0f; diff --git a/src/tabs/viewer.cpp b/src/tabs/viewer.cpp index 7f04f48..0ddb5b7 100644 --- a/src/tabs/viewer.cpp +++ b/src/tabs/viewer.cpp @@ -415,7 +415,7 @@ bool iconicBeforeSnip = false; bool trayedBeforeSnip = false; HWND hwndBeforeSnip = 0; HWND hwndTopBeforeSnip = 0; // Window above SKIV in z-order -ImRect selection_rect = { }; +//ImRect selection_rect = { }; bool coverRefresh = false; // This just triggers a refresh of the cover std::wstring coverRefreshPath = L""; @@ -2725,7 +2725,7 @@ SKIF_UI_Tab_DrawViewer (void) SUCCEEDED (DirectX::CopyRectangle (*captured_img.GetImages (), src_rect, *subrect.GetImages (), DirectX::TEX_FILTER_DEFAULT, 0, 0))) { - if (SKIV_Image_CopyToClipboard (subrect.GetImages (), cover.is_hdr, L"Desktop")) + if (SKIV_Image_CopyToClipboard (subrect.GetImages (), cover.is_hdr, true, L"cp_rect")) { ImGui::InsertNotification ( { @@ -2760,7 +2760,7 @@ SKIF_UI_Tab_DrawViewer (void) else { - if (SKIV_Image_CopyToClipboard (captured_img.GetImages (), cover.is_hdr, L"SKIV_Clipboard")) + if (SKIV_Image_CopyToClipboard (captured_img.GetImages (), cover.is_hdr, true, L"cp_full")) { ImGui::InsertNotification ( { @@ -3304,6 +3304,8 @@ SKIF_UI_Tab_DrawViewer (void) ImGui::InsertNotification (toast); } + static ImRect selection_rect = ImRect (); + if ((io.KeyCtrl && SKIF_ImGui_SelectionRect (&selection_rect, image_rect))) { // Flip an inverted rectangle @@ -3337,7 +3339,8 @@ SKIF_UI_Tab_DrawViewer (void) } ); */ - + + selection_rect = ImRect (); // Reset wantCopyToClipboard = true; copyRect = translated; } diff --git a/src/utility/image.cpp b/src/utility/image.cpp index 5c79268..088eaac 100644 --- a/src/utility/image.cpp +++ b/src/utility/image.cpp @@ -1078,7 +1078,7 @@ SKIV_PNG_CopyToClipboard (const DirectX::Image& image, const void *pData, size_t return false; } -bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool isHDR, const wchar_t* wszFileName) +bool SKIV_Image_CopyToClipboard (const DirectX::Image* pImage, bool isHDR, bool isTemp, const wchar_t* wszFileName) { using namespace DirectX; @@ -1087,10 +1087,8 @@ using namespace DirectX; static SKIF_CommonPathsCache& _path_cache = SKIF_CommonPathsCache::GetInstance ( ); - std::wstring wsPNGPath = _path_cache.skiv_screenshots; + std::wstring wsPNGPath = (isTemp) ? _path_cache.skiv_temp : _path_cache.skiv_screenshots; std::wstring wsFilename = std::wstring (wszFileName); - //wsPNGPath += snipped ? L"SKIV_Snip" - // : L"SKIV_Clipboard"; wsFilename += L"_"; @@ -3403,11 +3401,11 @@ SKIV_Image_CaptureDesktop (DirectX::ScratchImage& image, POINT point, int flags) } void -SKIV_Image_CaptureRegion (SKIV_Rect capture_area) +SKIV_Image_CaptureRegion (SKIV_Region capture_area) { HMONITOR hMonCaptured = - MonitorFromPoint ({ static_cast (capture_area._area.Min.x), - static_cast (capture_area._area.Min.y) }, MONITOR_DEFAULTTONEAREST); + MonitorFromPoint ({ static_cast (capture_area._rect.Min.x), + static_cast (capture_area._rect.Min.y) }, MONITOR_DEFAULTTONEAREST); MONITORINFO minfo = { .cbSize = sizeof (MONITORINFO) }; GetMonitorInfo (hMonCaptured, &minfo); @@ -3415,11 +3413,11 @@ SKIV_Image_CaptureRegion (SKIV_Rect capture_area) // Fixes snipping rectangles on non-primary (origin != 0,0) displays auto _AdjustCaptureAreaRelativeToDisplayOrigin = [&](void) { - capture_area._area.Min.x -= minfo.rcMonitor.left; - capture_area._area.Max.x -= minfo.rcMonitor.left; + capture_area._rect.Min.x -= minfo.rcMonitor.left; + capture_area._rect.Max.x -= minfo.rcMonitor.left; - capture_area._area.Min.y -= minfo.rcMonitor.top; - capture_area._area.Max.y -= minfo.rcMonitor.top; + capture_area._rect.Min.y -= minfo.rcMonitor.top; + capture_area._rect.Max.y -= minfo.rcMonitor.top; }; _AdjustCaptureAreaRelativeToDisplayOrigin (); @@ -3432,18 +3430,18 @@ SKIV_Image_CaptureRegion (SKIV_Rect capture_area) width = static_cast (minfo.rcMonitor.bottom - minfo.rcMonitor.top); - std::swap (capture_area._area.Min.x, capture_area._area.Min.y); - std::swap (capture_area._area.Max.x, capture_area._area.Max.y); + std::swap (capture_area._rect.Min.x, capture_area._rect.Min.y); + std::swap (capture_area._rect.Max.x, capture_area._rect.Max.y); const float capture_height = - static_cast (capture_area._area.Max.y - capture_area._area.Min.y), + static_cast (capture_area._rect.Max.y - capture_area._rect.Min.y), capture_width = - static_cast (capture_area._area.Max.x - capture_area._area.Min.x); + static_cast (capture_area._rect.Max.x - capture_area._rect.Min.x); if (SKIV_DesktopImage._rotation == DXGI_MODE_ROTATION_ROTATE90) { - capture_area._area.Min.y = height - capture_area._area.Max.y; - capture_area._area.Max.y = height - capture_area._area.Max.y + capture_height; + capture_area._rect.Min.y = height - capture_area._rect.Max.y; + capture_area._rect.Max.y = height - capture_area._rect.Max.y + capture_height; } else @@ -3456,10 +3454,10 @@ SKIV_Image_CaptureRegion (SKIV_Rect capture_area) } const size_t - x = static_cast (std::max (0.0f, capture_area._area.Min.x)), - y = static_cast (std::max (0.0f, capture_area._area.Min.y)), - width = static_cast (std::max (0.0f, capture_area._area.GetWidth ())), - height = static_cast (std::max (0.0f, capture_area._area.GetHeight ())); + x = static_cast (std::max (0.0f, capture_area._rect.Min.x)), + y = static_cast (std::max (0.0f, capture_area._rect.Min.y)), + width = static_cast (std::max (0.0f, capture_area._rect.GetWidth ())), + height = static_cast (std::max (0.0f, capture_area._rect.GetHeight ())); const DirectX::Rect src_rect (x,y, width,height); @@ -3518,7 +3516,7 @@ SKIV_Image_CaptureRegion (SKIV_Rect capture_area) PLOG_VERBOSE << "DirectX::FlipRotate ( ): FAILED"; } - if (SKIV_Image_CopyToClipboard (final, SKIV_DesktopImage._hdr_image, capture_area._title.c_str())) + if (SKIV_Image_CopyToClipboard (final, SKIV_DesktopImage._hdr_image, false, capture_area._title.c_str())) { PLOG_VERBOSE << "SKIV_Image_CopyToClipboard ( ): SUCCEEDED"; diff --git a/src/utility/skif_imgui.cpp b/src/utility/skif_imgui.cpp index 5767e32..90bd62e 100644 --- a/src/utility/skif_imgui.cpp +++ b/src/utility/skif_imgui.cpp @@ -524,7 +524,7 @@ SKIF_ImGui_SelectionRect (ImRect* selection, ImDrawList* draw_list = ImGui::GetForegroundDrawList (); - draw_list->AddRect (selection->Min-inset, selection->Max+inset, ImGui::GetColorU32 (IM_COL32(0,130,216,255)), 0.0f, 0, 5.0f); // Border + draw_list->AddRect (selection->Min-inset, selection->Max+inset, ImGui::GetColorU32 (IM_COL32(0,130,216,255)), 0.0f, 0, 5.0f); // Border if (flags & SelectionFlag_Filled) draw_list->AddRectFilled (selection->Min, selection->Max, ImGui::GetColorU32 (IM_COL32(0,130,216,50))); // Background