diff options
author | John Ankarström <john@ankarstrom.se> | 2022-07-29 15:31:26 +0200 |
---|---|---|
committer | John Ankarström <john@ankarstrom.se> | 2022-07-29 15:31:26 +0200 |
commit | c883d9cf5673fe0af8d69120b048d642e122bdbb (patch) | |
tree | e657e8375be9e881492bc05b15b036ed633a7765 /c | |
parent | a67d7ca9e69799728801e30eff6af1adc7d2e53b (diff) | |
download | EpisodeBrowser-c883d9cf5673fe0af8d69120b048d642e122bdbb.tar.gz |
Use swprintf_s instead of string streams.
I find it much simpler. It is very safe, as wszf only accepts
fixed-size arrays. There is, of course, the chance that swprintf_s
fails and writes nothing into the array. This can be handled by the
caller, if desired.
Diffstat (limited to 'c')
-rw-r--r-- | c/common.h | 8 | ||||
-rw-r--r-- | c/main.cpp | 30 |
2 files changed, 23 insertions, 15 deletions
@@ -42,6 +42,12 @@ T* Library::GetProcAddress(const char* const szProc) return (T*)(void*)::GetProcAddress(m_hModule, szProc); } +template<size_t N, typename... T> +inline auto wszf(wchar_t (&wsz)[N], const wchar_t* wszFmt, T... xs) +{ + return swprintf_s(wsz, N, wszFmt, xs...); +} + /* Create and return an object of type C. If construction fails, * return nothing. The returned value must be checked before being * used, as dereferencing is undefined if the value is empty. */ @@ -57,7 +63,7 @@ std::optional<T> maybe_make(U... xs) /* Variable template for caching values from GetSystemMetrics. */ template <int I> -const auto Metric = GetSystemMetrics(I); +auto Metric = GetSystemMetrics(I); /* Check result of Windows API call, throwing error on NULL. */ template <typename T> @@ -1,5 +1,4 @@ #include <exception> -#include <sstream> #include <windows.h> #include <commctrl.h> #include <uxtheme.h> @@ -47,14 +46,12 @@ static void UpdateTheme(); void TerminateMsg(const wchar_t* wsz1, const wchar_t* wsz2) noexcept { - std::wstringstream wss; - wss << L"Episode Browser was terminated due to "; - wss << wsz1; + wchar_t wsz[256] = {0}; if (wsz2) - wss << ": " << wsz2; + wszf(wsz, L"Episode Browser was terminated due to %s: %s.", wsz1, wsz2); else - wss << "."; - MessageBox(g_hWnd, wss.str().c_str(), L"Fatal Error", MB_ICONERROR); + wszf(wsz, L"Episode Browser was terminated due to %s.", wsz1); + MessageBox(g_hWnd, wsz, L"Fatal Error", MB_ICONERROR); } void OnTerminate() noexcept @@ -240,7 +237,11 @@ LRESULT CALLBACK WndProc(const HWND hWnd, const UINT uMsg, const WPARAM wParam, case 0x02E0: /* WM_DPICHANGED */ { const RECT* const lpr = (RECT*)lParam; + + /* Update DPI and cached metrics. */ g_iDPI = HIWORD(wParam); + Metric<SM_CXVSCROLL> = GetSystemMetrics(SM_CXVSCROLL); + prefer(SetWindowPos(hWnd, (HWND)NULL, lpr->left, lpr->top, lpr->right-lpr->left, @@ -455,9 +456,9 @@ void WndProcContextMenu(const HWND, unsigned short wCommand) EBMessageBox(L"Episode could not be opened locally.", L"Error", MB_ICONWARNING); } else if (cNotFound) { - std::wstringstream wss; - wss << cNotFound << L" episodes could not be opened locally."; - EBMessageBox(wss.str().c_str(), L"Error", MB_ICONWARNING); + wchar_t wsz[64] = {0}; + wszf(wsz, L"%d episodes could not be opened locally.", cNotFound); + EBMessageBox(wsz, L"Error", MB_ICONWARNING); } else if (ID_SUBGROUP(wCommand) == IDG_CTX_RATE) { g_pElv->Sort(); g_pElv->ShowFocus(); @@ -473,10 +474,11 @@ void WaitFor(const char* szMod, const char* szPred) static std::wstring wsPred; if (bActive) { - std::wstringstream wss; - wss << L"Another task (" << wsPred.c_str() << ") is active. " - << "Do you want to cancel the existing task and start a new one?"; - if (EBMessageBox(wss.str().c_str(), L"Error", MB_YESNO|MB_ICONWARNING) != IDYES) + wchar_t wsz[128] = {0}; + wszf(wsz, L"Another task (%s) is active. " + L"Do you want to cancel the existing task and start a new one?", + wsPred.c_str()); + if (EBMessageBox(wsz, L"Error", MB_YESNO|MB_ICONWARNING) != IDYES) return; KillTimer(NULL, iTimer); bActive = 0; |